Skip to content

Commit 885ba0a

Browse files
dilyevskyclaude
andcommitted
[api] restore DKIM, SPF, DMARC, DS, DNSKEY in v1alpha3 Domain DNS types
Reverts 3eeae11 and adds documentation explaining what each type actually represents: DKIM/SPF/DMARC are TXT records under specific naming conventions, DS/DNSKEY are DNSSEC types. Keeping them as distinct fields improves UX via format validation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3b01de5 commit 885ba0a

File tree

5 files changed

+628
-1
lines changed

5 files changed

+628
-1
lines changed

api/core/v1alpha/domain_conversion.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ func convertDomainTargetDNSToV1Alpha3(in *DomainTargetDNS) *v1alpha3.DomainTarge
9090
TTL: in.TTL,
9191
}
9292
}
93+
if len(in.DKIM) > 0 {
94+
out.DKIM = &v1alpha3.DNSDKIMRecords{
95+
Values: in.DKIM,
96+
TTL: in.TTL,
97+
}
98+
}
99+
if len(in.SPF) > 0 {
100+
out.SPF = &v1alpha3.DNSSPFRecords{
101+
Values: in.SPF,
102+
TTL: in.TTL,
103+
}
104+
}
105+
if len(in.DMARC) > 0 {
106+
out.DMARC = &v1alpha3.DNSDMARCRecords{
107+
Values: in.DMARC,
108+
TTL: in.TTL,
109+
}
110+
}
93111
if len(in.CAA) > 0 {
94112
out.CAA = &v1alpha3.DNSCAARecords{
95113
Values: in.CAA,
@@ -108,6 +126,19 @@ func convertDomainTargetDNSToV1Alpha3(in *DomainTargetDNS) *v1alpha3.DomainTarge
108126
TTL: in.TTL,
109127
}
110128
}
129+
if len(in.DS) > 0 {
130+
out.DS = &v1alpha3.DNSDSRecords{
131+
Values: in.DS,
132+
TTL: in.TTL,
133+
}
134+
}
135+
if len(in.DNSKEY) > 0 {
136+
out.DNSKEY = &v1alpha3.DNSDNSKEYRecords{
137+
Values: in.DNSKEY,
138+
TTL: in.TTL,
139+
}
140+
}
141+
111142
return out
112143
}
113144

@@ -144,6 +175,24 @@ func convertDomainTargetDNSFromV1Alpha3(in *v1alpha3.DomainTargetDNS) *DomainTar
144175
firstTTL = in.MX.TTL
145176
}
146177
}
178+
if in.DKIM != nil {
179+
out.DKIM = in.DKIM.Values
180+
if firstTTL == nil {
181+
firstTTL = in.DKIM.TTL
182+
}
183+
}
184+
if in.SPF != nil {
185+
out.SPF = in.SPF.Values
186+
if firstTTL == nil {
187+
firstTTL = in.SPF.TTL
188+
}
189+
}
190+
if in.DMARC != nil {
191+
out.DMARC = in.DMARC.Values
192+
if firstTTL == nil {
193+
firstTTL = in.DMARC.TTL
194+
}
195+
}
147196
if in.CAA != nil {
148197
out.CAA = in.CAA.Values
149198
if firstTTL == nil {
@@ -162,6 +211,19 @@ func convertDomainTargetDNSFromV1Alpha3(in *v1alpha3.DomainTargetDNS) *DomainTar
162211
firstTTL = in.NS.TTL
163212
}
164213
}
214+
if in.DS != nil {
215+
out.DS = in.DS.Values
216+
if firstTTL == nil {
217+
firstTTL = in.DS.TTL
218+
}
219+
}
220+
if in.DNSKEY != nil {
221+
out.DNSKEY = in.DNSKEY.Values
222+
if firstTTL == nil {
223+
firstTTL = in.DNSKEY.TTL
224+
}
225+
}
226+
165227
out.TTL = firstTTL
166228
return out
167229
}

api/core/v1alpha2/domain_conversion.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,24 @@ func convertDomainTargetDNSToV1Alpha3(in *DomainTargetDNS, target *DomainTargetS
9595
TTL: in.TTL,
9696
}
9797
}
98+
if len(in.DKIM) > 0 {
99+
out.DKIM = &v1alpha3.DNSDKIMRecords{
100+
Values: in.DKIM,
101+
TTL: in.TTL,
102+
}
103+
}
104+
if len(in.SPF) > 0 {
105+
out.SPF = &v1alpha3.DNSSPFRecords{
106+
Values: in.SPF,
107+
TTL: in.TTL,
108+
}
109+
}
110+
if len(in.DMARC) > 0 {
111+
out.DMARC = &v1alpha3.DNSDMARCRecords{
112+
Values: in.DMARC,
113+
TTL: in.TTL,
114+
}
115+
}
98116
if len(in.CAA) > 0 {
99117
out.CAA = &v1alpha3.DNSCAARecords{
100118
Values: in.CAA,
@@ -113,6 +131,19 @@ func convertDomainTargetDNSToV1Alpha3(in *DomainTargetDNS, target *DomainTargetS
113131
TTL: in.TTL,
114132
}
115133
}
134+
if len(in.DS) > 0 {
135+
out.DS = &v1alpha3.DNSDSRecords{
136+
Values: in.DS,
137+
TTL: in.TTL,
138+
}
139+
}
140+
if len(in.DNSKEY) > 0 {
141+
out.DNSKEY = &v1alpha3.DNSDNSKEYRecords{
142+
Values: in.DNSKEY,
143+
TTL: in.TTL,
144+
}
145+
}
146+
116147
return out
117148
}
118149

@@ -152,6 +183,24 @@ func convertDomainTargetDNSFromV1Alpha3(in *v1alpha3.DomainTargetDNS) *DomainTar
152183
firstTTL = in.MX.TTL
153184
}
154185
}
186+
if in.DKIM != nil {
187+
out.DKIM = in.DKIM.Values
188+
if firstTTL == nil {
189+
firstTTL = in.DKIM.TTL
190+
}
191+
}
192+
if in.SPF != nil {
193+
out.SPF = in.SPF.Values
194+
if firstTTL == nil {
195+
firstTTL = in.SPF.TTL
196+
}
197+
}
198+
if in.DMARC != nil {
199+
out.DMARC = in.DMARC.Values
200+
if firstTTL == nil {
201+
firstTTL = in.DMARC.TTL
202+
}
203+
}
155204
if in.CAA != nil {
156205
out.CAA = in.CAA.Values
157206
if firstTTL == nil {
@@ -170,6 +219,19 @@ func convertDomainTargetDNSFromV1Alpha3(in *v1alpha3.DomainTargetDNS) *DomainTar
170219
firstTTL = in.NS.TTL
171220
}
172221
}
222+
if in.DS != nil {
223+
out.DS = in.DS.Values
224+
if firstTTL == nil {
225+
firstTTL = in.DS.TTL
226+
}
227+
}
228+
if in.DNSKEY != nil {
229+
out.DNSKEY = in.DNSKEY.Values
230+
if firstTTL == nil {
231+
firstTTL = in.DNSKEY.TTL
232+
}
233+
}
234+
173235
out.TTL = firstTTL
174236
return out
175237
}

api/core/v1alpha3/domain_types.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,50 @@ type DNSMXRecords struct {
137137
TTL *int32 `json:"ttl,omitempty"`
138138
}
139139

140+
// DNSDKIMRecords holds DKIM (DomainKeys Identified Mail) values with an optional per-record TTL.
141+
// Stored as TXT records under <selector>._domainkey.<domain>.
142+
// Values should be DKIM public key records (e.g. "v=DKIM1; k=rsa; p=...").
143+
type DNSDKIMRecords struct {
144+
// Values is the list of DKIM record values.
145+
// +kubebuilder:validation:MinItems=1
146+
Values []string `json:"values"`
147+
148+
// TTL is the time-to-live for this record type.
149+
// +kubebuilder:validation:Minimum=0
150+
// +kubebuilder:validation:Maximum=3600
151+
// +optional
152+
TTL *int32 `json:"ttl,omitempty"`
153+
}
154+
155+
// DNSSPFRecords holds SPF (Sender Policy Framework) values with an optional per-record TTL.
156+
// Stored as TXT records. Values should follow SPF syntax (e.g. "v=spf1 include:_spf.google.com ~all").
157+
type DNSSPFRecords struct {
158+
// Values is the list of SPF record values.
159+
// +kubebuilder:validation:MinItems=1
160+
Values []string `json:"values"`
161+
162+
// TTL is the time-to-live for this record type.
163+
// +kubebuilder:validation:Minimum=0
164+
// +kubebuilder:validation:Maximum=3600
165+
// +optional
166+
TTL *int32 `json:"ttl,omitempty"`
167+
}
168+
169+
// DNSDMARCRecords holds DMARC (Domain-based Message Authentication, Reporting & Conformance) values
170+
// with an optional per-record TTL. Stored as TXT records under _dmarc.<domain>.
171+
// Values should follow DMARC syntax (e.g. "v=DMARC1; p=reject; rua=mailto:...").
172+
type DNSDMARCRecords struct {
173+
// Values is the list of DMARC record values.
174+
// +kubebuilder:validation:MinItems=1
175+
Values []string `json:"values"`
176+
177+
// TTL is the time-to-live for this record type.
178+
// +kubebuilder:validation:Minimum=0
179+
// +kubebuilder:validation:Maximum=3600
180+
// +optional
181+
TTL *int32 `json:"ttl,omitempty"`
182+
}
183+
140184
// DNSCAARecords holds CAA record values with an optional per-record TTL.
141185
type DNSCAARecords struct {
142186
// Values is the list of CAA record values.
@@ -176,6 +220,34 @@ type DNSNSRecords struct {
176220
TTL *int32 `json:"ttl,omitempty"`
177221
}
178222

223+
// DNSDSRecords holds DS (Delegation Signer) records for DNSSEC chain of trust,
224+
// with an optional per-record TTL. Values should be DS record data (e.g. "12345 8 2 <digest>").
225+
type DNSDSRecords struct {
226+
// Values is the list of DS record values.
227+
// +kubebuilder:validation:MinItems=1
228+
Values []string `json:"values"`
229+
230+
// TTL is the time-to-live for this record type.
231+
// +kubebuilder:validation:Minimum=0
232+
// +kubebuilder:validation:Maximum=3600
233+
// +optional
234+
TTL *int32 `json:"ttl,omitempty"`
235+
}
236+
237+
// DNSDNSKEYRecords holds DNSKEY records for DNSSEC, with an optional per-record TTL.
238+
// Values should be DNSKEY record data (e.g. "257 3 8 <base64-encoded-key>").
239+
type DNSDNSKEYRecords struct {
240+
// Values is the list of DNSKEY record values.
241+
// +kubebuilder:validation:MinItems=1
242+
Values []string `json:"values"`
243+
244+
// TTL is the time-to-live for this record type.
245+
// +kubebuilder:validation:Minimum=0
246+
// +kubebuilder:validation:Maximum=3600
247+
// +optional
248+
TTL *int32 `json:"ttl,omitempty"`
249+
}
250+
179251
type DomainTargetDNS struct {
180252
// IPs holds A/AAAA record addresses.
181253
// Cannot be set with FQDN.
@@ -195,6 +267,23 @@ type DomainTargetDNS struct {
195267
// +optional
196268
MX *DNSMXRecords `json:"mx,omitempty"`
197269

270+
// DKIM holds DKIM (DomainKeys Identified Mail) values.
271+
// Stored as TXT records under <selector>._domainkey.<domain>.
272+
// Values should be DKIM public key records (e.g. "v=DKIM1; k=rsa; p=...").
273+
// +optional
274+
DKIM *DNSDKIMRecords `json:"dkim,omitempty"`
275+
276+
// SPF holds SPF (Sender Policy Framework) values.
277+
// Stored as TXT records. Values should follow SPF syntax (e.g. "v=spf1 include:_spf.google.com ~all").
278+
// +optional
279+
SPF *DNSSPFRecords `json:"spf,omitempty"`
280+
281+
// DMARC holds DMARC (Domain-based Message Authentication, Reporting & Conformance) values.
282+
// Stored as TXT records under _dmarc.<domain>.
283+
// Values should follow DMARC syntax (e.g. "v=DMARC1; p=reject; rua=mailto:...").
284+
// +optional
285+
DMARC *DNSDMARCRecords `json:"dmarc,omitempty"`
286+
198287
// CAA holds Certification Authority Authorization record values.
199288
// +optional
200289
CAA *DNSCAARecords `json:"caa,omitempty"`
@@ -207,6 +296,15 @@ type DomainTargetDNS struct {
207296
// +optional
208297
NS *DNSNSRecords `json:"ns,omitempty"`
209298

299+
// DS holds DS (Delegation Signer) records for DNSSEC chain of trust.
300+
// Values should be DS record data (e.g. "12345 8 2 <digest>").
301+
// +optional
302+
DS *DNSDSRecords `json:"ds,omitempty"`
303+
304+
// DNSKEY holds DNSKEY records for DNSSEC.
305+
// Values should be DNSKEY record data (e.g. "257 3 8 <base64-encoded-key>").
306+
// +optional
307+
DNSKEY *DNSDNSKEYRecords `json:"dnskey,omitempty"`
210308
}
211309

212310
type DomainTLSSpec struct {
@@ -557,6 +655,41 @@ func getDomainRows(domain *Domain) []domainRow {
557655
ttl: resolveTTL(dns.CAA.TTL),
558656
})
559657
}
658+
if dns.DKIM != nil && len(dns.DKIM.Values) > 0 {
659+
rows = append(rows, domainRow{
660+
typ: "DNS:DKIM",
661+
value: formatMultiValue(dns.DKIM.Values, 30),
662+
ttl: resolveTTL(dns.DKIM.TTL),
663+
})
664+
}
665+
if dns.SPF != nil && len(dns.SPF.Values) > 0 {
666+
rows = append(rows, domainRow{
667+
typ: "DNS:SPF",
668+
value: formatMultiValue(dns.SPF.Values, 30),
669+
ttl: resolveTTL(dns.SPF.TTL),
670+
})
671+
}
672+
if dns.DMARC != nil && len(dns.DMARC.Values) > 0 {
673+
rows = append(rows, domainRow{
674+
typ: "DNS:DMARC",
675+
value: formatMultiValue(dns.DMARC.Values, 30),
676+
ttl: resolveTTL(dns.DMARC.TTL),
677+
})
678+
}
679+
if dns.DS != nil && len(dns.DS.Values) > 0 {
680+
rows = append(rows, domainRow{
681+
typ: "DNS:DS",
682+
value: formatMultiValue(dns.DS.Values, 30),
683+
ttl: resolveTTL(dns.DS.TTL),
684+
})
685+
}
686+
if dns.DNSKEY != nil && len(dns.DNSKEY.Values) > 0 {
687+
rows = append(rows, domainRow{
688+
typ: "DNS:DNSKEY",
689+
value: formatMultiValue(dns.DNSKEY.Values, 30),
690+
ttl: resolveTTL(dns.DNSKEY.TTL),
691+
})
692+
}
560693
}
561694

562695
if len(rows) == 0 {

0 commit comments

Comments
 (0)