Initial commit
This commit is contained in:
commit
a2a7921cb8
20 changed files with 1868 additions and 0 deletions
101
README.md
Normal file
101
README.md
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# checker-caa
|
||||
|
||||
CAA posture checker for happyDomain.
|
||||
|
||||
Validates that certificates observed by `checker-tls` were issued by a
|
||||
CA actually authorized by the domain's `CAA` records. This checker
|
||||
runs no network probes of its own: it reads the `svcs.CAAPolicy`
|
||||
service body (already parsed by happyDomain from the zone's `CAA`
|
||||
resource records) and the `tls_probes` observations published by
|
||||
`checker-tls`, and cross-references them via the CCADB "CAA
|
||||
Identifiers" mapping.
|
||||
|
||||
## How it works
|
||||
|
||||
1. The host runs this checker on a `svcs.CAAPolicy` service.
|
||||
2. `Collect` unmarshals the service body into a list of
|
||||
`(flag, tag, value)` entries. No network.
|
||||
3. The `caa_compliance` rule:
|
||||
- calls `obs.Get("caa_policy", …)` to load its own payload;
|
||||
- calls `obs.GetRelated("tls_probes")` to pick up every TLS probe
|
||||
produced on the target;
|
||||
- resolves each observed issuer (keyed by `IssuerAKI` with an
|
||||
`IssuerDN` fallback) against the embedded CCADB CSV to find the
|
||||
CA's published CAA identifier domain(s);
|
||||
- compares the observed identifiers against the `issue` /
|
||||
`issuewild` allow list (or flags a `DisallowIssue` violation).
|
||||
|
||||
## Observation payload
|
||||
|
||||
This checker does not publish endpoints or add a new observation
|
||||
schema. Under its own observation key `caa_policy` it returns a
|
||||
pass-through view of the zone-side CAA records:
|
||||
|
||||
```json
|
||||
{
|
||||
"domain": "example.net",
|
||||
"records": [
|
||||
{ "flag": 0, "tag": "issue", "value": "letsencrypt.org" },
|
||||
{ "flag": 0, "tag": "issuewild", "value": ";" }
|
||||
],
|
||||
"run_at": "2026-04-22T12:34:56Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Rule outcomes
|
||||
|
||||
- `caa_ok`: every observed issuer is authorized by the zone's CAA
|
||||
policy.
|
||||
- `caa_no_tls`: no TLS probes related to this target have been
|
||||
published yet. Reported as `UNKNOWN` (the same "eventual
|
||||
consistency" steady state used by `checker-tls` when it has no
|
||||
endpoints yet).
|
||||
- `caa_not_authorized`: CCADB mapped an observed issuer to a domain
|
||||
the CAA policy does not list. Reported `CRIT`.
|
||||
- `caa_issuance_disallowed`: the policy contains `CAA 0 issue ";"`
|
||||
(explicitly disallowing issuance) but a TLS cert was still observed.
|
||||
Reported `CRIT`.
|
||||
- `caa_issuer_unknown`: CCADB has no mapping for the observed issuer
|
||||
(AKI + DN). Reported `INFO`; action is to file a CCADB update.
|
||||
|
||||
## Issuer -> CAA domain mapping (CCADB)
|
||||
|
||||
The file `checker/AllCAAIdentifiersReport.csv` is an unmodified
|
||||
snapshot of the "CAA Identifiers (V2)" report from the Common CA
|
||||
Database (https://www.ccadb.org/resources). It is embedded into the
|
||||
binary via `//go:embed` but is **not committed to the repository**.
|
||||
To fetch or refresh it, run:
|
||||
|
||||
```bash
|
||||
go generate ./checker/
|
||||
```
|
||||
|
||||
This downloads the current CSV from CCADB. No code changes are needed
|
||||
to pick up a new snapshot: only a re-embed (recompile) is required
|
||||
after the file is refreshed. Note that the download depends on CCADB
|
||||
being reachable; `go build` itself has no network dependency.
|
||||
|
||||
The lookup key is:
|
||||
|
||||
1. `IssuerAKI` (uppercase hex of `leaf.AuthorityKeyId`), matched
|
||||
against CCADB's `"Subject Key Identifier (Hex)"` column.
|
||||
2. `IssuerDN` (Go's `leaf.Issuer.String()`), matched against CCADB's
|
||||
`"Subject"` column after normalization (RDNs sorted by type,
|
||||
whitespace trimmed, comma/semicolon separators collapsed).
|
||||
|
||||
## Options
|
||||
|
||||
| Id | Type | Default | Description |
|
||||
|-----------|--------|---------|------------------------------------|
|
||||
| `domain` | string | (auto) | Domain being checked (`AutoFill`). |
|
||||
| `service` | (n/a) | (auto) | `svcs.CAAPolicy` service body. |
|
||||
|
||||
## Running
|
||||
|
||||
```bash
|
||||
# Plugin (loaded by happyDomain at startup)
|
||||
make plugin
|
||||
|
||||
# Standalone HTTP server
|
||||
make && ./checker-caa -listen :8080
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue