Repository navigation
Hosted DNS service: reserve, records, lease and release - #1
Merged
Merged
Conversation
added 4 commits
September 25, 2026 04:22
Axum service over Route 53 and Postgres. Anonymous mint returns a name and a bcrypt-hashed bearer token; rotate, full-set apex records, lease renewal and release use that token. A reaper frees unused reservations after 24 hours and retires expired leases. Released names are never reissued. HTTP API tests run against a fake Route 53 and a Postgres testcontainer.
POST /domains/{name}/certificate takes a CSR naming exactly name and
*.name, orders both from the configured ACME CA (Google Trust Services,
EAB-bound account), answers DNS-01 with a TXT record in the zone, waits
for Route 53 to report INSYNC, finalises and returns the PEM chain. The
challenge is removed either way. The service never sees the private key
and stores no certificate.
A CA 429 pauses all issuance until its Retry-After and is passed back
as 429 ca_rate_limited. The ACME account credentials are kept in
Postgres because EAB keys are single use.
MINT_KEYS holds comma-separated keys. POST /domains with a known key as the bearer token skips the per-IP limiter; any other Authorization header is refused with 401 rather than treated as anonymous. Keys are compared without an early exit.
added 3 commits
September 25, 2026 04:58
- The reaper frees only reservations that never published records and never asked for a certificate; a name that may hold a valid wildcard is only ever retired, so it can not be reissued. - ClusterDomain and Token newtypes own the derived names, token generation and bcrypt hashing. - cert::Issuer owns the CA backoff and returns CertError; the handler is authorize, mark used, issue. - One RecordType to RrType mapping; TXT is never read back. - The wildcard CNAME is always upserted. - JsonRejection converts into ApiError; IntoResponse is one match. - authenticate is now authorize_and_renew. - Error-path test for the reaper; documented the API contract.
- ClusterDomain::parse accepts one DNS label under the configured apex; any other path name is 404 like an unknown name. - ClusterDomain::names() gives [name, *.name] to records, CSR check and order. - CertError maps into ApiError's own InvalidCsr, Ca and Zone variants, so IntoResponse has one arm per case. - Document CertError::Ca and CertError::Zone. - The mint test asserts the token contract (charset, distinct tokens) instead of its length; TOKEN_LEN is private again.
nick-potts
marked this pull request as ready for review
September 25, 2026 05:07
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A new Hosted DNS service: an axum API in front of one Route 53 zone (
ployz.app) and Postgres. Cloud is its only client. It also signs one wildcard certificate per name from Cloud's CSR through Google Trust Services DNS-01. It never sees the private key and stores no certificate.How a name moves through its life:
Evidence
After:
cargo testpasses 16 HTTP API tests (Docker required), locally and in CI. Clippy with-D warningsandfmt --checkare clean.Merge Danger
Door: two-way
Nothing is deployed and nothing calls this service yet. #1018 deploys it, and Cloud starts calling it in getployz/ployz#1061.
Blast Radius: none
Things to decide at deploy time (#1018):
MINTS_PER_HOUR). Give Hosted Cloud aMINT_KEYSentry so its single egress IP is not limited.CLIENT_IP_HEADER=x-real-ipthe limiter sees the proxy's IP, not the caller's.acme_accounts, keyed by directory URL. Wiping that table, or switching from the staging to the production directory, needs a fresh EAB key fromgcloud publicca external-account-keys create.route53:ChangeResourceRecordSets,route53:ListResourceRecordSetsandroute53:GetChangeon the zone.Retry-Afterpauses issuance for 1 hour; a restart forgets it..env.exampleholds only placeholders.Closes getployz/ployz#1016
Closes getployz/ployz#1017