Your clients keep the keys. AWS keeps the boundary.
CloudDeck never holds your clients’ AWS credentials. It reaches each account through a role the client creates, can inspect, and can delete, and that role can only change the servers they’ve tagged.
What happens when a client presses Reboot
1 · Client user
Signs in to your branded portal and presses Reboot on web-01.
2 · CloudDeck
Checks their role (owner, admin, operator or viewer), rate limits, and writes the audit entry.
3 · AWS STS
Issues CloudDeck 15-minute credentials for the client’s role, only when the ExternalId matches.
4 · Client’s AWS account
Evaluates the role’s policy: web-01 carries clouddeck:managed=true, so RebootInstances is allowed.
The tag condition is in the role’s own policy
The CloudFormation template your client deploys gives CloudDeck read access to describe EC2, and write access only where AWS can check the clouddeck:managed tag first:
- start, stop and reboot
- terminate
- tag edits (and the role can never write or delete clouddeck:* tags itself)
- attaching and detaching volumes during a snapshot restore
The portal checks the same tag before it calls AWS, so a refusal is a clear message rather than an error, but the policy is the part that holds even if our code were wrong.
# Trust: only CloudDeck, only with this client's ExternalId
Condition:
StringEquals:
sts:ExternalId: !Ref ExternalId
# Power: only servers the client has tagged
- Sid: EC2PowerOps
Action: [ec2:StartInstances, ec2:StopInstances, ec2:RebootInstances]
Condition:
StringEquals:
aws:ResourceTag/clouddeck:managed: 'true'
# CloudDeck can't grant itself scope
- Sid: DenyInstanceReservedTagWrites
Effect: Deny
Action: [ec2:CreateTags, ec2:DeleteTags]
Condition:
ForAnyValue:StringLike:
aws:TagKeys: ['clouddeck:*']Where the boundary is softer, today
Graceful OS shutdown and ISO mounting run through AWS Systems Manager. The role’s ssm:SendCommand permission is not yet limited to tagged servers in the policy; the portal enforces it instead. If that matters for a client, they can leave the SSM agent off servers CloudDeck shouldn’t reach, and power and snapshot features keep working.
We’ll update this page when the policy covers SSM as well.
What CloudDeck stores
Stored
- Tenant name and branding (name, logo URL, colours)
- The client’s role ARN and ExternalId
- Portal users: email, role and tenant
- The audit log: who did what, to which resource, when, and from which IP address
Never stored
- AWS access keys or secret keys, ever
- Instance contents, disks or snapshots: those stay in the client’s account
- Metrics history: it’s read from CloudWatch when a page asks for it
Inside the portal
- Tenant isolation
- Each tenant’s rows live in a dedicated Postgres schema with row-level security forced on every table. Server code resolves the tenant from the signed-in user, never from the request.
- Browser hardening
- A per-request nonce Content-Security-Policy with strict-dynamic, HSTS with preload, and origin checks on every state-changing request.
- Rate limits
- Database-backed limits per tenant and per IP, so they hold across every serverless instance.
- Least privilege inside the portal
- Termination needs an admin or owner and the server’s exact name typed back. Viewers can look but not touch.
Found a security issue? Tell us through the contact form and we’ll respond before anything is made public.
Book a demo