Compare commits
No commits in common. "af04121ff6aa4976f5619dee92646ef261d02825" and "1d562e7aa4c29b139d5eb4705813d4e4f407ce1d" have entirely different histories.
af04121ff6
...
1d562e7aa4
2 changed files with 23 additions and 16 deletions
|
|
@ -36,6 +36,7 @@ func (p *caaProvider) ParseForm(r *http.Request) (sdk.CheckerOptions, error) {
|
||||||
return nil, errors.New("domain is required")
|
return nil, errors.New("domain is required")
|
||||||
}
|
}
|
||||||
domain = dns.Fqdn(domain)
|
domain = dns.Fqdn(domain)
|
||||||
|
bare := strings.TrimSuffix(domain, ".")
|
||||||
|
|
||||||
records, err := lookupCAA(domain)
|
records, err := lookupCAA(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -55,12 +56,12 @@ func (p *caaProvider) ParseForm(r *http.Request) (sdk.CheckerOptions, error) {
|
||||||
|
|
||||||
svc := serviceMessage{
|
svc := serviceMessage{
|
||||||
Type: serviceType,
|
Type: serviceType,
|
||||||
Domain: strings.TrimSuffix(domain, "."),
|
Domain: bare,
|
||||||
Service: svcBody,
|
Service: svcBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
return sdk.CheckerOptions{
|
return sdk.CheckerOptions{
|
||||||
"domain": strings.TrimSuffix(domain, "."),
|
"domain": bare,
|
||||||
"service": svc,
|
"service": svc,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
@ -74,12 +75,12 @@ func lookupCAA(fqdn string) ([]CAARecord, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
for name := fqdn; name != "" && name != "."; {
|
for name := fqdn; name != "" && name != "."; {
|
||||||
msg := new(dns.Msg)
|
msg := new(dns.Msg)
|
||||||
msg.SetQuestion(name, dns.TypeCAA)
|
msg.SetQuestion(name, dns.TypeCAA)
|
||||||
msg.RecursionDesired = true
|
msg.RecursionDesired = true
|
||||||
|
|
||||||
c := new(dns.Client)
|
|
||||||
in, _, err := c.Exchange(msg, resolver)
|
in, _, err := c.Exchange(msg, resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ type issuerAgg struct {
|
||||||
severity string
|
severity string
|
||||||
code string
|
code string
|
||||||
msg string
|
msg string
|
||||||
fix string
|
|
||||||
endpoints map[string]bool
|
endpoints map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +116,7 @@ func (r *caaRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts
|
||||||
// info just because one probe happened to be unresolvable.
|
// info just because one probe happened to be unresolvable.
|
||||||
agg := map[string]*issuerAgg{} // keyed by AKI+DN
|
agg := map[string]*issuerAgg{} // keyed by AKI+DN
|
||||||
|
|
||||||
issue := func(p *tlsProbeView, severity, code, msg, fix string) {
|
issue := func(p *tlsProbeView, severity, code, msg string) {
|
||||||
k := p.IssuerAKI + "|" + p.IssuerDN
|
k := p.IssuerAKI + "|" + p.IssuerDN
|
||||||
cur, ok := agg[k]
|
cur, ok := agg[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -128,7 +127,6 @@ func (r *caaRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts
|
||||||
cur.severity = severity
|
cur.severity = severity
|
||||||
cur.code = code
|
cur.code = code
|
||||||
cur.msg = msg
|
cur.msg = msg
|
||||||
cur.fix = fix
|
|
||||||
}
|
}
|
||||||
if addr := p.address(); addr != "" {
|
if addr := p.address(); addr != "" {
|
||||||
cur.endpoints[addr] = true
|
cur.endpoints[addr] = true
|
||||||
|
|
@ -138,16 +136,14 @@ func (r *caaRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts
|
||||||
for _, p := range probes {
|
for _, p := range probes {
|
||||||
if al.disallowIssue {
|
if al.disallowIssue {
|
||||||
issue(p, SeverityCrit, CodeIssuanceDisallowed,
|
issue(p, SeverityCrit, CodeIssuanceDisallowed,
|
||||||
fmt.Sprintf("CAA policy forbids issuance (issue \";\") but a certificate was observed on %s", p.address()),
|
fmt.Sprintf("CAA policy forbids issuance (issue \";\") but a certificate was observed on %s", p.address()))
|
||||||
"Remove the CA 0 issue \";\" record, or stop serving TLS certificates for this domain.")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
domains, ok := Lookup(p.IssuerAKI, p.IssuerDN)
|
domains, ok := Lookup(p.IssuerAKI, p.IssuerDN)
|
||||||
if !ok {
|
if !ok {
|
||||||
issue(p, SeverityInfo, CodeIssuerUnknown,
|
issue(p, SeverityInfo, CodeIssuerUnknown,
|
||||||
fmt.Sprintf("Observed issuer not found in CCADB (AKI=%q, DN=%q)", p.IssuerAKI, p.IssuerDN),
|
fmt.Sprintf("Observed issuer not found in CCADB (AKI=%q, DN=%q)", p.IssuerAKI, p.IssuerDN))
|
||||||
"File a CCADB update for this CA, or verify the cert was issued by a real CA.")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,21 +154,18 @@ func (r *caaRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts
|
||||||
if !hasPolicy {
|
if !hasPolicy {
|
||||||
issue(p, SeverityInfo, CodeOK,
|
issue(p, SeverityInfo, CodeOK,
|
||||||
fmt.Sprintf("No CAA records published; certificate on %s issued by %s (CAA identifier %s).",
|
fmt.Sprintf("No CAA records published; certificate on %s issued by %s (CAA identifier %s).",
|
||||||
p.address(), issuerLabel(p), strings.Join(domains, ", ")),
|
p.address(), issuerLabel(p), strings.Join(domains, ", ")))
|
||||||
fmt.Sprintf("Publish %q IN CAA 0 issue %q to lock future issuance to %s.",
|
|
||||||
data.Domain, domains[0], domains[0]))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !intersects(domains, al.issueAll) {
|
if !intersects(domains, al.issueAll) {
|
||||||
issue(p, SeverityCrit, CodeNotAuthorized,
|
issue(p, SeverityCrit, CodeNotAuthorized,
|
||||||
fmt.Sprintf("Certificate on %s issued by %s (CAA identifier %s) is not authorized by the zone's CAA issue records",
|
fmt.Sprintf("Certificate on %s issued by %s (CAA identifier %s) is not authorized by the zone's CAA issue records",
|
||||||
p.address(), issuerLabel(p), strings.Join(domains, ", ")),
|
p.address(), issuerLabel(p), strings.Join(domains, ", ")))
|
||||||
"Either update the CAA record to authorize this CA, or re-issue with an authorized CA.")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
issue(p, "", "", "", "")
|
issue(p, "", "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit one CheckState per distinct issuer, keyed deterministically so
|
// Emit one CheckState per distinct issuer, keyed deterministically so
|
||||||
|
|
@ -239,6 +232,19 @@ func severityRank(s string) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func severityToStatus(s string) sdk.Status {
|
||||||
|
switch s {
|
||||||
|
case SeverityCrit:
|
||||||
|
return sdk.StatusCrit
|
||||||
|
case SeverityWarn:
|
||||||
|
return sdk.StatusWarn
|
||||||
|
case SeverityInfo:
|
||||||
|
return sdk.StatusInfo
|
||||||
|
default:
|
||||||
|
return sdk.StatusOK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// intersects reports whether any element of lhs is present in the set.
|
// intersects reports whether any element of lhs is present in the set.
|
||||||
func intersects(lhs []string, set map[string]bool) bool {
|
func intersects(lhs []string, set map[string]bool) bool {
|
||||||
for _, s := range lhs {
|
for _, s := range lhs {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue