Protecting AWS api keys the right way (part two).

2017-10-29

This is the second part of “Protecting AWS api keys the right way” instalment, the first part cand be found here.

In the first part of “Protecting AWS api keys the right way” we covered how to protect AWS API using MFA (Multi Factor Authentication) and restricting the source ip from where those credentials can be used. In this post we are going to implement how to store in a secure manner AWS access keys on laptop of desktop computer. For this purpose there are a few tools available, but one in particular has caught my attention, AWS-VAULT allow to store IAM credentials using the operating system secure keystore and also is aware of AWS STS assume role, this means no more ugly handcrafted scripts to do an AWS assume role whenever required.

Requirements:

  • AWS-VAULT: https://github.com/99designs/aws-vault

On OSX type:

brew install caskroom/cask/aws-vault

For all other operating system go to Downloads at: https://github.com/99designs/aws-vault/releases

  • AWS CLI: https://github.com/aws/aws-cli
pip3  install awscli --upgrade --user
  • Terraform: https://www.terraform.io/

On OSX type:

brew install terraform

For all other operating system go to Downloads at: https://www.terraform.io/downloads.html

  • AWS IAM user.

The following steps and the AWS IAM configurations can be fully automated with Terraform, but this is not in scope.

1) Create an IAM user as vault.test and note down the AWS access keys.

2) Enable MFA on vault.test and note down the MFA arn, something as: arn:aws:iam::AWS_ACCOUNT_ID:mfa/vault.test

3) Attach the following policy as “inline policy”, this policy will give EC2 and S3 full access to vault.test user when authenticated via MFA.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:*",
        "s3:*"
      ],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

Hands-on

1) Plain IAM user.

Open you AWS config file

vim ~/.aws/config

Add the following profile changing AWS_ACCOUNT_ID with your own.

[profile vault.test]
mfa_serial = arn:aws:iam::YOUR_AWS_ACCOUNT_ID:mfa/vault.test

Add vault.test AWS access keys into the AWS-VAULT secure store.

aws-vault add vault.test

Enter the credentials previously noted.

Enter Access Key ID:
Enter Secret Access Key:

Now you have to enter a password to seal the keychain for the above credentials, you will be asked of this password anytime you need to invoke AWS-VAULT with vault.test user profile.

Test the AWS-VAULT credentials running an EC2 describe instances command.

AWS_DEFAULT_REGION=us-west-2  aws-vault exec vault.test  aws ec2 describe-instances

At this point you will be required to enter the password to unseal the keyring along with the six digit MFA code as shown below.

Enter token for arn:aws:iam::973562982484:mfa/vault.test: 123456

Whether you have EC2 instances running that particular region the output might vary, otherwise will just return an empty response as follow.

{
    "Reservations": []
}

Executing Terraform with AWS-VAULT.

Use the gist below to create a terraform file changing the bucket name from bucket = "somethingVaultTest" to something meaningful to you.

Run terraform to create the bucket.

terraform init
aws-vault exec vault.test terraform plan
aws-vault exec vault.test terraform apply

Run terraform to destroy the bucket previously created.

aws-vault exec vault.test terraform destroy

2) IAM user with assume role.

Replace the vault.test “inline policy” with the following. This policy will grant to the user the following actions only; GetRoles,GetRolePolicy, ListRoles.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:GetRoles",
                "iam:GetRolePolicy",
                "iam:ListRoles"
            ],
            "Resource": [
                "arn:aws:iam::*"
            ]
        }
    ]
}

Create an IAM role by the name of aws-vault-role-test add full EC2/S3 access and attach the policy below replacing YOUR_AWS_ACCOUNT_ID with your AWS account ID. Please note down the role arn, arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/aws-vault-test.

The following policy ensure who can assume aws-vault-role-test role, in the specific the sole entity allowed is vault.test when authenticated via MFA.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::YOUR_AWS_ACCOUNT_ID:user/vault.test"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

Edit your vim ~/.aws/config adding the role arn resource.

[profile vault.test]
mfa_serial=arn:aws:iam::YOUR_AWS_ACCOUNT_ID:mfa/vault.test
role_arn= arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/aws-vault-test

Test the AWS-VAULT credentials with assume role running an EC2 describe instances command.

AWS_DEFAULT_REGION=us-west-2  aws-vault exec vault.test  aws ec2 describe-instances

At this point you will be required to enter the password to unseal the keyring along with the six digit MFA code as shown below.

Enter token for arn:aws:iam::973562982484:mfa/vault.test: 123456

Whether you have EC2 instances running that particular region the output might vary, otherwise will just return an empty response as follow.

{
    "Reservations": []
}

Executing Terraform with AWS-VAULT.

Use the gist below to create a terraform file changing the bucket name from bucket = "somethingVaultTest" to something meaningful to you.

Run terraform to create the bucket.

terraform init
aws-vault exec vault.test terraform plan
aws-vault exec vault.test terraform apply

Run terraform to destroy the bucket previously created.

aws-vault exec vault.test terraform destroy

I hope you have enjoyed this instalment and had a chance to get a better understanding of AWS Identity and Access Management.

Stay safe!