Skip to content

Commit 13542d7

Browse files
committed
feat: wire domain controller with rdap registration
1 parent a0c928c commit 13542d7

10 files changed

Lines changed: 1029 additions & 48 deletions

File tree

api/v1alpha/domain_types.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ type DomainSpec struct {
4343
type DomainStatus struct {
4444
Verification *DomainVerificationStatus `json:"verification,omitempty"`
4545
Registration *Registration `json:"registration,omitempty"`
46-
Conditions []metav1.Condition `json:"conditions,omitempty"`
46+
// Nameservers lists the authoritative NS for the *effective* domain name:
47+
// - If Apex == true: taken from RDAP for the registered domain (eTLD+1)
48+
// - If Apex == false: taken from DNS delegation for the subdomain; falls back to apex NS if no cut
49+
Nameservers []Nameserver `json:"nameservers,omitempty"`
50+
// Apex is true when spec.domainName is the registered domain (eTLD+1).
51+
Apex bool `json:"apex,omitempty"`
52+
Conditions []metav1.Condition `json:"conditions,omitempty"`
4753
}
4854

4955
const (
@@ -122,9 +128,6 @@ type Registration struct {
122128
// Raw statuses that will either be rdap rfc8056 or whois EPP status strings
123129
Statuses []string `json:"statuses,omitempty"` // e.g., clientTransferProhibited (EPP) or client transfer prohibited (RDAP)
124130

125-
// Nameservers is a list of nameservers for the domain and their registrant name
126-
Nameservers []Nameserver `json:"nameservers,omitempty"`
127-
128131
// DNSSEC (from RDAP secureDNS, with WHOIS fallback when parsable)
129132
DNSSEC *DNSSECInfo `json:"dnssec,omitempty"`
130133

@@ -133,6 +136,8 @@ type Registration struct {
133136

134137
// Abuse / support contacts (registrar/registry)
135138
Abuse *AbuseContact `json:"abuse,omitempty"`
139+
140+
NextRegistrationAttempt metav1.Time `json:"nextRegistrationAttempt,omitempty"`
136141
}
137142

138143
type RegistrarInfo struct {
@@ -147,8 +152,14 @@ type RegistryInfo struct {
147152
}
148153

149154
type Nameserver struct {
150-
Hostname string `json:"hostname"`
151-
RegistrantName string `json:"registrantName,omitempty"`
155+
Hostname string `json:"hostname"`
156+
IPs []NameserverIP `json:"ips,omitempty"`
157+
}
158+
159+
// NameserverIP captures per-address provenance for a nameserver.
160+
type NameserverIP struct {
161+
Address string `json:"address"` // e.g., "192.0.2.10" or "2001:db8::1"
162+
RegistrantName string `json:"registrantName,omitempty"` // org/name from IP RDAP if available
152163
}
153164

154165
type DNSSECInfo struct {

api/v1alpha/zz_generated.deepcopy.go

Lines changed: 28 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/networking.datumapis.com_domains.yaml

Lines changed: 128 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ spec:
8989
type: VerifiedHTTP
9090
description: DomainStatus defines the observed state of Domain
9191
properties:
92+
apex:
93+
description: Apex is true when spec.domainName is the registered domain
94+
(eTLD+1).
95+
type: boolean
9296
conditions:
9397
items:
9498
description: Condition contains details for one aspect of the current
@@ -145,40 +149,144 @@ spec:
145149
- type
146150
type: object
147151
type: array
148-
registrar:
149-
description: DomainRegistrarStatus represents the registrar information
152+
nameservers:
153+
description: |-
154+
Nameservers lists the authoritative NS for the *effective* domain name:
155+
- If Apex == true: taken from RDAP for the registered domain (eTLD+1)
156+
- If Apex == false: taken from DNS delegation for the subdomain; falls back to apex NS if no cut
157+
items:
158+
properties:
159+
hostname:
160+
type: string
161+
ips:
162+
items:
163+
description: NameserverIP captures per-address provenance
164+
for a nameserver.
165+
properties:
166+
address:
167+
type: string
168+
registrantName:
169+
type: string
170+
required:
171+
- address
172+
type: object
173+
type: array
174+
required:
175+
- hostname
176+
type: object
177+
type: array
178+
registration:
179+
description: Registration represents the registration information
150180
for a domain
151181
properties:
152-
clientStatusCodes:
153-
items:
154-
type: string
155-
type: array
156-
createdDate:
182+
abuse:
183+
description: Abuse / support contacts (registrar/registry)
184+
properties:
185+
email:
186+
type: string
187+
phone:
188+
type: string
189+
type: object
190+
contacts:
191+
description: Contacts (minimal, non-PII summary if available)
192+
properties:
193+
admin:
194+
properties:
195+
email:
196+
type: string
197+
organization:
198+
type: string
199+
phone:
200+
type: string
201+
type: object
202+
registrant:
203+
properties:
204+
email:
205+
type: string
206+
organization:
207+
type: string
208+
phone:
209+
type: string
210+
type: object
211+
tech:
212+
properties:
213+
email:
214+
type: string
215+
organization:
216+
type: string
217+
phone:
218+
type: string
219+
type: object
220+
type: object
221+
createdAt:
222+
description: Lifecycle
223+
format: date-time
157224
type: string
158225
dnssec:
159-
description: DNSSECStatus represents the DNSSEC status of a domain
226+
description: DNSSEC (from RDAP secureDNS, with WHOIS fallback
227+
when parsable)
160228
properties:
161-
signed:
229+
ds:
230+
items:
231+
properties:
232+
algorithm:
233+
type: integer
234+
digest:
235+
type: string
236+
digestType:
237+
type: integer
238+
keyTag:
239+
type: integer
240+
required:
241+
- algorithm
242+
- digest
243+
- digestType
244+
- keyTag
245+
type: object
246+
type: array
247+
enabled:
162248
type: boolean
163-
required:
164-
- signed
165249
type: object
166-
expirationDate:
250+
domain:
251+
description: Identity & provenance
167252
type: string
168-
ianaID:
253+
expiresAt:
254+
format: date-time
169255
type: string
170-
ianaName:
256+
handle:
171257
type: string
172-
modifiedDate:
258+
nextRegistrationAttempt:
259+
format: date-time
173260
type: string
174-
nameservers:
175-
items:
176-
type: string
177-
type: array
178-
serverStatusCodes:
261+
registrar:
262+
properties:
263+
ianaID:
264+
type: string
265+
name:
266+
type: string
267+
url:
268+
type: string
269+
type: object
270+
registry:
271+
properties:
272+
name:
273+
type: string
274+
url:
275+
type: string
276+
type: object
277+
registryDomainID:
278+
type: string
279+
source:
280+
type: string
281+
statuses:
282+
description: Raw statuses that will either be rdap rfc8056 or
283+
whois EPP status strings
179284
items:
180285
type: string
181286
type: array
287+
updatedAt:
288+
format: date-time
289+
type: string
182290
type: object
183291
verification:
184292
description: DomainVerificationStatus represents the verification

go.mod

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ toolchain go1.24.2
66

77
require (
88
github.com/google/go-cmp v0.7.0
9+
github.com/google/uuid v1.6.0
910
github.com/onsi/ginkgo/v2 v2.23.4
11+
github.com/openrdap/rdap v0.9.1
1012
github.com/stretchr/testify v1.10.0
1113
go.miloapis.com/milo v0.1.0
14+
golang.org/x/net v0.41.0
1215
golang.org/x/sync v0.15.0
1316
google.golang.org/protobuf v1.36.6
1417
k8s.io/api v0.33.1
@@ -22,6 +25,8 @@ require (
2225

2326
require (
2427
cel.dev/expr v0.24.0 // indirect
28+
github.com/alecthomas/kingpin/v2 v2.4.0 // indirect
29+
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
2530
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
2631
github.com/beorn7/perks v1.0.1 // indirect
2732
github.com/blang/semver/v4 v4.0.0 // indirect
@@ -46,12 +51,12 @@ require (
4651
github.com/google/cel-go v0.25.0 // indirect
4752
github.com/google/gnostic-models v0.6.9 // indirect
4853
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
49-
github.com/google/uuid v1.6.0 // indirect
5054
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
5155
github.com/inconshreveable/mousetrap v1.1.0 // indirect
5256
github.com/josharian/intern v1.0.0 // indirect
5357
github.com/json-iterator/go v1.1.12 // indirect
5458
github.com/mailru/easyjson v0.9.0 // indirect
59+
github.com/mitchellh/go-homedir v1.1.0 // indirect
5560
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
5661
github.com/modern-go/reflect2 v1.0.2 // indirect
5762
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -66,6 +71,7 @@ require (
6671
github.com/spf13/pflag v1.0.7 // indirect
6772
github.com/stoewer/go-strcase v1.3.0 // indirect
6873
github.com/x448/float16 v0.8.4 // indirect
74+
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
6975
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
7076
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
7177
go.opentelemetry.io/otel v1.35.0 // indirect
@@ -79,8 +85,8 @@ require (
7985
go.uber.org/multierr v1.11.0 // indirect
8086
go.uber.org/zap v1.27.0 // indirect
8187
go.yaml.in/yaml/v2 v2.4.2 // indirect
88+
golang.org/x/crypto v0.39.0 // indirect
8289
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
83-
golang.org/x/net v0.41.0 // indirect
8490
golang.org/x/oauth2 v0.30.0 // indirect
8591
golang.org/x/sys v0.33.0 // indirect
8692
golang.org/x/term v0.32.0 // indirect

0 commit comments

Comments
 (0)