Fix authoritative secondary replication (TSIG transfer + stable primary)
Secondaries never replicated any member zone: the master's catalog zone
requires key-authenticated AXFR (allow-transfer { key "transfer-key"; }),
but the rendered secondary config transferred without presenting the key,
so every catalog transfer was REFUSED and no member zones provisioned.
Two further gaps compounded it: member zones had no allow-transfer at all,
and secondaries pointed at the primary's pod IP, which dies on restart.
- Render the catalog transfer key into the secondary catalog-zones
default-primaries and the secondary catalog zone primaries, so
key-authenticated AXFR from the primary is accepted.
- Add allow-transfer { key "<transfer-key>"; } to catalog member primary
zones (when the zone does not set an explicit allow-transfer), so
secondaries can pull them; applied to existing zones via modzone.
- Point secondaries at the stable primary Service ClusterIP instead of the
primary pod IP, so replication survives primary pod restarts (falls back
to the pod IP when no primary Service exists).
This commit is contained in:
+30
-8
@@ -230,15 +230,40 @@ func responsePolicyClause(policies []bindv1alpha1.BindPolicy, indent string) str
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// transferPrimaries returns the primaries list secondaries use to AXFR the
|
||||
// catalog (and, by inheritance, its member zones), each annotated with the
|
||||
// catalog transfer TSIG key. The primary requires key-authenticated transfers
|
||||
// (allow-transfer { key ... }), so an unkeyed primaries list is REFUSED.
|
||||
func transferPrimaries(in RenderInput) []string {
|
||||
primaries := in.Catalog.Spec.DefaultPrimaries
|
||||
if len(primaries) == 0 && in.PrimaryAddress != "" {
|
||||
primaries = []string{in.PrimaryAddress}
|
||||
}
|
||||
key := in.Catalog.Spec.TransferKeyRef
|
||||
if key == "" {
|
||||
return primaries
|
||||
}
|
||||
out := make([]string, 0, len(primaries))
|
||||
for _, p := range primaries {
|
||||
p = strings.TrimSpace(strings.TrimRight(p, ";"))
|
||||
if p == "" {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(p, " key ") {
|
||||
out = append(out, p)
|
||||
} else {
|
||||
out = append(out, fmt.Sprintf("%s key \"%s\"", p, key))
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func catalogZonesClause(in RenderInput, isPrimary bool, indent string) string {
|
||||
// Only secondaries consume the catalog to auto-provision member zones.
|
||||
if in.Catalog == nil || isPrimary {
|
||||
return ""
|
||||
}
|
||||
primaries := in.Catalog.Spec.DefaultPrimaries
|
||||
if len(primaries) == 0 && in.PrimaryAddress != "" {
|
||||
primaries = []string{in.PrimaryAddress}
|
||||
}
|
||||
primaries := transferPrimaries(in)
|
||||
if len(primaries) == 0 {
|
||||
return ""
|
||||
}
|
||||
@@ -259,10 +284,7 @@ func renderCatalogZoneDecl(in RenderInput, isPrimary bool, indent string) string
|
||||
}
|
||||
cat := in.Catalog
|
||||
file := CatalogFilePath(cat.Spec.ZoneName)
|
||||
primaries := cat.Spec.DefaultPrimaries
|
||||
if len(primaries) == 0 && in.PrimaryAddress != "" {
|
||||
primaries = []string{in.PrimaryAddress}
|
||||
}
|
||||
primaries := transferPrimaries(in)
|
||||
if len(primaries) == 0 {
|
||||
// Primary IP not known yet; omit the secondary catalog zone rather than
|
||||
// emit an invalid empty primaries list. A Pod-triggered reconcile renders
|
||||
|
||||
@@ -80,6 +80,24 @@ func TestRenderCatalogUsesPrimaryIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderCatalogPrimariesCarryTransferKey(t *testing.T) {
|
||||
// When the catalog declares a transfer key, secondaries must present it in
|
||||
// both the catalog-zones default-primaries and the secondary catalog zone,
|
||||
// or the key-authenticated primary REFUSES the AXFR.
|
||||
in := RenderInput{
|
||||
Cluster: newCluster(bindv1alpha1.ModeAuthoritative),
|
||||
Catalog: &bindv1alpha1.BindCatalogZone{Spec: bindv1alpha1.BindCatalogZoneSpec{ZoneName: "catalog.internal", TransferKeyRef: "transfer-key"}},
|
||||
PrimaryAddress: "10.43.0.5",
|
||||
}
|
||||
_, secondary := RenderNamedConf(in)
|
||||
if !strings.Contains(secondary, `default-primaries { 10.43.0.5 key "transfer-key"; }`) {
|
||||
t.Fatalf("catalog-zones default-primaries must carry the transfer key:\n%s", secondary)
|
||||
}
|
||||
if !strings.Contains(secondary, `primaries { 10.43.0.5 key "transfer-key"; }`) {
|
||||
t.Fatalf("secondary catalog zone primaries must carry the transfer key:\n%s", secondary)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderForwardZoneInView(t *testing.T) {
|
||||
rec := true
|
||||
in := RenderInput{
|
||||
|
||||
Reference in New Issue
Block a user