Control Who Can Start and Stop Cloud Resources
Two layers decide who can switch a resource off: the cloud's own IAM, and the roles inside whatever tool runs your schedules.
Scheduling moves the power to stop a resource from a person to a timer, and to whoever can edit that timer. Access control therefore has two layers. The cloud layer decides which principals can call the stop and start APIs at all. The scheduler layer decides who can create schedules, attach resources to them and override them. This guide sets up both, with AWS as the worked example.
Layer 1: tag-conditioned IAM for start and stop
Grant the stop and start actions only on resources carrying an agreed tag. AWS’s own example for EC2 requires both a resource tag and a matching principal tag:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "StartStopIfTags", "Effect": "Allow", "Action": ["ec2:StartInstances", "ec2:StopInstances"], "Resource": "arn:aws:ec2:us-east-1:123456789012:instance/*", "Condition": { "StringEquals": { "aws:ResourceTag/Project": "DataAnalytics", "aws:PrincipalTag/Department": "Data" } } } ]}Both conditions must be true. AWS recommends attaching policies that use aws:PrincipalTag to IAM groups, for the case where some users carry the tag and some do not.
RDS has its own tag condition keys. rds:StopDBInstance and rds:StartDBInstance accept rds:db-tag/${TagKey}, and the cluster actions rds:StopDBCluster and rds:StartDBCluster accept rds:cluster-tag/${TagKey}. A statement allowing rds:StopDBInstance on arn:aws:rds:*:123456789012:db:* with "StringEquals": {"rds:db-tag/stage": ["development", "test"]} keeps staging and production databases out of reach.
Test before anyone relies on it
The IAM policy simulator evaluates a principal’s attached policies against specific actions and resources:
aws iam simulate-principal-policy \ --policy-source-arn arn:aws:iam::123456789012:role/dev-scheduler \ --action-names ec2:StopInstances ec2:StartInstances \ --resource-arns arn:aws:ec2:us-east-1:123456789012:instance/i-0abc1234def567890 \ --query "EvaluationResults[].{action:EvalActionName,decision:EvalDecision}"EvalDecision is allowed, explicitDeny or implicitDeny. Run it against one tagged and one untagged resource; the untagged one should come back implicitDeny.
The principal a scheduling tool uses to reach your account is the one that matters most. If it can stop everything, every user of the tool effectively can too, whatever their own IAM rights.
Layer 2: roles inside the scheduler
Write down the decisions before configuring anything:
- Who can create and delete schedules.
- Who can attach resources and groups to a schedule.
- Who can set an override that keeps something running past its stop time, or holds it off.
- Who can view history and reports but change nothing.
- Whether rights follow teams, so the payments team can only touch payments resources.
Mapping that to ZopNight
ZopNight enforces RBAC at its gateway, where every endpoint maps to a required policy. It ships three system roles: Admin (all policies across all resources), Editor (create, update and delete on resources, view-only on admin areas) and Viewer (view only). Custom roles pick individual policies, including schedule, override, resource-group, resource and state-history, and each resource-scopeable policy can be limited to specific resources instead of all of them. Team members inherit their role’s policies scoped to the resource UIDs assigned to their team, which covers decision 5 above. Pages a user cannot use show “Access restricted”. Every mutating request is written to the audit log with its request and response bodies.
The cloud layer still applies underneath: a read-only account connection gets discovery and recommendations, but start, stop and remediation only work on an account connected with read and write access. More on the model in role-based access control and audit trails.