You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
templates/iam.role.child.account.cfn.yaml asks every customer for write access across eight AWS services. Nothing in TOPS uses any of it.
TOPS instantiates only StsClient, SnsClient and SqsClient. There is no Security Hub, GuardDuty, Macie, Inspector, Config or CloudTrail client code in the repository.
All 36 operations declared across app/rules/tasks/*/tasks.json are list, get or describe. Zero mutate anything.
So the role is provisioned for operational features that do not exist. This is the largest remaining objection in a vendor review: a reviewer reaches securityhub:* on Resource: "*" and stops reading, and we have no answer beyond "we might build something one day".
Unchanged — TopsPassRole, TopsCloudFormationAccess, TopsCloudFormationListAccess, TopsCloudTrailTrail, and the separate TopsCWEventRole.
Do it properly: those 11 policies probably vanish too
After trimming, each Logs and Config policy retains exactly one Describe action — and ReadOnlyAccess is already attached to this role. If it grants logs:Describe* and config:Describe*, all 11 are dead weight and the inline policies should be deleted entirely rather than left as one-action husks.
If they are covered, 21 policies → 4, which is a much better story than 15.
Three decisions this exposes
TopsS3Bucket is probably orphaned. Its comment says it exists "to create an S3 bucket for Config delivery". With Config read-only there is no delivery channel to create, so s3:CreateBucket / s3:DeleteBucket on arn:aws:s3:::tops-config-* have no remaining purpose. Remove?
TopsPassRole may be orphaned for the same reason.iam:PassRole on arn:aws:iam::*:role/tops* exists to hand a service role to Config's recorder or delivery channel. Nothing else passes a role. Remove?
CloudTrail keeps StopLogging and DeleteTrail. Agreed to keep, and noting it once rather than relitigating: these two are what a reviewer flags hardest, because anyone who can assume the role can disable audit logging in every linked account. If the trails are only ever read, the same read-only treatment would apply. Worth a deliberate yes.
Acceptance criteria
Given the trimmed template, when a child stack is created, then the role carries no securityhub, guardduty, macie or inspector permission at all
Given the trimmed template, when a child stack is created, then no logs: or config: write action is granted
Given each retained read action, when checked against ReadOnlyAccess, then it is deleted if already covered rather than left in place
Given an existing linked account, when the stack is updated to the new template, then it updates cleanly rather than requiring a delete and re-link
Given a scan against an account on the trimmed role, then it completes and returns the same findings as before — this is the test that proves nothing depended on the write half
The template is served from each operator's own S3 bucket, so trimming it does not change any role already created. Existing linked accounts keep the wider role until their stack is updated. Worth saying explicitly in the release notes — an operator who read the old docs may reasonably assume the change is retroactive.
Size: S · Found 2026-08-02 while writing
user-docs/aws-accounts/what-the-iam-role-can-do.md. Scope agreed 2026-08-03.Problem
templates/iam.role.child.account.cfn.yamlasks every customer for write access across eight AWS services. Nothing in TOPS uses any of it.StsClient,SnsClientandSqsClient. There is no Security Hub, GuardDuty, Macie, Inspector, Config or CloudTrail client code in the repository.app/rules/tasks/*/tasks.jsonarelist,getordescribe. Zero mutate anything.So the role is provisioned for operational features that do not exist. This is the largest remaining objection in a vendor review: a reviewer reaches
securityhub:*onResource: "*"and stops reading, and we have no answer beyond "we might build something one day".Agreed scope
What that works out to
21 inline policies → 15. 66 actions → 34 kept, 32 dropped. Six policies disappear entirely.
Removed outright —
TopsSecurityHub,TopsGuardDuty,TopsMacie,TopsInspector(securityhub:*,guardduty:*,macie:*,inspector:*, allResource: "*"), plusTopsCloudWatchLogEvent(logs:PutLogEvents, nothing left after trimming).Trimmed to read — drop the write half of each, keep the
Describe:TopsCloudWatchLogGrouplogs:CreateLogGroup,logs:DeleteLogGroupTopsCloudWatchLogStreamlogs:CreateLogStream,logs:DeleteLogStreamTopsCloudWatchLogMetricFilterlogs:PutMetricFilter,logs:DeleteMetricFilterTopsConfigRuleconfig:PutConfigRule,config:DeleteConfigRuleTopsConfigConfigurationRecorderconfig:PutConfigurationRecorder,config:DeleteConfigurationRecorderTopsConfigDeliveryChannelconfig:PutDeliveryChannel,config:DeleteDeliveryChannelTopsConfigConfigurationAggregatorconfig:PutConfigurationAggregator,config:DeleteConfigurationAggregatorTopsConfigConfigurationSnapshotconfig:StartConfigurationRecorder,config:StopConfigurationRecorderTopsConfigConformancePackconfig:PutConformancePack,config:DeleteConformancePackTopsConfigRemediationConfigurationconfig:PutRemediationConfigurations,config:DeleteRemediationConfigurationsTopsConfigRemediationExceptionsconfig:PutRemediationExceptions,config:DeleteRemediationExceptionsUnchanged —
TopsPassRole,TopsCloudFormationAccess,TopsCloudFormationListAccess,TopsCloudTrailTrail, and the separateTopsCWEventRole.Do it properly: those 11 policies probably vanish too
After trimming, each Logs and Config policy retains exactly one
Describeaction — andReadOnlyAccessis already attached to this role. If it grantslogs:Describe*andconfig:Describe*, all 11 are dead weight and the inline policies should be deleted entirely rather than left as one-action husks.Check before writing the trimmed version:
If they are covered, 21 policies → 4, which is a much better story than 15.
Three decisions this exposes
TopsS3Bucketis probably orphaned. Its comment says it exists "to create an S3 bucket for Config delivery". With Config read-only there is no delivery channel to create, sos3:CreateBucket/s3:DeleteBucketonarn:aws:s3:::tops-config-*have no remaining purpose. Remove?TopsPassRolemay be orphaned for the same reason.iam:PassRoleonarn:aws:iam::*:role/tops*exists to hand a service role to Config's recorder or delivery channel. Nothing else passes a role. Remove?StopLoggingandDeleteTrail. Agreed to keep, and noting it once rather than relitigating: these two are what a reviewer flags hardest, because anyone who can assume the role can disable audit logging in every linked account. If the trails are only ever read, the same read-only treatment would apply. Worth a deliberate yes.Acceptance criteria
securityhub,guardduty,macieorinspectorpermission at alllogs:orconfig:write action is grantedReadOnlyAccess, then it is deleted if already covered rather than left in placetests/install-messaging.test.shstill passesuser-docs/aws-accounts/what-the-iam-role-can-do.mdand the permissions section ofuser-docs/start-here/how-tops-connects-to-aws.mdboth currently say nothing uses the write half; after this they describe what is actually grantedNote on existing installs
The template is served from each operator's own S3 bucket, so trimming it does not change any role already created. Existing linked accounts keep the wider role until their stack is updated. Worth saying explicitly in the release notes — an operator who read the old docs may reasonably assume the change is retroactive.