public_tls.go RawHistoryFolder
1package domain
2
3import (
4 "fmt"
5 "strings"
6 "time"
7)
8
9type ACMEChallengeMode string
10
11const (
12 ACMEChallengeAuto ACMEChallengeMode = "auto"
13 ACMEChallengeHTTP01 ACMEChallengeMode = "http-01"
14 ACMEChallengeCloudflareDNS01 ACMEChallengeMode = "cloudflare-dns-01"
15
16 MaxHTTP01TokenLength = 256
17 TLSRenewalWindow = 30 * 24 * time.Hour
18)
19
20func IsValidHTTP01Token(token string) bool {
21 return token != "" && len(token) <= MaxHTTP01TokenLength && !strings.Contains(token, "/") && !strings.Contains(token, "\\") && !strings.Contains(token, "..") && !strings.Contains(token, "\x00")
22}
23
24func ParseACMEChallengeMode(value string) (ACMEChallengeMode, error) {
25 switch strings.TrimSpace(value) {
26 case "", string(ACMEChallengeAuto):
27 return ACMEChallengeAuto, nil
28 case string(ACMEChallengeHTTP01):
29 return ACMEChallengeHTTP01, nil
30 case string(ACMEChallengeCloudflareDNS01):
31 return ACMEChallengeCloudflareDNS01, nil
32 default:
33 return "", fmt.Errorf("%w: %q", ErrACMEChallengeInvalid, value)
34 }
35}
36
37type ACMETokenSource string
38
39const (
40 ACMETokenSourceNone ACMETokenSource = "none"
41 ACMETokenSourcePass ACMETokenSource = "pass"
42 ACMETokenSourceFile ACMETokenSource = "file"
43 ACMETokenSourceEnv ACMETokenSource = "env"
44)
45
46type TLSCertificateStatus string
47
48const (
49 TLSCertificateStatusMissing TLSCertificateStatus = "missing"
50 TLSCertificateStatusValid TLSCertificateStatus = "valid"
51 TLSCertificateStatusWarning TLSCertificateStatus = "warning"
52 TLSCertificateStatusExpired TLSCertificateStatus = "expired"
53 TLSCertificateStatusError TLSCertificateStatus = "error"
54)
55
56type ManagedCertificate struct {
57 ID string
58 Names []string
59 Challenge ACMEChallengeMode
60 Status TLSCertificateStatus
61 NotAfter time.Time
62 LastError string
63 RenewalPending bool
64}
65
66func (c ManagedCertificate) Covers(host string) bool {
67 return CertificateNamesCoverHost(c.Names, host)
68}
69
70// CertificateNamesCoverHost reports whether any certificate name covers host.
71func CertificateNamesCoverHost(names []string, host string) bool {
72 host = strings.TrimSuffix(strings.ToLower(strings.TrimSpace(host)), ".")
73 if host == "" {
74 return false
75 }
76 for _, name := range names {
77 name = strings.TrimSuffix(strings.ToLower(strings.TrimSpace(name)), ".")
78 if name == host {
79 return true
80 }
81 if suffix, ok := strings.CutPrefix(name, "*."); ok && strings.HasSuffix(host, "."+suffix) {
82 left := strings.TrimSuffix(host, "."+suffix)
83 if left != "" && !strings.Contains(left, ".") {
84 return true
85 }
86 }
87 }
88 return false
89}
90
91func (c ManagedCertificate) Health(now time.Time) TLSCertificateStatus {
92 if c.LastError != "" {
93 return TLSCertificateStatusError
94 }
95 if c.NotAfter.IsZero() {
96 return TLSCertificateStatusMissing
97 }
98 if !now.Before(c.NotAfter) {
99 return TLSCertificateStatusExpired
100 }
101 if !now.Add(TLSRenewalWindow).Before(c.NotAfter) {
102 return TLSCertificateStatusWarning
103 }
104 return TLSCertificateStatusValid
105}
106
107type TLSRouteCoverage struct {
108 Domain string
109 Covered bool
110 CoveredBy string
111 RequiredACME bool
112 Error string
113}
114
115type PublicTLSStatus struct {
116 ACMEEnabled bool
117 ConfiguredMode ACMEChallengeMode
118 EffectiveMode ACMEChallengeMode
119 SelectionReason string
120 TokenSource ACMETokenSource
121 Certificates []ManagedCertificate
122 Routes []TLSRouteCoverage
123 Errors []string
124}