@@ -38,36 +38,35 @@ func GenerateLetsEncryptCert(ctx context.Context, client cliClient.Client) error
38
38
}
39
39
}
40
40
if cnt == 0 {
41
- term .Infof ("No services found need to generate Let's Encrypt cert" )
41
+ term .Infof (" * No services found need to generate Let's Encrypt cert" )
42
42
}
43
43
44
44
return nil
45
45
}
46
46
47
47
func generateCert (ctx context.Context , domain , albDns string ) {
48
- term .Infof ("Triggering Let's Encrypt cert generation for %v" , domain )
48
+ term .Infof (" * Triggering Let's Encrypt cert generation for %v" , domain )
49
49
if err := waitForCNAME (ctx , domain , albDns ); err != nil {
50
50
term .Errorf ("Error waiting for CNAME: %v" , err )
51
51
return
52
52
}
53
53
54
- term .Infof ("%v DNS is properly configured!" , domain )
54
+ term .Infof (" * %v DNS is properly configured!" , domain )
55
55
if err := checkTLSCert (ctx , domain ); err == nil {
56
- term .Infof ("TLS cert for %v is already ready" , domain )
56
+ term .Infof (" * TLS cert for %v is already ready" , domain )
57
57
return
58
58
}
59
- term .Infof ("Triggering cert generation for %v" , domain )
59
+ term .Infof (" * Triggering cert generation for %v" , domain )
60
60
triggerCertGeneration (ctx , domain )
61
61
62
- term .Infof ("Waiting for TLS cert to be online for %v" , domain )
62
+ term .Infof (" * Waiting for TLS cert to be online for %v" , domain )
63
63
if err := waitForTLS (ctx , domain ); err != nil {
64
64
term .Errorf ("Error waiting for TLS to be online: %v" , err )
65
- // FIXME: The message below is only valid for BYOC, need to update when playground ACME cert support is added
66
- term .Errorf ("Please check for error messages from `/aws/lambda/acme-lambda` log group in cloudwatch for more details" )
65
+ // FIXME: Add more info on how to debug, possibly provided by the server side to avoid client type detection here
67
66
return
68
67
}
69
68
70
- term . Infof ("TLS cert for %v is ready" , domain )
69
+ fmt . Printf ("TLS cert for %v is ready\n " , domain )
71
70
}
72
71
73
72
func triggerCertGeneration (ctx context.Context , domain string ) {
@@ -141,12 +140,13 @@ func waitForCNAME(ctx context.Context, domain, albDns string) error {
141
140
case <- ctx .Done ():
142
141
return ctx .Err ()
143
142
case <- ticker .C :
144
- cname , err := resolver . LookupCNAME (ctx , domain )
143
+ cname , err := waitForCNAMEInSync (ctx , domain )
145
144
cname = strings .TrimSuffix (cname , "." )
146
145
if err != nil || strings .ToLower (cname ) != strings .ToLower (albDns ) {
147
146
if ! msgShown {
148
- term .Infof ("Please setup CNAME record for %v to point to ALB %v, waiting for CNAME record setup and DNS propagation" , domain , strings .ToLower (albDns ))
149
- term .Infof ("Note: DNS propagation may take a while, we will proceed as soon as the CNAME record is ready, checking..." )
147
+ term .Infof (" * Please setup CNAME record for %v" , domain )
148
+ fmt .Printf (" %v CNAME %v\n " , domain , strings .ToLower (albDns ))
149
+ term .Infof (" * Waiting for CNAME record setup and DNS propagation..." )
150
150
msgShown = true
151
151
}
152
152
if doSpinner {
@@ -185,3 +185,69 @@ func getWithRetries(ctx context.Context, url string, tries int) error {
185
185
}
186
186
return errors .Join (errs ... )
187
187
}
188
+
189
+ func waitForCNAMEInSync (ctx context.Context , domain string ) (string , error ) {
190
+ ns , err := getNSServers (ctx , domain )
191
+ if err != nil {
192
+ return "" , err
193
+ }
194
+
195
+ ticker := time .NewTicker (1 * time .Second )
196
+ defer ticker .Stop ()
197
+ for {
198
+ select {
199
+ case <- ticker .C :
200
+ cnames := make (map [string ]bool )
201
+ var cname string
202
+ var err error
203
+ for _ , n := range ns {
204
+ cname , err = resolverAt (n ).LookupCNAME (context .Background (), domain )
205
+ if err != nil {
206
+ term .Debugf (" - Error looking up CNAME for %v at %v: %v" , domain , n , err )
207
+ }
208
+ cnames [cname ] = true
209
+ }
210
+ if len (cnames ) > 1 {
211
+ continue
212
+ }
213
+ return cname , err
214
+ case <- ctx .Done ():
215
+ return "" , ctx .Err ()
216
+ }
217
+ }
218
+ }
219
+
220
+ func getNSServers (ctx context.Context , domain string ) ([]string , error ) {
221
+ d := domain
222
+ var ns []* net.NS
223
+ for {
224
+ var err error
225
+ ns , err = resolver .LookupNS (ctx , d )
226
+ var ne * net.DNSError
227
+ if errors .As (err , & ne ) {
228
+ if strings .Count (d , "." ) <= 1 {
229
+ return nil , fmt .Errorf ("No DNS server found" )
230
+ }
231
+ d = d [strings .Index (domain , "." )+ 1 :]
232
+ continue
233
+ } else if err != nil {
234
+ return nil , fmt .Errorf ("Failed to find NS server for %v at %v: %v" , domain , d , err )
235
+ }
236
+ break
237
+ }
238
+ servers := make ([]string , len (ns ))
239
+ for i , n := range ns {
240
+ servers [i ] = n .Host
241
+ }
242
+ return servers , nil
243
+ }
244
+
245
+ func resolverAt (nsServer string ) * net.Resolver {
246
+ return & net.Resolver {
247
+ PreferGo : true ,
248
+ Dial : func (ctx context.Context , network , address string ) (net.Conn , error ) {
249
+ d := net.Dialer {}
250
+ return d .DialContext (ctx , network , nsServer + ":53" )
251
+ },
252
+ }
253
+ }
0 commit comments