Wring Docs
Security

IAM Permissions in Detail

Every permission the Wring role carries, what it is used for, and what is explicitly denied.

This page documents the exact IAM footprint of the Wring Base stack (CloudFormation template v2.2) — the stack you launch when connecting an account. It is the full version of the access model: every allowed action mapped to the platform function that uses it, and everything that is permanently denied.

The Base stack is pure cost & usage reading. Optional capabilities — such as security checks or Wring Bedrock — ship as separate stacks with their own narrowly scoped roles, listed in the access model; you always review a level's permissions before launching it.

What the stack creates

ComponentName / patternPurpose
IAM roleWringCostAccess-{id}Cross-account role assumed by Wring
Allow policyWringAccess (inline)Four audited read-only permissions (below)
Deny policyWringDataProtectionPolicy-{id}Always active — blocks sensitive data access
EventBridge rulewring-callback-{id}Notifies Wring of stack lifecycle events
IAM rolewring-eb-sqs-{id}Lets EventBridge deliver those events to Wring's event bus (events:PutEvents on that one bus, nothing else)

Stacks created before September 2026 also contain a one-time Custom::WringStackNotification deploy-completion ping and deliver events to a Wring queue instead of the event bus; both variants keep working.

The trust relationship

Only Wring's platform account can assume the role, and only when it supplies your per-customer external ID — the standard protection against confused-deputy attacks. The role has no login profile and no access keys; access happens exclusively through short-lived STS sessions (15–60 minutes), each tagged and visible in your CloudTrail.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::{WRING_ACCOUNT_ID}:root" },
    "Action": ["sts:AssumeRole", "sts:TagSession"],
    "Condition": {
      "StringEquals": { "sts:ExternalId": "{YOUR_EXTERNAL_ID}" }
    }
  }]
}

Allowed: four read-only actions

Every action maps to a named platform function — nothing is granted "just in case".

Billing & cost data

ActionUsed for
ce:GetCostAndUsageDaily cost synchronization, savings calculation, connection validation
organizations:DescribeOrganizationDetect whether the account belongs to an AWS Organization
organizations:ListAccountsDiscover member accounts during onboarding (management accounts only)

Cost & Usage Report files

ActionUsed for
s3:GetObjectRead Cost & Usage Report files — restricted to CUR bucket naming patterns

S3 access is limited to Cost & Usage Report buckets. Report files are read directly by key; the role cannot even list bucket contents, and all other S3 object reads are explicitly denied (next section).

Denied: the data protection policy

A permanent explicit-DENY policy is always attached. In AWS IAM, an explicit deny always wins over any allow — so even a misconfigured future allow statement could not reach this data:

CategoryDenied actions
Secrets Managersecretsmanager:GetSecretValue, DescribeSecret
SSM Parametersssm:GetParameter, GetParameters, GetParametersByPath
Database datards-data:ExecuteStatement, BatchExecuteStatement · dynamodb:GetItem, BatchGetItem, Query, Scan
CloudWatch Logslogs:GetLogEvents, FilterLogEvents, GetLogRecord, StartQuery, GetQueryResults
Source codecodecommit:GetFile, GetBlob, GetDifferences, GetCommit, GitPull · codeartifact:GetPackageVersionAsset, ReadFromRepository
User identitiescognito-idp:AdminGetUser, ListUsers, AdminListGroupsForUser · cognito-sync:QueryRecords · iam:GetUser, ListUsers, ListAccessKeys
Instance accessec2-instance-connect:SendSSHPublicKey · ssm:StartSession, SendCommand
Queues & streamssqs:ReceiveMessage · kinesis:GetRecords, GetShardIterator · firehose:GetRecord · kafka:FetchTopic

Additionally, s3:GetObject is denied for every bucket that does not match Cost & Usage Report naming patterns — application data in S3 is unreachable regardless of any other policy.

The stack callback

So your account activates automatically, an EventBridge rule notifies Wring when CloudFormation finishes:

PropertyValue
WatchesOnly stacks whose name starts with Wring-, in the account and Region the stack was created in
EventsCreate/update/delete completions and failures
DeliveryWring's EventBridge event bus, via a role that can only events:PutEvents on that bus
RegionAny — the bus accepts events from every AWS Region, so you can create the stack wherever your policies allow

The event carries no secret: it is the unmodified CloudFormation status event, and AWS itself stamps the sending account. Before Wring activates an account it verifies that the new role trusts Wring under exactly your external ID — a role created for a different ID, or one without the ID condition, is refused. | Integrity | Events carry a per-customer signature; unsigned events are discarded |

No AWS managed policies

Earlier template versions attached AWS's managed AWSBillingReadOnlyAccess policy, which covers the entire billing console surface (payment methods, tax registrations, budgets, …). A least-privilege audit removed it: the explicit actions above cover everything the platform actually calls.

Both template revisions since then have narrowed the Base stack. The one grant ever added to it after that audit — read-only CloudWatch metrics, for the Bedrock usage dashboard — no longer lives here either: it moved into its own opt-in level, so an account that doesn't use Bedrock never grants it.

Design principles

PrincipleImplementation
Audited least privilegeEvery action maps to a named platform function
Explicit denyData protection policy cannot be overridden by any allow
External IDRequired on every cross-account role assumption
Read-onlyNo write, modify, or delete permission exists anywhere in the role
No standing accessNo users, passwords, or access keys — only short-lived STS sessions
Audit trailEvery role assumption and API call appears in your CloudTrail
No instance accessSSH, SSM sessions, and remote command execution are explicitly denied
Revocable by youDeleting the CloudFormation stack removes all access instantly

Questions about a specific permission? Ask [email protected] — we're happy to walk your security team through the template line by line.

On this page