gate

package
v0.64.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package gate implements pre-apply DNS policy enforcement. Operators configure a TXT policy at `_workflow-dns-policy.<zone>` declaring which owners may upsert which (name, type) tuples; the Gate reads that policy at apply time and denies actions that the policy does not permit.

Relocated from workflow-plugin-infra/internal/dnsgate. Adapted to dispatch via interfaces.ResourceDriver.Read (not dnspolicy.Adapter) so the same gate logic works against any DNS provider that implements the strict-contract ResourceDriver interface — not just providers carrying the legacy libdns surface.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Gate

func Gate(ctx context.Context, reader policy.DNSPolicyReader, zone, name, recordType, owner string) error

Gate is the uncached entry point (one GetTXT per call). Use this for one-off invocations (CLI commands, integration tests). For step handlers or apply loops processing many records in one go, use NewCachingGate + Check so the policy TXT is read at most once per zone.

func PolicyName

func PolicyName(zone string) string

PolicyName returns the TXT name where policy lives for a zone — the same convention enforced by the parser side (workflow/dns/policy.Parse expects records named `_workflow-dns-policy.<zone>`).

Types

type CachingGate

type CachingGate struct {
	// contains filtered or unexported fields
}

CachingGate is a Gate-call wrapper with per-zone caching. One per wfctl apply invocation; releases at end of invocation (no TTL). Use this when an apply touches multiple records under the same zone — the dns-policy TXT is fetched + parsed exactly once per zone instead of once per record. Mirrors the v1 dnsgate.CachingGate pattern.

func NewCachingGate

func NewCachingGate() *CachingGate

NewCachingGate returns a new CachingGate.

func (*CachingGate) Check

func (g *CachingGate) Check(ctx context.Context, reader policy.DNSPolicyReader, zone, name, recordType, owner string) error

Check is the cached entry point — single GetTXT per zone per Gate. Returns nil when (zone, name, recordType, owner) is permitted; non-nil when the policy denies the action. Fails closed: a missing policy TXT (zero policy entries after parse) returns an error rather than allowing.

Reader is the policy.DNSPolicyReader interface — either a libdns adapter (legacy) or a *DriverReader (wfctl-driven, this package). The narrow 2-method interface means new transports can be added without touching the gate logic.

type DriverReader

type DriverReader struct {
	// Driver is the resolved ResourceDriver for resource type "infra.dns".
	// Caller is responsible for getting the right driver (via
	// IaCProvider.ResourceDriver("infra.dns")) before constructing the
	// reader — keeps this adapter's concerns narrow.
	Driver interfaces.ResourceDriver
	// Zone is the FQDN of the zone whose policy is being read. Used as
	// ResourceRef.ProviderID — the DNS provider plugins (DO, CF, NC,
	// Hover) all accept zone-name-as-ID for the infra.dns resource type.
	Zone string
}

DriverReader adapts an interfaces.ResourceDriver to the full policy.DNSPolicyReader interface so the Gate can read TXT records AND the dns-policy mutating commands (set / transfer-ownership) can write them — all via the strict-contract driver path (no libdns dependency).

GetTXT scans Outputs["records"] for TXT records matching the given name. UpsertTXT issues a Driver.Update against a synthesized ResourceSpec whose records list replaces all TXT entries at the target name. Both halves are scoped narrowly to the policy-TXT use case; the general DNS-record CRUD surface is `wfctl infra apply`.

func (*DriverReader) GetTXT

func (r *DriverReader) GetTXT(ctx context.Context, name string) ([]string, error)

GetTXT implements policy.DNSPolicyReader. Reads the zone via Driver.Read, then scans Outputs["records"] for TXT records whose name matches the requested policy name. Returns an empty (nil) slice when the zone has no matching TXT records — the caller (Gate.Check) handles the "no policy" case by failing closed.

Tolerates both `[]map[string]any` and `[]any` (with element-wise type-assertion) for the Outputs["records"] entry — different provider plugins surface the records slice with slightly different concrete types depending on whether the value passed through a structpb roundtrip or stayed Go-native within the same process. Either shape works.

func (*DriverReader) UpsertTXT

func (r *DriverReader) UpsertTXT(ctx context.Context, name string, values []string, ttl int) error

UpsertTXT implements the write half of policy.DNSPolicyReader so DriverReader satisfies the full interface used by the wfctl dns-policy mutating commands AND can be passed to CachingGate.Check (which takes a DNSPolicyReader, not a narrower Reader sub-interface).

Strategy: Read the current zone via Driver.Read, rewrite the records slice replacing all TXT entries at `name` with the supplied values (one TXT RR per value), then call Driver.Update with a synthesized ResourceSpec carrying the new records list.

Limitations: the synthesized ResourceSpec carries only `domain` + `records` fields. Providers requiring additional zone-level config on Update (e.g. CF "type" / "settings") may reject. The narrow scope is intentional — this adapter exists to manage the policy TXT specifically, not to be a general DNS-record CRUD surface (the `wfctl infra apply` path covers general record CRUD via config-declared records).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL