Having security controls in place is no longer the only consideration when assessing one’s risk factors. Even when security controls are implemented, they’re often not appropriately permissioned. For example, it’s not uncommon for critical service-level accounts to be given excessive system privileges. This increases attack vectors within a system should that account be compromised. This compromised account could then execute malicious code or access very sensitive data that could present any number of issues for an organization. One way to prevent these types of security incidents is to implement the concept of Principle of Least Privilege. The Principle of Least Privilege means giving an account only those privileges which are essential to perform its intended function. For example, a service account for the sole purpose of reading files from an Amazon S3 bucket does not need to write files to the bucket. Any other privileges, such as listing, updating or writing files are blocked. Accounts with minimal privileges protect systems from being exploited by compromised accounts that have too many privileges.

In this post I’m going to show you how to tighten up the permissions on your AWS IAM CircleCI Service account so that it only has access & permission to a /build folder in a specific AWS S3 Bucket. These permissions will restrict this account to only operate on the /build folder and prevents access to other resources.

This post assumes you have:

Identify\Create an AWS S3 bucket to hold your builds

You’ll need to identify an existing S3 bucket or create a new bucket for your CircleCI service account to access. My example S3 bucket name is You can name your S3 bucket whatever you like, but a common, and best, practice is to name buckets using the familiar Fully Qualified Domain Names (FQDN) format which will help keeps things straight as your infrastructure grows. The devops. portion of my bucket signifies that this bucket will be related to devops processes for my domain.

Now that you have a bucket, go ahead and create a folder called builds which will hold all of the build artifacts that are generated by the CircleCI build.

Create a new IAM Group

AWS IAM has a concept of Groups which is a collection of IAM users and enables you to set permissions for multiple users. These Groups ease the management of users & their permissions.

From the IAM Console:

  • Click Groups > Create New Group button.
  • Specify a New Group Name. Use a meaningful descriptive name. I’ll be using circleci_devops.
  • At the Attach Policy screen > click Next Step.
  • Click Create Group button.

You should now see your newly created group in the list.

Create IAM Policy

IAM Policies are AWS entities that are associated with identities or resources which define their permissions. AWS evaluates these policies when a principal, such as a user, makes a request. Permissions in the policies determine whether the request is allowed or denied. Policies are stored in AWS as JSON documents attached to principals as identity-based policies, or to resources as resource-based policies.

AWS basically has two categories of policies: managed policies and inline policies.

Managed policies are standalone identity-based policies that you can attach to multiple users, groups, and roles in your AWS account. You can use two types of managed policies:

  • AWS managed policies: These are managed policies that are created and managed by AWS.
  • Customer managed policies: Managed policies that you create and manage in your AWS account. Customer managed policies provide more precise control over your policies than AWS managed policies.

Inline policies are policies that you create and manage and that are embedded directly into a single user, group, or role.

In this post you’re going to create a new customer managed policy because we want to restrict our service account user’s access to the build folder in our bucket.

In the IAM Console:

  • click Policies > click Create Policy
  • click the JSON tab
  • Paste the following JSON AWS Policy into the text field > click Review Policy


You must replace the bucket name in the the following JSON with the name of the bucket you created earlier. So the bucket name must be replaced with your bucket name in all instances of the text, otherwise the account will not be able to access the S3 bucket.

    "Version": "2012-10-17",
    "Statement": [
            "Effect": "Allow",
            "Action": [
            "Resource": "arn:aws:s3:::*"
            "Effect": "Allow",
            "Action": [
            "Resource": ""
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
  • Enter a name for the policy. My example uses s3_full_access_devops_builds.
  • Enter a description of the policy.
  • Click > Create Policy.

The policy you just created basically permits full access to the build folder in our S3 bucket which equates to read/write permission for this folder only.

Attach New Policy to the IAM Group

The new s3_full_access_devops_builds policy is ready to be attached to the circleci_devops IAM group we created earlier. In the AWS IAM Console:

  • Click Groups > click Permissions tab.
  • Click Attach Policy button.
  • Type s3_full_access_devops_builds or the name of your policy in the filter field.
  • Check the policy you want to attach in the list.
  • Click Attach Policy button.

The new policy is now attached to the circleci_devops group and will be applied to any users assigned to the group.

Create new IAM User

You’ve created a new IAM group an IAM customer managed policy and you’ve also attached the policy to the group. Next you’ll create a new user and assign it to the circleci_devops group which will grant that account read/write privileges in the bucket’s S3 build folder.

In the AWS IAM Console:

  • Click Users > click Add User button.
  • Enter a name in the User Name text field. My example user is circleci_service.
  • Check the Programmatic access option in the Access Type section.
  • Click Next Permissions button.
  • Check the circleci_devops option in the Add user to group section.
  • Click Next: Review button > click Create User button.

You should now see a Success! Account created… message and here you must capture the account’s Access Key ID and Secret Access Key.


The Access Key ID and Secret Access Key values are extremely sensitive and must be protected. You have to the ability to download these credentials in the form of a .csv but be aware this will be the ONLY time you’ll be able to access the Secret Key. If you don’t save the key at this time or lose the key you will have to create new keys and manage the previously created keys.

Configuring AWS IAM Keys in CircleCI Project

You created a new programmatic user that only has read/write access to the build folder in your S3 bucket and now you must associate this account to the project in your CircleCI account. Log into the CircleCI Console Dashboard. Below are brief directions to associate the AWS IAM credentials and you can also see a more detailed set of directions here

  • click the Settings (cog button) for the project you want to link the IAM account
  • Find Permissions section > click AWS Permissions
  • Enter your Access Key ID and Secret Access Key > click Save AWS Keys button

Your IAM account keys are now saved in the CircleCI project and you will now have read/write access to the build\ folder in your S3 bucket. Your CircleCI builds can now securely upload build release packages to your S3 bucket.

Now you can safely manage and use these AWS Credentials to perform specific actions on strictly defined resources.


This post briefly explains the concept of Principle of Least Privilege and shows you how to implement the practice into your CI\CD pipelines. These concepts will dramatically minimize security risks & attack vector in the event that IAM credentials are compromised. These practices are also very help for user management, incident management and security audits.

Now that you have a basic understanding of Principle of Least Privilege, go forth and compute responsibly!