Skip to content

Welcome

Welcome to Aegis Docs

These pages cover what Aegis is, how to use the tool, and additional reference materials.

Why Aegis?

Managing IAM permissions across an AWS organization is expensive, error prone, and rarely ever implemented securely. If you've ever been an IAM administrator, you might have experienced some of this pain.

Some of the reasons that contribute to making AWS IAM administration for an organization so expensive are:

  1. AWS has a huge API that is expanding faster than ever.
  2. It is often unclear what permissions are necessary to perform an operation or set of operations.
  3. Permissions are distributed over multiple policies attached to users or roles directly or indirectly, and even understanding what actions a user can perform either themselves or via a role they can assume can be a daunting task.
  4. It is expensive and slow to implement approval processes for IAM resources in an organization and IAM administrators quickly become the bottleneck in providing access for developers, and deployments.
  5. As users move from one job function to another, they tend to retain whatever legacy permissions they had. There is no easy way of determining which permissions they still require.

Aegis tackles these pain-points, augmenting the suite of AWS provided security services with a set of features designed to make managing IAM access within an AWS Organization more secure, and painless.

How Aegis Works

Privilege Deployment

Aegis enables users to configure AWS organization and IAM resources via a simple, declarative YAML configuration that can be chcecked into version control, and managed via pull requests.

The initial human readable configuration is created by directing Aegis to import your existing AWS IAM resources.

When users want to request additional permissions for themselves, they can modify the YAML configuration to add their new permissions. They can then submit a pull request against the master branch, that generates a change plan to be reviewed by an IAM administrator.

An IAM administrator can approve pull requests to have a continuous integration pipeline kick off to deploy new privileges.

This process enables engineers to propose privilege changes for themselves, enabling IAM administrators to simply process a queue of proposed changes rather than make all changes themselves.

Privilege Analysis

Aside from making it far easier to manage the process of requesting and deploying privileges in AWS, Aegis enhances the capability of IAM administrators to audit what actions users and roles are performing over time.

IAM administrators can generate access reports for users and roles within an AWS Organization. These reports detail:

  1. What privileges have recently been performed by users and roles
  2. What privileges have been granted to users and roles but can be removed
  3. What roles can be assumed by a user in an organization including cross-account roles
  4. What user / aws managed policies are attached either directly or via a group to a user or role.

These reports are designed to provide a path to identifying, and eliminating unused AWS privileges across an AWS organization.

Aegis Analyze vs AWS Access Analyzer

AWS released in December of 2019 Access Analyzer. Access Analyzer helps you identify entities trusted by your resource based policies outside of your AWS zone of trust (your AWS account). Aegis is geared to helping you understand access within your zone of trust and your organization.

By way of example: if you want to understand which AWS accounts can access your S3 bucket, access analyzer is the right tool for you. If, however, you want to understand who in your organization can perform what actions on what resources you own, Aegis privilege analysis makes this task achieveable.

We recommend you use AWS Access Analyzer to help ensure that your resource-based IAM policies are secure, and Aegis Privilege Analysis, to ensure that you can enforce zero-trust security within your organization.

Usage

Prerequisites

To prepare your AWS organization to use aegis to manage your account permissions you should perform the following steps:

AWS Requirements

  1. Create an aegis admin user to manage organization: and iam: privileges in the master account. The user should have the following policy attached, replacing placeholders with relevant values:
{
    "Statement": [
        {
            "Action": [
                "dynamodb:BatchGetItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:DeleteItem",
                "dynamodb:ListTagsOfResource",
                "dynamodb:Query",
                "dynamodb:UpdateItem",
                "dynamodb:DescribeTimeToLive",
                "dynamodb:DescribeTable",
                "dynamodb:GetItem",
                "dynamodb:DescribeContinuousBackups"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:dynamodb:${your-aws-region}:${your-aws-account-id}:table/aegis-lock",
            "Sid": "AllowAccessToLockTable"
        },
        {
            "Action": [
                "dynamodb:DescribeReservedCapacityOfferings",
                "dynamodb:ListGlobalTables",
                "dynamodb:ListTables",
                "dynamodb:DescribeReservedCapacity",
                "dynamodb:ListBackups",
                "dynamodb:PurchaseReservedCapacityOfferings",
                "dynamodb:DescribeLimits",
                "dynamodb:ListStreams"
            ],
            "Effect": "Allow",
            "Resource": "*",
            "Sid": "AllowDynamoDbDescribe"
        },
        {
            "Action": [
                "s3:PutObject",
                "s3:GetObjectAcl",
                "s3:GetObject",
                "s3:ListBucketMultipartUploads",
                "s3:AbortMultipartUpload",
                "s3:DeleteObjectVersion",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:GetBucketLocation",
                "s3:PutObjectAcl",
                "s3:GetObjectVersion"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::${organization-name}-cloudtrail*",
                "arn:aws:s3:::${organization-name}-cloudtrail*/*",
                "arn:aws:s3:::aegis-${organization-name}",
                "arn:aws:s3:::aegis-${organization-name}/*",
                "arn:aws:s3:::${organization-name-compliance-terraform-state",
                "arn:aws:s3:::${organization-name-compliance-terraform-state/*"
            ],
            "Sid": "AegisS3ReadWrite"
        },
        {
            "Action": [
                "athena:StartQueryExecution",
                "athena:StopQueryExecution",
                "athena:Get*",
                "athena:BatchGet*",
                "athena:List*",
                "glue:CreateDatabase",
                "glue:CreatePartition",
                "glue:CreateTable",
                "glue:CreateTable",
                "glue:CreateJob",
                "glue:BatchCreatePartition",
                "glue:Get*"
            ],
            "Effect": "Allow",
            "Resource": [
                "*"
            ],
            "Sid": "AegisAnalysisPrivileges"
        },
        {
            "Action": [
                "iam:*",
                "organizations:*"
            ],
            "Effect": "Allow",
            "Resource": [
                "*"
            ],
            "Sid": "PrivilegeModification"
        },
        {
            "Action": [
                "sts:AssumeRole"
            ],
            "Effect": "Allow",
            "Resource": [
                "*"
            ],
            "Sid": "AllowAegisMemberPrivilegeModification"
        },
        {
            "Action": [
                "ecr:GetAuthorizationToken",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability"
            ],
            "Effect": "Allow",
            "Resource": [
                "${aegis-ecr-repo-arn}"
            ],
            "Sid": "AllowAccessToAegisDockerContainer"
        }
    ],
    "Version": "2012-10-17"
}
  1. Create a role to manage iam:* resources in each member account for your organization. You should give this role the same name in each member account. We recommend using AegisMemberAccountRole as the name for these roles. You will use this name when you initialize your aegis project. These roles should have a trust policy that allows the organization account to assume them They should have . By default aegis uses OrganizationsAccountAccessRole (the default name AWS uses for the role used by the master account to manage the member account when creating an account from an organization) for this value.
  2. Use Service Control Policies / Permissions Boundaries, and / or IAM policies to prevent all IAM Principals from performing write actions related to AWS Organization and IAM resources. Aegis is meant to import values a single time, and then all permissions should be handled by using Aegis.

System Requirements

You will also need to install terraform 0.12.10+ and ensure it is added to your path. On a Macou can brew install tfswitch and use that tool to modify your version of terraform.

We have packaged this as a binary file. You can see how to create the binary later, but in order to use the binary aegis, you simply need to add it to your PATH. It packages all of its dependencies except for terraform. This is so that it can be used with future versions of terraform, as long as they are above 0.12.10. We may decide to bundle terraform in this binary at a later stage.

Initializing an aegis project

When creating a new aegis project, it is necessary to first configure aegis project settings. You can do this by creating a new folder and performing the following command from within it:

 aegis init

This command will prompt you to define a set of configuration options:

Usage: aegis init [OPTIONS] [PATH]

  Initializes an aegis project with necessary configuration.

Options:
  --organization TEXT             [required]
  --aegis-state-bucket TEXT       [required]
  --aegis-state-key TEXT
  --aegis-lock-table TEXT         [required]
  --member-account-role TEXT
  --aws-region TEXT
  --terraform-directory TEXT
  --reports-dir TEXT
  --athena-database TEXT
  --athena-query-result-location TEXT
                                  [required]
  --cloudtrail-logs-bucket TEXT
  1. The organization should be the name of your organization as a spinal cased string.
  2. The aegis state bucket should be an s3 bucket that can store the state of your IAM resources.
  3. The state key defaults to aegis.tfstate, but can be overridden if you need to use the same s3 bucket for multiple aegis state files.
  4. The aegis lock table should be a dynamodb table with a hash key named lockID. This is used to prevent concurrent changes to your privilege configuration.
  5. Your member account role is the role name defined in prerequisites step 2.
  6. Your aws region is the one where your s3 bucket is. Organization and IAM resources are generally global. It is also the place where your Athena resources are created
  7. terraform-directory is the local file where intermediate terraform assets are created.
  8. reports-dir is the location where privilege analysis reports are created locally.
  9. athena-database is the name of the database to store historical privilege access logs from cloudtrail.
  10. athena-query-result-location is the s3 location to store athena query outputs.
  11. cloudtrail-logs-bucket is the logs bucket with your Organization Cloudtrail logs inside.

Importing resources from an AWS Organization

When setting up an aegis project for your organization, you will need to synchronize the current state of your AWS resources with those defined in your aegis configuration. You should ensure that you have performed Prerequisites>Step##3 at this point.

To import resources from your AWS account, you will use the following command:

aegis import --aws-profile=my-aws-profile

Your aws profile is a profile in your aws credentials file you can specify. If this is not specified , AWS environment variables can be used to override these values at runtime. See the full list of these variables.

When you run this command, aegis iterates over all IAM and Organizations resources in your AWS account and creates a folder structure with YAML files that describes the current setup of your AWS account. These files together are called an Aegis Configuration.

It further imports each resource into a terraform statefile used under the hood to determine which resources need to be changed and when. It should be noted that this import process is incredibly slow error prone because of terraform's instability and lack of flexibility. To compensate for this, we have made this process idempotent, so if you need to kill the process in the middle and restart it because it hangs or because terraform doesn't realize that temporary credentials have expired you can do so. Because this process only needs to be run when you first start using aegis, we think this approach should be sufficient.

Once you have imported these resources, you should commit all files created to source control to represent the existing state of your infrastructure.

Understanding and Modifying your Aegis configuration

Aegis Configuration Structure

Once you have imported an organization, you will have the following folder structure created in the directory:

.
├── aegis.ini
├── master_account
│   ├── account.yaml
│   ├── groups
│   │   └── groups.yaml
│   ├── policies
│   │   └── policies.yaml
│   ├── roles
│   │   └── roles.yaml
│   └── users
│       └── users.yaml
├── member_accounts
│   ├── member-account-name-1
│   │   ├── account.yaml
│   │   ├── groups
│   │   │   └── groups.yaml
│   │   ├── policies
│   │   │   └── policies.yaml
│   │   ├── roles
│   │   │   └── roles.yaml
│   │   └── users
│   │       └── users.yaml
│   ├── Member-account-name2
│   │   ├── account.yaml
│   │   ├── groups
│   │   │   └── groups.yaml
│   │   ├── policies
│   │   │   └── policies.yaml
│   │   ├── roles
│   │   │   └── roles.yaml
│   │   └── users
│   │       └── users.yaml
|   ├──...
└── organization.yaml

Modifying privileges

In order to modify a configuration, simply clone the repository into the file you want to modify, add the accounts, users, policies, groups, or roles you want to add. Commit these changes to a branch or fork of the master repository, and submit a pull request against master.

Aegis Types Reference:

Organization

An Organization configuration is configured in the organization.yaml file in the root folder of your aegis configuration.

Sample Configuration:

%YAML 1.1
---
provider: aws.master
name: elementryx
feature_set: ALL
enabled_organizations_services:
  - cloudtrail.amazonaws.com
  - config-multiaccountsetup.amazonaws.com
  - config.amazonaws.com
organization_policies:
  - content: |-
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": "*",
              "Resource": "*"
            }
          ]
        }
    arn: arn:aws:organizations::aws:policy/service_control_policy/p-FullAWSAccess
    description: Allows access to every operation
    provider: aws.master
    id: p-FullAWSAccess
    name: FullAWSAccess
    policy_type: SERVICE_CONTROL_POLICY
    aws_managed: true
organization_roots:
  - arn: arn:aws:organizations::ORGANIZATIONACCOUNTID:root/o-ep81r3dpl0/r-epxr
    provider: aws.master
    organizational_units: []
    accounts:
      - _ref: AWSAccount.aws.master.elementryx__prototyping
      - _ref: AWSAccount.aws.master.aegis_test
    id: r-epxr
    name: Root
    policy_types:
      - status: ENABLED
        policy_type: SERVICE_CONTROL_POLICY
    policies:
      - {}
master_account:
    $ref: master_account/account.yaml
member_accounts:
  - $ref: member_accounts/aegis-test/account.yaml
AWSAccount

An AWSAccount configuration is configured in the master_account/account.yaml and in each of the member_accounts/member_account_name/account.yaml files.

Sample Configuration:

provider: aws.master
email: your@validemail.address
name: aegis-test
users:
    $ref: member_accounts/aegis-test/users/users.yaml
iam_policies:
    $ref: member_accounts/aegis-test/policies/policies.yaml
iam_roles:
    $ref: member_accounts/aegis-test/roles/roles.yaml
iam_groups:
    $ref: member_accounts/aegis-test/groups/groups.yaml
Role

A list of Role configurations is configured in the master_account/roles/roles.yaml and in each of the member_accounts/member_account_name/roles/roles.yaml files.

Sample Configuration:

  - name: my-aegis-test-role
    path: /
    description:
    assume_role_policy_document: |-
        {
            "Statement": [
                {
                    "Action": "sts:AssumeRole",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    }
                }
            ],
            "Version": "2008-10-17"
        }
    attached_policies:
      - _ref: arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
      - _ref: Policy.aws.master.my_new_policy
    permissions_boundary:
    tags: []
Group

A list of Group configurations is configured in the master_account/groups/groups.yaml and in each of the member_accounts/member_account_name/groups/groups.yaml files.

Sample Configuration:

  - name: an-aegis-test
    path: /
    attached_policies:
      - _ref: arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
      - _ref: Policy.aws.master.allow_s3_list
User

A list of User configurations is configured in the master_account/users/users.yaml and in each of the member_accounts/member_account_name/users/users.yaml files. Sample Configuration:

  - name: new-admin
    path: /
    permissions_boundary:
    tags: []
    groups:
      - _ref: Group.aws.master.my_second_test_group
      - _ref: Group.aws.master.my_test_group
Policy

A list of Policy configurations is configured in the master_account/policies/policies.yaml and in each of the member_accounts/member_account_name/policies/policies.yaml files.

Sample Configuration:

  - name: allow-s3-list
    description:
    path: /
    document: |-
        {
            "Statement": [
                {
                    "Action": [
                        "s3:ListAllMyBuckets",
                        "s3:ListBucket",
                        "s3:HeadBucket"
                    ],
                    "Effect": "Allow",
                    "Resource": "*",
                    "Sid": "VisualEditor0"
                }
            ],
            "Version": "2012-10-17"
        }

Attaching Policy to Groups, and Adding Users to Groups

When referencing other objects within your aegis configuration you will need to use _ref tags.

_refs are supported in the following scenarios:

  1. Attaching policies to roles and groups. Policy refs can be written as: _ref: Policy.aws.account-name.policy_name if you are referencing a policy managed within this configuration.

Alternatively if you are referring to a managed policy you can simply pass: _ref: arn:managedpolicyarnvalue 2. Adding users to groups. group references can be provided as: _ref: Group.aws.account_name.group_name 3. Adding AWS accounts to an organization. _ref: AWSAccount.aws.master.elementryx__prototyping

Note that in _ref definitions, every reference to another resource in the configuration must be defined using snake case. The exception to this is the type of referenced entity.

Planning changes to your AWS Privileges.

Simply make the desired changes to your yaml configuration, and execute from your project root:

aegis plan --aws-profile=my-aws-profile

Your aws profile is a profile in your aws credentials file you can specify. If this is not specified , AWS environment variables can be used to override these values at runtime. See the full list of these variables.

Deploying changes to your AWS Privileges

Once you are happy with your desired aegis plan, execute from your project root:

aegis deploy --aws-profile=my-aws-profile

Your aws profile is a profile in your aws credentials file you can specify. If this is not specified , AWS environment variables can be used to override these values at runtime. See the full list of these variables.

Managing a Secure Privilege Release Pipeline with Aegis

Background

We created aegis to help organizations define a process for delegating and releasing privileges across their organization. We've found that having one person or team manage privileges for everyone does not scale easily.

Instead, we recommend that you use a pull-request based workflow to manage permissions.

Process

An example process for a pull-request based workflow might resemble the following:

  1. Storing your aegis configuration in a version control system such as git as soon as you have run aegis import
  2. Pushing this configuration to a remote location such as GitHub or BitBucket with a branch master
  3. Granting read access to master and write access to branches starting with privilege-request/ to everyone who needs AWS permissions.
  4. Granting access to merge pull requests to designated approvers.
  5. Setting up an automated pipeline to invoke aegis plan whenever a pull request is submitted from a branch with privilege-request, and aegis deploy whenever a pull request is merged to master.

Using Bitbucket To Implement a Privilege Release Pipeline

  1. Create a bitbucket repository for your aegis config.
  2. Import your organization's resources into aegis and commit the created configuration to this repository.
  3. Create a bitbucket pipeline with the following contents in your bitbucket-pipelines.yml
  image: 
    name: 055571234181.dkr.ecr.us-east-1.amazonaws.com/aegis:latest
    aws: 
      access-key: $AWS_ACCESS_KEY_ID
      secret-key: $AWS_SECRET_ACCESS_KEY

  pipelines:
    pull-requests:
      privilege-proposal/*: ##any branch with a privelege proposal prefix
        - step:
            name: Aegis Plan
            script:
              - aegis plan
    branches:
      master:
        - step:
            name: Aegis Deploy
            script: 
              - aegis deploy
  1. Create a system user to your master account in AWS IAM. Grant the user programmatic credentials, and access to iam:, organizations:, sts:assumeRole for your member account roles, and read and write access to your dynamodb lock table and s3 backend bucket.
  2. Navigate to your bitbucket repository settings, and select Repository Variables in the left menu.
    1. set AWS_ACCESS_KEY_ID to the appropriate value.
    2. set AWS_SECRET_ACCESS_KEY to the appropriate value, and ensure you have selected the secured checkbox.
  3. Navigate to Branch Permissions in the left menu.
    1. Select the master branch
    2. Add authorized approvers access to merge pull requests into the master branch.
    3. Grant everyone else write access to branches with prefix: privilege-request/*.

Requesting a Change to Privileges

  1. Clone the configuration repository.
  2. Checkout a new branch named privilege-request/<your-request-summary>.
  3. Make your changes and validate them by executing aegis plan --aws-profile <your-aws-read-only-profile>
  4. When you are happy with the changes commit them to the branch.
  5. Push the branch to the remote.
  6. Open a pull request against master, requiring the feedback from 1 or more approvers. A plan will automatically be executed by the pipeline.

Reviewing and Approving Changes to Privileges

When a pull request is assigned to you: 1. View the commit. 2. Verify the privileges are acceptable. 3. Verify that the pipeline successfully built the pull request. 4. Merge the pull request into master. 5. Verify that the deployment step triggered by the merge successfully executes.

Integrating your Terraform Workflow with Aegis

If you use Terraform to manage your AWS infrastructure and these scripts has IAM resources scattered throughout, you will need to migrate management of these resource to Aegis.

There are two primary dependencies between aegis and terraform templates:

  1. Often IAM policies will require resource blocks that reference arns of resources created in terraform templates. This makes the aegis configuration dependent on the Terraform template.
  2. Often resources created in terraform templates require an attached IAM role. This makes the terraform template depend on the aegis configuration.

As such a seeming circular dependency between terraform and aegis executions makes it important to define careful procedure to enable secure development on AWS with limited pain.

We therefore recommend the fo following procedures:

  1. Import organization into aegis.
  2. IAM resources definitions should be removed from Terraform configuration and terraform state management.

    See terraform state rm

  3. Manage all future changes to IAM privileges through a code based IAM workflow within aegis and revoke access to all users with permissions to create and update any of the resources managed by aegis.
  4. Always create privilege changes in aegis before infrastructure changes in terraform. Because IAM policies are evaluated dynamically, it is possible to define an IAM policy for resources that have not yet been created. If you need to refer to a resource not yet created in terraform, you can do so by either of the following two methods:
  5. simply construct the arn manually as you define your IAM policy. Your IAM policy can then be created with aegis, freeing you up to execute your terraform changes.

    Note: For disaster recovery, ensure that there is no randomness possible in your resource arns. Usually, this means using using a deterministic resource name and resource path. This practice allows you to recover from disaster by using aegis to restore your IAM resources, and then once your IAM state is restored, use terraform scripts to recreate your infrastructure.

  6. Restrict policy access based on resource tags rather than resource blocks. (Note Not all actions can restrict access based on resource tags.).

    Note: Although it is easier to use terraform's resource references and dependency graph to create terraform resources, we recommend you do not allow users to create IAM resources with your regular terraform templates. For little effort to your developers, aegis provides you the security of being able to see all your privileges in one place and put a rigorous approval process to enable you to approve and track privilege changes over time.

Analyzing AWS Privileges Within Your Organization

Once you have imported your privileges into aegis you can use aegis analyze to start analyzing privilege utilization. Your aegis schema defining the state of current privileges can be compared against the actual IAM usage of users and roles to generate reports detailing:

  1. What privileges have recently been performed by users and roles
  2. What privileges have been granted to users and roles but can be removed
  3. What roles can be assumed by a user in an organization including cross-account roles
  4. What user / aws managed policies are attached either directly or via a group to a user or role.

In order to run analyses you can run, aegis analyze

Usage: aegis analyze [OPTIONS] [PATH]

Options:
  --aws-profile TEXT
  --account TEXT
  --role TEXT
  --user TEXT
  --detailed / --summary
  --help                  Show this message and exit.

When you do not specify account, user, or role, analyses are generated for all roles and all users in all accounts. You can target specific accounts to generate analyses only for these accounts by passing the account name to the --account option.

If you have specified an account, you can further target either roles or users by specifying a pattern to limit which roles or users will be analyzed. Patterns consist of a case insensitive set of characters interspersed with a wildcard *. For instance, to generate a report for all users with names starting with a in the master account, execute aegis analyze --account master --user a*

By default, a summarized report which does not specify all allowed or unused actions for a user is generated. This summarized report does include some high level statistics including how many actions a user can perform and how many of them have been unused recently. To generate more detailed reports which take longer, you can add the --detailed flag to the query. aegis analyze --account master --user adam --detailed will generate a detailed report for user adam in the master account.