No. Give build, test and deploy their own roles, because they need very different access and face different risk. The job that runs untrusted dependency code should not hold the permission to change production. Separate roles also make logs and reviews easier.
The problem with one shared role
A single CI role is convenient and it grows. Someone adds storage permissions for a build, then database access for an integration test, then deploy rights for a release. A year later one role can do everything, and every pipeline step runs with all of it. A compromised test dependency inherits production reach.
AWS's best practices page recommends least privilege: only the permissions required for a task, on specific resources, under specific conditions. A shared role cannot satisfy that, because the tasks differ.
A simple role map
| Role | Used by | Needs | Should not have |
|---|---|---|---|
| Build | Compile and package | Write to the artifact prefix, read dependency cache | Any production access |
| Test | Integration tests | Access to test resources only | Production data, artifact delete |
| Plan or diff | Pull request checks | Read only on target stack | Any write action |
| Deploy | After merge, on a protected environment | Update named resources, pass named roles | Permission to edit IAM policies |
Not every team needs all four. Two is a good start: a low privilege role for everything before merge and a deploy role for after merge.
How trust keeps the split real
A role map is only real if the trust policy enforces it. Use the CI token's subject to tie each role to the right job. For GitHub, a pull request event and a job that references an environment produce different subjects, per GitHub's documentation. Trust the pull request subject for the read only role, and the environment subject for the deploy role. Add required reviewers on that environment, since GitHub notes a job cannot access environment secrets until a reviewer approves.
On GitLab, the ref_protected claim lets the deploy role be assumed only from protected branches or tags.
Separate accounts as an extra wall
AWS recommends separating workloads into multiple accounts managed with AWS Organizations and using service control policies to set permissions guardrails across accounts. AWS also stresses that these policies grant nothing on their own. They only limit what identity and resource policies can allow.
For CI this means a test account whose roles cannot touch production, and a production account with a deploy role that only the protected environment can reach. A mistake in the test role then has a limited blast radius.
Steps to split an existing role
- Export the current role's permissions and list which pipeline step uses each.
- Use last accessed information or Access Analyzer to find unused permissions and drop them.
- Create the pre merge role first, with only read and test permissions.
- Point pull request workflows at it and run them.
- Create the deploy role with scoped write access and an environment bound trust policy.
- Move deploy jobs to it, then remove deploy permissions from the old role.
- Delete the old role when CloudTrail shows no activity.
Cost of splitting
More roles mean more things to name and document. Use a clear naming scheme that includes the repository and purpose. Keep the definitions in code so changes are reviewed. The extra effort is small next to untangling a role that has become an administrator in disguise.
Quick check
Is a separate deploy role worth it for a small team?
Yes. Two roles, one for pre merge checks and one for protected deploys, remove most of the risk with little extra work.
Do service control policies grant permissions?
No. AWS says they only set guardrails. You still attach identity or resource policies to grant access.
Safeguard does not manage your cloud accounts. It scans your code and dependencies, applies pull request policies and gates, and automates compliance evidence. Free scan: gold.safeguard.sh/scan.
Sources
- AWS IAM User Guide: Security best practices in IAM
- GitHub Docs: OpenID Connect reference
- GitHub Docs: Secure use reference
- GitLab Docs: ID token authentication
Last reviewed: 19 October 2026.