// Package kubesource turns fancy-dns custom resources (DNSZone, ClientGroup, // BlockList) into the runtime's own configuration types. It is read-only: the // runtime watches the cluster and never writes to it. // // Objects are decoded from unstructured data into the plain structs below, so // there is no generated clientset or deepcopy code to keep in step with the // CRD manifests in deploy/k8s/crds. package kubesource import ( "k8s.io/apimachinery/pkg/runtime/schema" "git.k8s-git-k6n.net/mats/fancy-dns/internal/config" ) // APIGroup and Version name the custom resources. const ( APIGroup = "fancydns.k6n.net" Version = "v1alpha1" ) // The resources the runtime watches. var ( ZoneGVR = schema.GroupVersionResource{Group: APIGroup, Version: Version, Resource: "dnszones"} GroupGVR = schema.GroupVersionResource{Group: APIGroup, Version: Version, Resource: "clientgroups"} ListGVR = schema.GroupVersionResource{Group: APIGroup, Version: Version, Resource: "blocklists"} OverrideGVR = schema.GroupVersionResource{Group: APIGroup, Version: Version, Resource: "addressoverrides"} RuleGVR = schema.GroupVersionResource{Group: APIGroup, Version: Version, Resource: "domainrules"} allGVRs = []schema.GroupVersionResource{ZoneGVR, GroupGVR, ListGVR, OverrideGVR, RuleGVR} ) // DNSZoneSpec declares one authoritative zone. The zone's name is spec.zone, // not metadata.name, because a DNS name is not always a legal object name. type DNSZoneSpec struct { Zone string `json:"zone"` // TTL is the zone's $TTL and SOA minimum; 0 means the writer's default. TTL uint32 `json:"ttl,omitempty"` // SOA is the SOA rdata ("ns1.example.com. hostmaster.example.com. ..."), // or empty to synthesise one from the first apex NS record. SOA string `json:"soa,omitempty"` Records []ZoneRecord `json:"records,omitempty"` } // ZoneRecord is one resource record. Value is presentation-format RDATA. type ZoneRecord struct { Name string `json:"name"` Type string `json:"type"` TTL uint32 `json:"ttl,omitempty"` Value string `json:"value"` } // ClientGroupSpec mirrors config.Group. The group's name is metadata.name. // Groups are evaluated first-match-wins, so Priority orders them: lower runs // first, ties break on name. type ClientGroupSpec struct { Priority int32 `json:"priority,omitempty"` Comment string `json:"comment,omitempty"` Match config.Match `json:"match"` Policy string `json:"policy"` AllowDomains []string `json:"allow_domains,omitempty"` DenyDomains []string `json:"deny_domains,omitempty"` SkipBlocklist bool `json:"skip_blocklist,omitempty"` SkipCache bool `json:"skip_cache,omitempty"` RateLimit int `json:"rate_limit,omitempty"` MaxConcurrent int `json:"max_concurrent,omitempty"` LogQueries bool `json:"log_queries,omitempty"` Upstreams []string `json:"upstreams,omitempty"` } // BlockListSpec mirrors config.ListSource for a remote list. There is no path // field on purpose: a namespace-scoped object must not be able to name a file // the runtime reads or writes. file:// URLs are refused for the same reason. type BlockListSpec struct { URL string `json:"url"` Format string `json:"format,omitempty"` Mirror []string `json:"mirror,omitempty"` Disabled bool `json:"disabled,omitempty"` Refresh string `json:"refresh,omitempty"` Timeout string `json:"timeout,omitempty"` MaxBytes int64 `json:"max_bytes,omitempty"` Categories []string `json:"categories,omitempty"` Comment string `json:"comment,omitempty"` InsecureSkipTLSVerify bool `json:"insecure_skip_tls_verify,omitempty"` } // AddressOverrideSpec answers a name, and everything under it, with fixed // addresses instead of asking upstream: "tornberg.me -> 10.10.3.10" for split // horizon DNS. It is what an RPZ "name A address" line does, one object per // name. type AddressOverrideSpec struct { Domain string `json:"domain"` // Addresses are IPv4 and IPv6 literals; each becomes an A or AAAA answer. Addresses []string `json:"addresses"` } // DomainRuleSpec is an inline allow or block rule list, the objects behind the // console's Domains page. A name may carry a wildcard prefix: "*.example.com" // is the subdomains, "**.example.com" the name and its subdomains. type DomainRuleSpec struct { // Action is "block" or "allow". An allow rule rescues a name that any // blocklist would block. Action string `json:"action"` Names []string `json:"names"` Comment string `json:"comment,omitempty"` }