Skip to content

DNS best practices for operationcode.org and operationcode.net - #193

Merged
irvingpop merged 2 commits into
mainfrom
dns-best-practices
Nov 1, 2026
Merged

irvingpop merged 2 commits into
mainfrom
dns-best-practices

Conversation

@irvingpop

Copy link
Copy Markdown
Member

Summary

DNS best-practice changes for operationcode.org and operationcode.net. Follow-up to #192.

operationcode.org (terraform/dns_operationcode_org.tf)

  • CAA: add issue tags for amazon.com, amazontrust.com and letsencrypt.org. Before this, any CA could issue for the apex. The served cert issuer of every hostname was checked: only Amazon (ACM) and Let's Encrypt (Vercel) issue for our names.
  • Google MX: replace the legacy 5-record ASPMX set with Google's current single MX, 1 smtp.google.com.. Google still supports the old values, so this is cleanup.
  • DMARC: add rua=mailto:tech@operationcode.org and raise the TTL to 3600. The policy stays p=none until Google Workspace DKIM is set up.
  • DKIM TTLs: 60s to 3600s for Mailchimp k2/k3. Values unchanged.
  • Null SPF: v=spf1 -all on hosts that never send mail: www, api, pybot, resources, api.staging. Cloudways and DigitalOcean hosts are excluded until their owners are confirmed.

operationcode.net (terraform/dns_operationcode_net.tf, new)

  • Zone imported as aws_route53_zone with prevent_destroy, plus the apex alias and www CNAME (no changes on import).
  • The domain sends no mail, so it gets anti-spoofing records: apex v=spf1 -all, null MX 0 . (RFC 7505), and _dmarc with p=reject; sp=reject.
  • operationcode.net._report._dmarc.operationcode.org TXT authorizes operationcode.org to receive the .net DMARC reports.
  • Stray records at operationcode.org.operationcode.net (MX, SPF, TXT) are not imported. They are deleted by hand.

DNSSEC and query logging (terraform/dns_operationcode_org_security.tf, new)

  • DNSSEC stage 1 (zone signing): KMS key in us-east-1 (ECC_NIST_P256, SIGN_VERIFY, prevent_destroy) with the Route53 DNSSEC key policy, a key-signing key, and aws_route53_hosted_zone_dnssec.
  • DNSSEC stage 2 (DS record at the registrar) is commented out on purpose. Enable it in a follow-up PR only after aws route53 get-dnssec shows SIGNING, dig +dnssec operationcode.org shows RRSIG records, and 48 hours have passed (the apex NS TTL). A DS record before signing works would take the domain offline. The file documents the rollback order.
  • Query logging: a 30-day CloudWatch log group in us-east-1, a log resource policy for Route53, and the zone query log.
  • Cost: about $1.07/month (KMS key $1, logs about $0.06 at about 444k queries/month).

Plan

3 to import, 16 to add, 5 to change, 0 to destroy. Plans run locally; CI does not apply.

Rollout

  1. cd terraform && terraform plan, and confirm the line above.
  2. terraform apply from this branch.
  3. Delete the stray .net records, remove the .net import blocks, and confirm that terraform plan reports No changes.
  4. Merge.
  5. After 48 hours with signing verified: follow-up PR to enable the DS record.

Not in this PR

  • Google Workspace DKIM, then DMARC quarantine/reject for operationcode.org.
  • Apex SPF -all and the Mailgun include.
  • Cloudways (services, kibana, mautic, test, slash-commands) and DigitalOcean (community, nfs.services) owner checks.

🤖 Generated with Claude Code

…erationcode.net protection, DNSSEC signing, query logging

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude of Duty review, run 41325625277: 2 inline finding(s). Model output from untrusted input. Check it before you act on it. The gate result is in the summary comment.

# ======================================================================

# Google Workspace mail
# Replaced this zone's legacy ASPMX records with Google's current single MX on 2026-11-01. Google still supports the old values.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low bug, confidence low, pass review

Comment cites a specific date that may be wrong or future

The comment claims the MX was replaced on a specific date (2026-11-01). The date cannot be verified from the bundle and may be inaccurate, but it has no runtime effect.

Model output from untrusted input. Check it before you act on it.

sid = "Route53QueryLogging"
effect = "Allow"
actions = ["logs:CreateLogStream", "logs:PutLogEvents"]
resources = ["arn:aws:logs:us-east-1:${data.aws_caller_identity.current.account_id}:log-group:/aws/route53/*"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low security, confidence medium, pass security

Log policy grants Route53 write to all /aws/route53/* log groups

The CloudWatch resource policy allows route53.amazonaws.com to write to any log group under /aws/route53/* in the account, not only the new operationcode.org group. It is limited by SourceAccount and hostedzone SourceArn conditions, so only this account's Route53 zones can use it. The risk is small, but scoping to the specific log group ARN would follow least privilege.

Model output from untrusted input. Check it before you act on it.

@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

🟡 Clear to proceed: Claude of Duty logged 3 items to consider

Mission: Review the code. Protect the branch. Deploy the future.

Note

3 findings to consider. They do not block this PR.
Next step for the author: read the findings and fix what you agree with.

Severity Effect Where Finding Found by
🟠 Medium Does not block terraform/dns_operationcode_org.tf:184 Comment cites a future/unverifiable change date See the inline comment. Review (medium)
🟠 Medium Does not block terraform/dns_operationcode_org_security.tf:95 Query logging and DNSSEC changes in one apply may race See the inline comment. Review (medium)
🟡 Low Does not block terraform/dns_operationcode_org_security.tf:136 Route53 log policy allows writes to any /aws/route53/* log group See the inline comment. Security (low)
File checks Review Security Supply chain Dependency review Coverage
✅ ok, 1 signal ✅ ran, 2 findings ✅ ran, 1 finding ✅ ran, 0 findings ✅ ok ✅ complete

Run 41327313970, attempt 1 for head 8399893 into main. The required workflow in the merge box is the result that counts.

Claude of Duty never approves a PR. A human reviewer gives the final approval.

📋 Full review record: reasons, checks, signals, finding details, model summaries, token usage

Reviewed snapshot

Head SHA Merge base SHA Base branch Run
83998933cfb08a0be526d12d595e34ee757a2cb4 ffea3f6197382107c572d8fda6d8f289d2f2757c main 41327313970, attempt 1

Reasons the gate failed

None. No reason applies.

Checks (code, no model)

Check Result Detail
Hard blocks ✅ none
Coverage ✅ complete files in comparison 3, files collected 3, trees complete
Dependency changes ✅ none
Dependency review job ✅ success

Signals (context only, never block)

  • ℹ️ Credential-like string: credential-assignment (value redacted), in terraform/dns_operationcode_org_security.tf, lines 73

Dependency changes

None.

Finding details

Model output from untrusted input. Check it before you act on it. Verified means only that the quoted text is at that place. It does not mean the claim is true.

Blocking is decided by code from category and severity, never by the model. A finding in a blocking category blocks only at high or critical severity.

Pass Severity Category Confidence Citation Posted Model title
Review medium bug medium ✅ checked inline Comment cites a future/unverifiable change date
Review medium bug low ✅ checked inline Query logging and DNSSEC changes in one apply may race
Security low security low ✅ checked inline Route53 log policy allows writes to any /aws/route53/* log group

The Supply chain pass completed and reported no findings.

Model summaries

Model output from untrusted input. Check it before you act on it. Verified means only that the quoted text is at that place. It does not mean the claim is true.

Pass Status Model Summary
Review ✅ ok claude-sonnet-5-5 Adds DNS hardening for operationcode.org and .net, DNSSEC signing and query logging. I found a couple of plausible correctness issues, mostly around ordering and a questionable date comment; nothing is clearly broken.
Security ✅ ok claude-sonnet-5-5 The PR changes DNS records (CAA, MX, DMARC, null SPF), adds an operationcode.net zone, and adds Route53 DNSSEC signing plus query logging in Terraform. I found no injection, secrets, or prompt-injection content. The redacted line at the KMS key spec is the key spec string (ECC_NIST_P256 per the PR body), not a real credential. One minor concern: the CloudWatch log resource policy is broader than needed.
Supply chain ✅ ok claude-sonnet-5-5 The PR changes Terraform DNS for operationcode.org and operationcode.net: CAA, MX, DMARC, null SPF, a new .net zone, DNSSEC signing (stage 1 only, the DS record is commented out), and Route53 query logging. I found no obfuscation, encoded payloads, dynamic code, network calls, CI or workflow edits, dependency changes, or text aimed at an AI reviewer. The prefilter credential signal at line 73 of the security file is a redacted KMS key spec attribute, which is a configuration value and not a secret. The KMS key policy and the log resource policy are scoped by account and source ARN. The only breadth is the log policy's /aws/route53/* wildcard, which is documented. The changes run only when someone applies Terraform locally.

Token usage

Pass Input Output Cache write Cache read Attempts
Review 723 462 0 29629 1
Security 1049 415 0 29629 1
Supply chain 1241 273 29629 0 1
Total 3013 1150 29629 59258 3

Imports applied locally (3 imported). Stray operationcode.org.operationcode.net
MX/SPF/TXT records deleted by hand. terraform plan reports No changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@irvingpop

Copy link
Copy Markdown
Member Author

Applied locally from this branch: 3 imported, 16 added, 5 changed, 0 destroyed. Stray operationcode.org.operationcode.net MX/SPF/TXT deleted by hand. Import blocks removed (this commit). terraform plan on this branch now reports No changes, so the branch is ready to merge. DNSSEC status: SIGNING. The DS record follow-up waits 48 hours.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude of Duty review, run 41327313970: 3 inline finding(s). Model output from untrusted input. Check it before you act on it. The gate result is in the summary comment.

# ======================================================================

# Google Workspace mail
# Replaced this zone's legacy ASPMX records with Google's current single MX on 2026-11-01. Google still supports the old values.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium bug, confidence medium, pass review

Comment cites a future/unverifiable change date

The comment asserts the MX replacement happened on 2026-11-01, which may be a wrong or future date. It is misleading about when the change was made, but has no runtime effect.

Model output from untrusted input. Check it before you act on it.

name = "operationcode_org_ksk"
}

resource "aws_route53_hosted_zone_dnssec" "operationcode" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium bug, confidence low, pass review

Query logging and DNSSEC changes in one apply may race

The DNSSEC signing resource has no dependency on the KMS alias or the key policy being fully propagated. KMS policy eventual consistency can make the KSK creation fail on first apply. A retry normally resolves it.

Model output from untrusted input. Check it before you act on it.

sid = "Route53QueryLogging"
effect = "Allow"
actions = ["logs:CreateLogStream", "logs:PutLogEvents"]
resources = ["arn:aws:logs:us-east-1:${data.aws_caller_identity.current.account_id}:log-group:/aws/route53/*"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low security, confidence low, pass security

Route53 log policy allows writes to any /aws/route53/* log group

The account-wide CloudWatch Logs resource policy lets Route53 write to any log group under /aws/route53/* for any hosted zone in the account. It is scoped by source account, so exposure is limited to this account's own zones. The policy could instead name the specific log group and zone, so this is a minor least-privilege gap.

Model output from untrusted input. Check it before you act on it.

@irvingpop
irvingpop merged commit ea43574 into main Nov 1, 2026
5 checks passed
@irvingpop
irvingpop deleted the dns-best-practices branch November 1, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant