Generate AWS Credentials dynamically in Vault

One of the key integrations that Vault provides is the AWS Secrets Engine, which can be used to create credentials on the fly. Credentials for Vault to access the AWS API can be obtained via secrets engine root configuration, IAM role attached to the Vault server instance, or environment variables.

The idea behind dynamic secrets is that whenever a user requests for secrets, they are created at that moment of time. So dynamic secrets do not exist until they are generated.

Solution Overview

A user will send a request to generate his/her own credentials. Since Vault (with the appropriate permissions) will be integrated with AWS, it will send back the access key and secret key to the user. The credentials will be associated with a lease duration that determines when the credentials should stop working.

Prerequisite

Ensure you have a running Vault node on your machine or in your AWS account like we did in the previous post. Below is the Vault UI with default secrets engines:

Vault instance started on my laptop

Step 1: Configure the AWS Secrets Engine

Secrets engines are components which store, generate, or encrypt data. Users can generate AWS credentials through a Vault cluster that has the AWS Secrets Engine enabled.

  • We can enable the engine on UI or via the terminal by running the command below:
vault secrets enable aws
Response from the command
  • We need to specify a role that will be associated with the credentials that are being generated dynamically. We will make use of the ReadOnlyAccess policy thats managed by AWS, take note of the ARN:
  • Create a new role to be given the new IAM user that will be created by Vault, simply run the command below:
vault write aws/roles/developer-access \
      policy_arns=arn:aws:iam::aws:policy/ReadOnlyAccess \
      credential_type=iam_user 
Response from the command

We can check the Vault UI to confirm our configurations thus far, it should look something like this:

Step 2: Integrate Vault and AWS IAM

We need relevant permissions associated with our Vault cluster in order to interact with AWS IAM. Check the example IAM policy for Vault to have a view of the required permissions.

  • Create a vault-policy on the IAM Management Console to give Vault permission to manage dynamic IAM users. Below is the policy document:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:AttachUserPolicy",
        "iam:CreateAccessKey",
        "iam:CreateUser",
        "iam:DeleteAccessKey",
        "iam:DeleteUser",
        "iam:DeleteUserPolicy",
        "iam:DetachUserPolicy",
        "iam:GetUser",
        "iam:ListAccessKeys",
        "iam:ListAttachedUserPolicies",
        "iam:ListGroupsForUser",
        "iam:ListUserPolicies",
        "iam:PutUserPolicy",
        "iam:AddUserToGroup",
        "iam:RemoveUserFromGroup"
      ],
      "Resource": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:user/vault-*"]
    }
  ]
}
  • Create a vault-user on the IAM Management Console that will be used by Vault to manage dynamic credentials. Make sure to attach the vault-policy to this user:
  • Create access key on the security credentials tab as we need these to finalize configuration of the AWS Secrets Engine in Vault:
  • Since we enabled the secrets engine in Vault, we can integrate the vault-user by simply running the command:
vault write aws/config/root \
      access_key=AKIA4P4EY7KUMYNGRTVX \
      secret_key=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 \
      region=af-south-1                         
Response from the command

Step 3: Manage dynamic credentials

Since we have configured Vault to interact with AWS, we can create dynamic credentials with a ReadOnly policy attached to the specific user.  In order to generate these dynamic credentials, we will run the below command:

vault read aws/creds/developer-access
Response from the command
  • Anytime we create dynamic credentials, we get a lease associated with that. Using the lease_id we can either renew the credentials or we can revoke those credentials. By default the lease_duration is 768h, which equates to 32 days.
  • We can use the access_key and secret_key to login using the AWS CLI, we can confirm these are indeed the credentials by simply checking the AWS Console:
  • To delete the credential (IAM user from AWS) we just created, we can simply run the command below:
vault lease revoke aws/creds/developer-access/9RTjBGPLSn6WailO9LBGm5QX
Response from the command

Given we have generated a bunch of credentials dynamically as seen on the below screenshot:

If we want to delete all credentials in our developer-access role with a single command, and not running vault lease revoke <lease_id> multiple times, the super easy way to do this is by running the command:

vault lease revoke -prefix aws/creds/developer-access
Response from the command

If we check the AWS console, we'll notice all dynamic credentials were indeed deleted:

Summary

That was a detailed step-by-step guide on how to generate dynamic credentials for an AWS account. I made use of the Vault CLI but this is easily achievable via the Vault UI as well.