Skip to content
This repository was archived by the owner on Mar 16, 2024. It is now read-only.

add: waitForDomain func to wait for a domain to be resolvable before pinging lets-encrypt #2236

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions pkg/controller/tls/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/x509"
"encoding/pem"
"fmt"
"net"
"strings"
"time"

Expand Down Expand Up @@ -49,6 +50,24 @@ func RequireSecretTypeTLS(h router.Handler) router.Handler {
})
}

func WaitForDomain(domain string, retryInterval time.Duration, maxRetries int) error {
done := make(chan error)

go func() {
for retries := 0; retries < maxRetries; retries++ {
ips, err := net.LookupIP(domain)
if err == nil && len(ips) > 0 {
done <- nil // Domain is resolvable
return
}
time.Sleep(retryInterval)
}
done <- fmt.Errorf("domain %s is not resolvable after %d retries", domain, maxRetries) // Domain is not resolvable
}()

return <-done
}

// RenewCert handles the renewal of existing TLS certificates
func RenewCert(req router.Request, resp router.Response) error {
sec := req.Object.(*corev1.Secret)
Expand Down Expand Up @@ -82,6 +101,11 @@ func RenewCert(req router.Request, resp router.Response) error {

logrus.Infof("Renewing TLS cert for %s", domain)

if err := WaitForDomain(domain, 5*time.Second, 12); err != nil {
logrus.Warnf("Domain %s is not resolvable, skipping certificate renewal: %v", domain, err)
return
}

// Get new certificate
cert, err := leUser.getCert(req.Ctx, domain)
if err != nil {
Expand Down
22 changes: 22 additions & 0 deletions pkg/publish/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import (
"encoding/pem"
"fmt"
"sort"
"sync"
"time"

"github.com/acorn-io/baaah/pkg/name"
"github.com/acorn-io/baaah/pkg/router"
"github.com/acorn-io/baaah/pkg/typed"
v1 "github.com/acorn-io/runtime/pkg/apis/internal.acorn.io/v1"
"github.com/acorn-io/runtime/pkg/controller/tls"
"github.com/acorn-io/runtime/pkg/labels"
"github.com/acorn-io/runtime/pkg/system"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -155,6 +158,25 @@ func setupCertsForRules(req router.Request, svc *v1.ServiceInstance, rules []net
ingressTLS = setupCertManager(svc.Name, rules)
}

// Best effort to wait for all domains to be ready, so we don't spam Let's Encrypt
// with requests for domains where the DNS entry was not yet propagated
hostsSeen := map[string]struct{}{}
wg := sync.WaitGroup{}
for _, rule := range rules {
if _, ok := hostsSeen[rule.Host]; ok {
continue
}
hostsSeen[rule.Host] = struct{}{}
wg.Add(1)
go func(host string) {
err := tls.WaitForDomain(host, 5*time.Second, 6)
if err != nil {
logrus.Debugln(err)
}
wg.Done()
}(rule.Host)
}
wg.Wait()
return secrets, ingressTLS, annotations, nil
}

Expand Down