Skip to content

Delete the audit CFN template that defaults to the vendor's AWS account - #107

Merged
kiwifellows merged 1 commit into
developfrom
claude/issue-102-remove-audit-template
Aug 3, 2026
Merged

Delete the audit CFN template that defaults to the vendor's AWS account#107
kiwifellows merged 1 commit into
developfrom
claude/issue-102-remove-audit-template

Conversation

@kiwifellows

Copy link
Copy Markdown
Contributor

Stacked on #106. Based on claude/github-issue-103-49098a, because #106 adds TopsInstallId to the template this PR deletes. GitHub will retarget this to develop automatically once #106 merges. Review #106 first; the diff here is just the deletion.

What and why

templates/iam.role.audit.account.cfn.yaml defaulted ParentAWSAccountId to 660228977852Teem's own SaaS AWS account — and built the notifier's ServiceToken from AWS::Region, the child's region, rather than from a parent-region parameter. The sibling child template was fixed to take an explicit ParentDeploymentRegion; this one never was.

Deployed with defaults, it created a cross-account IAM role in the operator's own account trusting an account they do not control, carrying ReadOnlyAccess plus securityhub:*, guardduty:*, macie:*, inspector:*, config:Put*, CloudTrail and CloudWatch Logs writes, and iam:PassRole on role/tops*.

Closes #102.

Deleted rather than repaired

Nothing in the product referenced it. install-messaging.sh uploads only iam.role.child.account.cfn.yaml, and TOPS_CFN_TEMPLATE_URL points at that same file — so it was never on the onboarding path. It was reachable only by a self-hosted operator browsing templates/ and picking the file whose name matched what they wanted.

A second, unexercised copy of the onboarding template was itself the defect. It drifted through an entire SaaS-to-self-hosted pivot without anyone noticing, precisely because nothing ran it. Repairing it — dropping the Default, adding ParentDeploymentRegion — would have restored exactly the condition that let it rot: a plausible-looking file that no code path exercises. #102 reached the same conclusion ("most likely just delete it").

templates/sync.sh goes with it

aws s3api put-bucket-acl --bucket storage.teemops.com --acl public-read
aws s3 sync . s3://storage.teemops.com/ --acl public-read ...

This is what made the broken template look canonical — served from the vendor's own domain, next to the one that works. A bucket-wide public-read ACL plus a public sync of the whole directory is vendor-era publishing with no meaning in a self-hosted install, where the installer uploads the template to the operator's own deployment bucket.

That answers the third acceptance criterion on #102 — whether storage.teemops.com should be publicly readable at all. The recorded decision: not on this project's behalf, because this project no longer publishes anything to it.

⚠️ Deleting the script does not un-publish what is already in that bucket. Objects synced there previously remain public until removed by hand, which only the bucket's owner can do. That is a separate action, outside this repo.

Also in here

  • $topsType dropped from ProcessSqsMessages — assigned and never read. It distinguished "ops" from "audit", and nothing branched on it even while the audit template existed. A comment records that messages still carry the field.
  • The installer test now guards the whole templates/ directory against a Default on ParentAWSAccountId, rather than checking one file, so a future template cannot reintroduce the defect.

How it was tested

Infrastructure change — no user story.

  • 709 PHP tests passing (3 skipped), unchanged by the deletion
  • 45 installer assertions passing — the two audit-template checks added in N-11 · Lock down the account-linking SNS topic (phases 1 and 2) #106 are gone, replaced by the directory-wide ParentAWSAccountId guard
  • Grepped for dangling references: none outside references/samples/ (historical captured SNS messages, which record TopsAuditSetup role ARNs as they were and are left as-is) and a gitignored .claude/settings.local.json entry

Quality gate

  • Acceptance criteria are met — all three on Audit CFN template defaults to the vendor's AWS account and is publicly served #102, including the recorded sync.sh decision
  • Solves the user problem simply — deletion beats maintaining an unexercised second copy
  • Follows the practices in docs/practices/
  • Tests written and passing
  • Documentation updated — the "Adjacent findings" entry in the feature doc records the reasoning
  • No obvious performance issues
  • Ready for production

Practices check

  • Security — removes a template that pointed a stranger's IAM trust at the vendor's account, and a script that set a bucket-wide public-read ACL
  • Simplicity — one child template instead of two, one of which nothing ran
  • Multi-tenancy — untouched
  • Database — no migrations
  • Scan definitionsscan:validate-rules passes (untouched)

Out of scope

  • Emptying storage.teemops.com. Only the bucket owner can do that, and it is not a repo change. Flagged above.
  • TopsMainSQSPolicy granting SQS:ReceiveMessage to Principal: "*" — the other adjacent finding in the feature doc. Dead permission in practice (the aws:SourceArn condition can never match a direct caller) but it reads badly in review. Not filed yet.

🤖 Generated with Claude Code

Base automatically changed from claude/github-issue-103-49098a to develop August 3, 2026 06:13
templates/iam.role.audit.account.cfn.yaml defaulted ParentAWSAccountId to
660228977852 -- Teem's own SaaS account -- and built the notifier's
ServiceToken from AWS::Region, the child's region, rather than from a
parent-region parameter. The sibling child template was fixed to take an
explicit ParentDeploymentRegion; this one never was.

Deployed with defaults it created a cross-account IAM role in the
operator's account trusting an account they do not control, carrying
ReadOnlyAccess plus securityhub:*, guardduty:*, macie:*, inspector:*,
config:Put*, CloudTrail and CloudWatch Logs writes, and iam:PassRole on
role/tops*.

Nothing in the product referenced it. install-messaging.sh uploads only
iam.role.child.account.cfn.yaml, and TOPS_CFN_TEMPLATE_URL points at that
same file, so it was never on the onboarding path -- it was reachable only
by a self-hosted operator browsing templates/ and picking the file whose
name matched what they wanted.

Deleted rather than repaired. A second, unexercised copy of the onboarding
template was itself the defect: it drifted through an entire
SaaS-to-self-hosted pivot without anyone noticing, because nothing ran it.
Repairing it would have restored exactly that condition.

templates/sync.sh goes with it. It ran

  aws s3api put-bucket-acl --bucket storage.teemops.com --acl public-read

and synced the whole directory with --acl public-read, which is what made
the broken template look canonical -- served from the vendor's domain next
to the one that works. Vendor-era publishing has no meaning in a
self-hosted install, where the installer uploads the template to the
operator's own deployment bucket. That answers the third acceptance
criterion on #102: storage.teemops.com should not be publicly readable on
this project's behalf, because this project no longer publishes to it.

Deleting the script does not un-publish what is already in that bucket.
Objects synced there previously stay public until removed by hand.

Also drops $topsType from ProcessSqsMessages, assigned and never read. It
distinguished "ops" from "audit", and nothing branched on it even while
the audit template existed.

The installer test now guards the whole templates/ directory against a
Default on ParentAWSAccountId, rather than the one file, so a future
template cannot reintroduce the defect.

Closes #102

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kiwifellows
kiwifellows force-pushed the claude/issue-102-remove-audit-template branch from 3279c0e to 05e11b9 Compare August 3, 2026 06:13
@kiwifellows
kiwifellows merged commit 8ef8c09 into develop Aug 3, 2026
3 checks passed
@kiwifellows
kiwifellows deleted the claude/issue-102-remove-audit-template branch August 3, 2026 10:14
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.

Audit CFN template defaults to the vendor's AWS account and is publicly served

1 participant