Table of contents

This documentation is intended for internal use by the GDS community.

Amazon Web Services (AWS)

Several teams in GDS use Amazon Web Services (AWS) as their infrastructure provider. GDS teams manage their own AWS accounts, but users must first sign into a shared base AWS account managed by the Reliability Engineering team.

Access AWS Accounts

People joining GDS do not automatically have access to Amazon Web Services (AWS). To grant a user access to AWS you’ll need to add them to the gds-users base account.

To add a user to the gds-users base account, complete the Request user access section of the request an AWS account form form.

After a user is added to the GDS base account it’s the individual teams’ responsibility to grant that user access to any team specific roles.

Once setup is complete users can access AWS using the AWS Console or the command line.

Use AWS Console

  • Sign in to the GDS base account at: https://gds-users.signin.aws.amazon.com/console
    Screenshot of the sign in page Screenshot of the sign in page
  • From the top right dropdown menu, select Switch Role
    Screenshot of the switch role menu item Screenshot of the sign in page
  • Complete Account with account or account alias and the role you’re switching to
    Screenshot of the switch role page Screenshot of the sign in page

Teams manage their own lists of accounts and roles, for example GOV.UK, Verify, and Digital Marketplace.

Use the command line

There are several command line tools you can use to work with AWS, such as:

These tools need credentials to access AWS. We recommend using aws-vault to manage your credentials.

Installing aws-vault

aws-vault needs to be installed and available on your PATH. Follow their instructions to do this.

Add your credentials to aws-vault

To add your credentials to aws-vault, run the command aws-vault add gds-users. This will prompt you for your Access Key ID and your Secret Access Key, and then create a new keychain to store these - you will be prompted to set a passphrase for this new keychain. Once done you should see the message:

Added credentials to profile "gds-users" in vault

You can find your aws_access_key_id and aws_secret_access_key by logging into the GDS base account using the AWS console.

AWS has more instructions for creating, modifying, and viewing Access Keys (Console) to do this.

Setup cross-account profile access

For each role you need to assume, add a section like the following to ~/.aws/config:

[profile target-account]
source_profile = gds-users
region = eu-west-1
role_arn = <role arn>
mfa_serial = <mfa device arn>

<role arn> - is from your team’s list of accounts and roles, for example GOV.UK, Verify, and Digital Marketplace.

<mfa device arn> - is your user’s assigned Multi-Factor Authentication (MFA) device.

How to find your MFA device ARN
  • sign into the GDS base account using the AWS console
  • navigate to IAM > Users > $your-user
  • select the Security credentials tab
  • look for the Assigned MFA device
  • Once this is all in place, you should be able to run aws-vault list and see output something like:

    Profile                  Credentials              Sessions
    =======                  ===========              ========
    gds-users                gds-users                -
    target-account           gds-users                -
    

    Use aws-vault to invoke commandline tools

    You can now use aws-vault exec to invoke the AWS CLI or other tools (eg Terraform) as follows:

    aws-vault exec target-account -- aws sts get-caller-identity
    

    aws-vault will prompt you for the passphrase that you set above to unlock the store (if it hasn’t been accessed recently), and then prompt for your MFA token.

    Optional: add some shortcuts to your shell config

    If you find the above aws-vault exec ... invocation too verbose, you can add something like the following to your shell startup script:

    for profile in $(awk '/^[profile / { gsub("]", "", $2); print $2 }' ~/.aws/config); do
      alias "aws-${profile}"="aws-vault exec ${profile} --"
    done
    

    This sets up an alias for each profile in your ~/.aws/config so that you can then invoke AWS commands as follows:

    aws-target-account aws sts get-caller-identity
    aws-target-account terraform plan
    etc...
    

    Create AWS Accounts

    GDS teams can request as many AWS accounts as required, for example one production and one non-production account.

    Using multiple AWS accounts allows GDS teams to:

    • enforce administrative isolation between workloads
    • minimize the impact of security breaches
    • isolate audit data in separate accounts

    AWS Answers has more information about AWS Multiple Account Security Strategy.

    Request an account

    To request an AWS account complete and submit the request an AWS account form.

    Reliability Engineering will confirm if your account can be included in GDS AWS billing and perform the initial account setup.

    Once your account is created you’ll receive an email with the account ID and will be able to assume an administrative role from the GDS users base account.

    Set up an account

    Your new account will come with a GDS created bootstrap role which has full admin rights.

    All users in the Request an AWS account form will be able to assume the bootstrap role from the GDS users base account.

    You should use the bootstrap role to set up your new account following your team’s best practices, for example using Terraform.

    As part of your account setup, ensure your users can assume roles with permissions relevant to their role.

    Remove the bootstrap role once you’ve added a properly configured admin role.

    Manage AWS accounts

    If you’re setting up a new AWS account and your team want to use cross-account access use the gds-users account as your base account.

    Use multiple AWS accounts to:

    • enforce administrative isolation between workloads
    • minimize the impact of security breaches
    • isolate audit data in separate accounts

    By having separate AWS accounts for production and test workloads teams can restrict the security impact of a compromised AWS credential.

    To avoid managing several sets of AWS credentials for multiple accounts, teams should use roles and cross-account access. AWS describe this approach as multiple account security strategy.

    Cross account access

    AWS cross account access allows user accounts held in the gds-users base account to access resources in target AWS account’s created by your team.

    Access to resources within a target AWS account is controlled using AWS Identity and Access Management (IAM) roles managed within that AWS account.

    IAM roles establish trust relationships between the target’s (trusting) AWS account and the GDS base (trusted) AWS account.

    Manage Access to Resources

    Users exist in the GDS base account and have permission to assume a role into a target account. The target account defines the roles users in the base account can assume, for example a Data Analyst:

    Assume Role Diagram

    The Trust Relationship (Assume Role Policy)

    The trust relationship describes what entities can assume the role (principles) and imposes conditions on how and when those entities can assume the role. An AWS principle can be a user account, an AWS account or a role, principle entities are expressed as an Amazon Resource Name (ARN).

    Use conditions to enforce the presence of Multifactor authentication (MFA), for example restricting access to particular IP addresses or particular times of the day.

    It’s strongly recommended not to trust an AWS base account. Trusting an AWS base account allows all of the entities within that base account to assume that particular role.

    Example Trust Relationship policy:

    {
      "Version": "2012-10-17",
      "Statement": {
        "Effect": "Allow",
        "Principal": { "AWS": "arn:aws:iam::123456789012:user/example.user@digital.cabinet-office.gov.uk" },
        "Action": "sts:AssumeRole",
        "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } }
      }
    }
    

    Resource Permissions (Policies)

    Access to resources are managed through IAM Policies which can be custom built or defined by Amazon. Design your roles around the permissions people need to complete a task.

    Amazon provides some examples of AWS policies related to IAM permissions.

    Manage “admin” permissions

    It is strongly recommended that anyone supporting an AWS account in an engineering capacity should have admin access. Admin access should allow an engineer to completely recreate any given resource running in the account.

    In AWS one can restrict access to resources by only allowing only certain permissions:

    data "aws_iam_policy_document" "admin" {
      statement {
        actions = [
          "route53:",
        ]
         resources = [""]
        effect    = "Allow"
      }
    }
    

    This should be done where we do not want services to be run for proprietary service proliferation reasons, not for security reasons. The use case for this is so that we can manage what AWS services we consume, for instance not allowing people to spin up an AWS Neptune database.

    Services can be managed at the organisation level using service control policies, but this is not something we currently use. More information can be found here.

    It is an anti-pattern for administrators to not have full IAM permissions. The reasoning behind this decision is that it prevents untracked access to things. However in practice it leads to the use of shared users and roles rather than the creation of a single user and/or role for a given purpose, which violates the principle of least privilege.

    Name IAM roles

    For IAM roles attached to human IAM users, they should have descriptive names and ideally conform to the following (except for extenuating circumstances):

    • Admin: Can do everything in the account including IAM administration
    • Trusted user: Can do most things in the account excluding IAM administration
    • Read only: Can read things in the account but not perform any side-effects; should NOT be able to do things like ssm:DescribeParameters

    Delete AWS accounts

    When your team no longer requires an AWS account, contact Reliability Engineering using the #Reliability-eng Slack Channel.

    GDS teams are responsible for managing their own leavers’ process.

    Remove access to AWS accounts

    When someone no longer requires access to AWS (for example, because they’ve left GDS or your team) remove them from the gds-users base account using the Request user removal section of the:

    Request an AWS account form.

    Before you request someone’s removal make sure they do not need access to AWS in another team within GDS.

    GDS teams are responsible for managing their own leavers’ process.