This example shows how to use the AWS IAM role attached to a resource to authenticate
to a vault cluster.
Vault provides multiple ways to authenticate a human or machine to Vault, known as
auth methods. For example, a human can authenticate with a Username
& Password or with GitHub.
Among those methods you will find AWS. The way it works is that Vault
understands AWS as a trusted third party, and relies on AWS itself for affirming
if an authentication source such as an EC2 Instance or other resources like a Lambda
Function are legitimate sources or not.
There are currently two ways an AWS resource can authenticatate to Vault: ec2 and iam.
In this example, we demonstrate the AWS IAM Auth Method.
Note: To keep this example as simple to deploy and test as possible and because we are
focusing on authentication, it deploys the Vault cluster into your default VPC and default subnets,
all of which are publicly accessible. This is OK for learning and experimenting, but for
production usage, we strongly recommend deploying the Vault cluster into the private subnets
of a custom VPC.
Running this example
You will need to create an Amazon Machine Image (AMI) that has both Vault and Consul
installed, which you can do using the vault-consul-ami example). All the EC2
Instances in this example (including the EC2 Instance that authenticates to Vault) install
Dnsmasq (via the install-dnsmasq module) or
setup-systemd-resolved (in the case of Ubuntu 18.04) so that all DNS queries
for *.consul will be directed to the Consul Server cluster. Because Consul has knowledge of
all the Vault nodes (and in some cases, of other services as well), this setup allows the EC2
Instance to use Consul's DNS server for service discovery, and thereby to discover the IP addresses
of the Vault nodes.
Quick start
git clone this repo to your computer.
Build a Vault and Consul AMI. See the vault-consul-ami example documentation for
instructions. Make sure the install_auth_signing_script variable is true.
Make sure to note down the ID of the AMI.
Open variables.tf, set the environment variables specified at the top of the file, and fill in any other variables
that don't have a default. Put the AMI ID you previously took note into the ami_id variable.
Run terraform init.
Run terraform apply.
Run the vault-examples-helper.sh script to
print out the IP addresses of the Vault server and some example commands you can run to interact with the cluster:
../vault-examples-helper/vault-examples-helper.sh.
Run curl <auth-instance-ip>:8080 to check if the client instance is fetching the secret from Vault properly
Vault Authentication using IAM user or role
IAM auth is a process in which Vault leverages AWS STS (Security Token Service) to
identify the AWS IAM principal (user or role) attached to an AWS resource such as
an ECS Task or a Lambda Function that originates the login request. You can still
use the iam method for EC2 instances attached to a role, like we do in this example,
but for a login method specifically for EC2 instances, please refer to the
ec2 auth method example.
The workflow is that the client trying to authenticate will create a request to
the method GetCallerIdentity of the AWS STS API (but not yet send it). This
method basically answers the question "Who am I?". This request is then signed
with the AWS credentials of the client. The signed result is then sent with the
login request to the Vault Server. When the Vault server receives a login request
with the iam method, it can execute the STS request without actually knowing
the contents of the signed part. It then receives a response from STS identifying
who signed it, which the Vault Server then can check against the ARN of the IAM
principal bounded to a previously created Vault Role and decide if it should be
allowed to authenticate or not.
It is important to notice that, when the Vault Server receives this encrypted STS
API request attached to a login request, to be able to execute it and perform the
login, the cluster needs to have AWS Policies that will allow the cluster to execute
the following actions: iam:GetRole or iam:GetUser, and sts:GetCallerIdentity.
Configuring a Vault server
Before we try to authenticate, we must be sure that the Vault Server is configured
properly and prepared to receive requests. First, we must make sure the Vault server
has been initialized (using vault operator init) and unsealed (using vault operator unseal).
Next, we must enable Vault to support the AWS auth method (using vault auth enable aws).
After that, we enable the Vault kv secrets engine at the path secret (note that this engine
was enabled by default in previous versions < 1.1.0). Finally, we must define the correct
Vault Policies and Roles to declare which IAM Principals will have access to which resources
in Vault.
Policies are rules that grant or forbid access and actions to certain paths in
Vault. With one or more policies on hand, you can then finally create the authentication role.
When you create a Role in Vault, you define the Policies that are attached to that
Role and for how long tokens issued for that Role will be valid.
In our example we create a simple Vault Policy that allows writing and reading from
secrets in the path secret namespaced with the prefix example_, and then create
a Vault Role that allows authentication from AWS resources attached to a certain IAM Role.
You can read more about Role creation and check which other configurations you can
use on auth here.
The vault-consul-ami includes a python script called
sign-request.py. We use python here instead of bash to take advantage of the
boto3 AWS SDK library. This script is a modified version of the Python 2.x example
posted by J. Thompson, the author of Vault's IAM auth method, at the Vault mailing
list. It uses boto3 to create a request to the AWS Security Token Service API
with the action "GetCallerIdentity" and then signs the request using the AWS credentials.
The same pattern should work with the AWS SDK in any other supported language such
as Go, Java or Ruby, for example. For more details on the IAM auth method, there's
a talk by J. Thompson called Deep Dive into Vault's AWS Auth Backend.
After sending the login request to Vault, Vault will execute the STS request to
verify the client's identity with AWS and return a JSON object with your login
information containing the client_token. The client token is an ephemeral token
that you will send with your future operations requests to Vault. It can expire,
be rotated, or become invalid for some other reason and you might be required to
authenticate again.
If vault cli is installed we can perform the login operation with it. The VAULT_ADDR
environment variable has to be set and you need to have AWS credentials in some form.
The vault cli will look for credentials configured in the standard locations such as
environment variables, ~/.aws/credentials, IAM instance profile, or ECS task role, in
that order. The way the it works is the same as with an HTTP request. The vault cli
tool uses the golang AWS SDK to the create the STS API request and sign it with the
credentials for you. It's important to note that the role value being passed is
the Vault Role name, not the AWS IAM Role name.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"be1841a927697869a942fb91e86672c646cc32bb"}]},{"name":".gitignore","path":".gitignore","sha":"6c4ebe4426586b7febbaba178294ef59b8272c05"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"5949dbc0fa6d4dd6610575e3c878c353d92da44a"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","sha":"ea1ca5c8d6ff2d0d62880ee0ea80ef86e0b87dad"},{"name":"LICENSE","path":"LICENSE","sha":"7a4a3ea2424c09fbe48d455aed1eaa94d9124835"},{"name":"NOTICE","path":"NOTICE","sha":"2288082e33ae18a610f6a7747180f7e05e47a001"},{"name":"README.md","path":"README.md","sha":"1a2de50f26400eda43c1067fccf4aa49b3db8dfe"},{"name":"_ci","children":[{"name":"publish-amis-in-new-account.md","path":"_ci/publish-amis-in-new-account.md","sha":"3182a0a90775f7bb9622c037196ac2a1f15e455d"},{"name":"publish-amis.sh","path":"_ci/publish-amis.sh","sha":"3d4a46a02f26d45a5fc27cce07cd3db7bc140399"}]},{"name":"_docs","children":[{"name":"amazon-linux-ami-list.md","path":"_docs/amazon-linux-ami-list.md","sha":"be9f50c689839b099d0222711ec13a86108660f0"},{"name":"architecture-elb.png","path":"_docs/architecture-elb.png","sha":"9e02e4f53afdd2929ec4fc4246ae5e47bd49f295"},{"name":"architecture-with-s3.png","path":"_docs/architecture-with-s3.png","sha":"8a91ef2d06665e40fe82a8ccf7ae4281f338fd50"},{"name":"architecture.png","path":"_docs/architecture.png","sha":"a9f6098b37b1aaafe8c744b154208efc3e642881"},{"name":"ubuntu16-ami-list.md","path":"_docs/ubuntu16-ami-list.md","sha":"60caafe1f2b90046e819f373ed22c0df47043f03"}]},{"name":"examples","children":[{"name":"root-example","children":[{"name":"README.md","path":"examples/root-example/README.md","sha":"4d73916c181c9c4157905162d4ed66d2d7427342"},{"name":"user-data-consul.sh","path":"examples/root-example/user-data-consul.sh","sha":"5043e6904cab4564ed0c7f8337599a884f96a194"},{"name":"user-data-vault.sh","path":"examples/root-example/user-data-vault.sh","sha":"26fad57bb49a78e4e2a4b7ce52427efb27e87ced"}]},{"name":"vault-agent","children":[{"name":"README.md","path":"examples/vault-agent/README.md","sha":"0a80c92a455171b6af0e1774a1e67adee32579d6"},{"name":"main.tf","path":"examples/vault-agent/main.tf","sha":"1411aff0b44e6554a96d0481d0ffa31a1b4a27ea"},{"name":"outputs.tf","path":"examples/vault-agent/outputs.tf","sha":"16bb9676e7fa2ec2bb5148c5ca5763d7c01db837"},{"name":"user-data-auth-client.sh","path":"examples/vault-agent/user-data-auth-client.sh","sha":"9ff5ebc6c45f791f9357a71a7f3415f1e333b61e"},{"name":"user-data-consul.sh","path":"examples/vault-agent/user-data-consul.sh","sha":"0c96497e38b05e5b5a54277c95ae129827a3daa2"},{"name":"user-data-vault.sh","path":"examples/vault-agent/user-data-vault.sh","sha":"49983b4b543bd7d28c2adde81629d4a3867ffe13"},{"name":"variables.tf","path":"examples/vault-agent/variables.tf","sha":"9abf58af8a0dc24bd445a1b779f07fcf48a05a0e"}]},{"name":"vault-auto-unseal","children":[{"name":"README.md","path":"examples/vault-auto-unseal/README.md","sha":"770b559d99f84ce103f01fddcdc10c1fef58d482"},{"name":"main.tf","path":"examples/vault-auto-unseal/main.tf","sha":"56169fcd17ecacb9dd028c7f9e8a1e880a9badd6"},{"name":"outputs.tf","path":"examples/vault-auto-unseal/outputs.tf","sha":"9e7ebd3be30c61662e8647cfecfec210de53e6d2"},{"name":"user-data-consul.sh","path":"examples/vault-auto-unseal/user-data-consul.sh","sha":"0c96497e38b05e5b5a54277c95ae129827a3daa2"},{"name":"user-data-vault.sh","path":"examples/vault-auto-unseal/user-data-vault.sh","sha":"1d9533ea3ba6f9b89242ce503e8b7ea1e59579ba"},{"name":"variables.tf","path":"examples/vault-auto-unseal/variables.tf","sha":"03847da844d2c5a5c24a27872324da11249d11de"}]},{"name":"vault-cluster-private","children":[{"name":"README.md","path":"examples/vault-cluster-private/README.md","sha":"ca0abbac27030e0041b221b8c96b68868615d46c"},{"name":"main.tf","path":"examples/vault-cluster-private/main.tf","sha":"8d799c376e723c81a781fee11a5ca279fc6aeac4"},{"name":"outputs.tf","path":"examples/vault-cluster-private/outputs.tf","sha":"9e7ebd3be30c61662e8647cfecfec210de53e6d2"},{"name":"user-data-consul.sh","path":"examples/vault-cluster-private/user-data-consul.sh","sha":"5043e6904cab4564ed0c7f8337599a884f96a194"},{"name":"user-data-vault.sh","path":"examples/vault-cluster-private/user-data-vault.sh","sha":"ef32d804ab9f1807730bae1551fc3fd3fff6da95"},{"name":"variables.tf","path":"examples/vault-cluster-private/variables.tf","sha":"3e919aff20454c6ef004986d3f28b7f65c5d9379"}]},{"name":"vault-consul-ami","children":[{"name":"README.md","path":"examples/vault-consul-ami/README.md","sha":"97b6eeaf3f45cb12b227eb47059042630ec342a4"},{"name":"auth","children":[{"name":"sign-request.py","path":"examples/vault-consul-ami/auth/sign-request.py","sha":"cba97708676a0d3aa8068ee1b5ecb3bf8d14067f"}]},{"name":"tls","children":[{"name":"README.md","path":"examples/vault-consul-ami/tls/README.md","sha":"92f88219562304b995bd78889a24047bdde336af"},{"name":"ca.crt.pem","path":"examples/vault-consul-ami/tls/ca.crt.pem","sha":"9bf1a62b0649d1ab5c0b16710166c146a1fd1fa3"},{"name":"vault.crt.pem","path":"examples/vault-consul-ami/tls/vault.crt.pem","sha":"e642f0b108bfdebe56331111ce9ce75f8ff42f52"},{"name":"vault.key.pem","path":"examples/vault-consul-ami/tls/vault.key.pem","sha":"0103aa55a5a68ffc002c7c9c14a292adbd97fd2d"}]},{"name":"vault-consul.json","path":"examples/vault-consul-ami/vault-consul.json","sha":"34fc05d0337fd83fdb42faa143e6b216a8f6585b"}]},{"name":"vault-ec2-auth","children":[{"name":"README.md","path":"examples/vault-ec2-auth/README.md","sha":"29af1121fa99b3903b09447c79e127daecb30bfb"},{"name":"images","children":[{"name":"ec2-auth.png","path":"examples/vault-ec2-auth/images/ec2-auth.png","sha":"a98fb916ed6a32204efbc525cac59c0d570d619d"}]},{"name":"main.tf","path":"examples/vault-ec2-auth/main.tf","sha":"5417c9d851c4b9ad99033205e615aff8c9b59cf1"},{"name":"outputs.tf","path":"examples/vault-ec2-auth/outputs.tf","sha":"8694fbce70e13690b8bca4bab50d2570dcd7bdd9"},{"name":"user-data-auth-client.sh","path":"examples/vault-ec2-auth/user-data-auth-client.sh","sha":"e049ec6dca2d35d6fde5badec4e48ecafe8bfc38"},{"name":"user-data-consul.sh","path":"examples/vault-ec2-auth/user-data-consul.sh","sha":"0c96497e38b05e5b5a54277c95ae129827a3daa2"},{"name":"user-data-vault.sh","path":"examples/vault-ec2-auth/user-data-vault.sh","sha":"dd8a73e43e9a4c42e4687ad4cc3c84a543ce548a"},{"name":"variables.tf","path":"examples/vault-ec2-auth/variables.tf","sha":"f04b84eac1668fa2ca3b92d50b27ca6139fde834"}]},{"name":"vault-examples-helper","children":[{"name":"README.md","path":"examples/vault-examples-helper/README.md","sha":"a28a95258bee372025e4282daf60a20d1bf96bdb"},{"name":"vault-examples-helper.sh","path":"examples/vault-examples-helper/vault-examples-helper.sh","sha":"ebe3d8b9bb599384add9a7c635b397529b10fde5"}]},{"name":"vault-iam-auth","children":[{"name":"README.md","path":"examples/vault-iam-auth/README.md","sha":"7557e5abb41341b82464a36eebd0e759d857625d","toggled":true},{"name":"images","children":[{"name":"iam-auth.png","path":"examples/vault-iam-auth/images/iam-auth.png","sha":"095dcd0060f6cd1f5dad3be9d5ec83dcbba8316f"}]},{"name":"main.tf","path":"examples/vault-iam-auth/main.tf","sha":"6e1034d29495a9b8895e79f5cf716689782a51cc"},{"name":"outputs.tf","path":"examples/vault-iam-auth/outputs.tf","sha":"16bb9676e7fa2ec2bb5148c5ca5763d7c01db837"},{"name":"user-data-auth-client.sh","path":"examples/vault-iam-auth/user-data-auth-client.sh","sha":"4122511229818b6ddf8fe03fd2c314f8a1521ee2"},{"name":"user-data-consul.sh","path":"examples/vault-iam-auth/user-data-consul.sh","sha":"0c96497e38b05e5b5a54277c95ae129827a3daa2"},{"name":"user-data-vault.sh","path":"examples/vault-iam-auth/user-data-vault.sh","sha":"1f32c36dc968467fc59b44f624638e1437703fb9"},{"name":"variables.tf","path":"examples/vault-iam-auth/variables.tf","sha":"9abf58af8a0dc24bd445a1b779f07fcf48a05a0e"}],"toggled":true},{"name":"vault-s3-backend","children":[{"name":"README.md","path":"examples/vault-s3-backend/README.md","sha":"e37fbaec6982c87a87a16d3499db3c17f85dbbfd"},{"name":"main.tf","path":"examples/vault-s3-backend/main.tf","sha":"64617b4235bca44d381e7007a29d39a02e0edd03"},{"name":"outputs.tf","path":"examples/vault-s3-backend/outputs.tf","sha":"e1af7046390871d4e63797089c39aebab5d9ac26"},{"name":"user-data-consul.sh","path":"examples/vault-s3-backend/user-data-consul.sh","sha":"5043e6904cab4564ed0c7f8337599a884f96a194"},{"name":"user-data-vault.sh","path":"examples/vault-s3-backend/user-data-vault.sh","sha":"cfc21ee0525b0cee2753e1823b8656bf504a910a"},{"name":"variables.tf","path":"examples/vault-s3-backend/variables.tf","sha":"f526eaaa0c65aa5f8be3d4dbde0dd453781d4461"}]}],"toggled":true},{"name":"main.tf","path":"main.tf","sha":"3e2db19f150bfb9ae8b8d1b33ce9e20d3b076dde"},{"name":"modules","children":[{"name":"install-vault","children":[{"name":"README.md","path":"modules/install-vault/README.md","sha":"6bb7538adb7dd8f8527690d96fc06d701cd79462"},{"name":"install-vault","path":"modules/install-vault/install-vault","sha":"e1564049029f50af3507fb2e57dc188c607cb1aa"}]},{"name":"private-tls-cert","children":[{"name":"README.md","path":"modules/private-tls-cert/README.md","sha":"42f2d131477fae97cdfaeef893b3c916f2f7f209"},{"name":"main.tf","path":"modules/private-tls-cert/main.tf","sha":"f906b61efe2b5356bcf759dc60c47a89cf853894"},{"name":"outputs.tf","path":"modules/private-tls-cert/outputs.tf","sha":"078afd869917866e91d2beab7f91fa0d14af524e"},{"name":"variables.tf","path":"modules/private-tls-cert/variables.tf","sha":"57720d8462ddd0a472082d76f1605ea32c443612"}]},{"name":"run-vault","children":[{"name":"README.md","path":"modules/run-vault/README.md","sha":"b2f1e1e074ffd65b4c715675bd59657c6eac6992"},{"name":"run-vault","path":"modules/run-vault/run-vault","sha":"192feb7aa74fde7c93df0e091352780adfeb46c4"}]},{"name":"update-certificate-store","children":[{"name":"README.md","path":"modules/update-certificate-store/README.md","sha":"1348a7aba71475b5a17d31f3f8d66663f656e672"},{"name":"update-certificate-store","path":"modules/update-certificate-store/update-certificate-store","sha":"e07d9a1d997843d62033ee019121895c91e29447"}]},{"name":"vault-cluster","children":[{"name":"README.md","path":"modules/vault-cluster/README.md","sha":"7b4c4ee5f59dc3a216154c4402acd70b96d6585f"},{"name":"main.tf","path":"modules/vault-cluster/main.tf","sha":"d8e6b486f28dc2fc35591d7389e6b2ad4d4bf4df"},{"name":"outputs.tf","path":"modules/vault-cluster/outputs.tf","sha":"ab03f0accf81c6722c79656844acd1fd39b41e87"},{"name":"variables.tf","path":"modules/vault-cluster/variables.tf","sha":"4067580ffe82b3c9aaf558887c413ba2992e9394"}]},{"name":"vault-elb","children":[{"name":"README.md","path":"modules/vault-elb/README.md","sha":"9dc6564baaaaa8176f650e3c548b8c8066631b6f"},{"name":"main.tf","path":"modules/vault-elb/main.tf","sha":"0f85aea4f41332461dadcda41e767f983d53ad66"},{"name":"outputs.tf","path":"modules/vault-elb/outputs.tf","sha":"024b1c73b457ed1c9256b39fc3ee283b39ed6544"},{"name":"variables.tf","path":"modules/vault-elb/variables.tf","sha":"f6ec2cedeb90b046d4caf020482f0169f872f17d"}]},{"name":"vault-security-group-rules","children":[{"name":"README.md","path":"modules/vault-security-group-rules/README.md","sha":"48df12587b14b7a0d93333b6c12c19dc7082d8b0"},{"name":"main.tf","path":"modules/vault-security-group-rules/main.tf","sha":"c42c6e6d296dd17c021b134bb2f4c5774cf0079c"},{"name":"variables.tf","path":"modules/vault-security-group-rules/variables.tf","sha":"2e18f3fef1b2ff2b3a32f62a49085480ed61763e"}]}]},{"name":"outputs.tf","path":"outputs.tf","sha":"9d46ba8bb2ee80bf8bb1ba3ac5b7660280be3e1c"},{"name":"test","children":[{"name":"Gopkg.lock","path":"test/Gopkg.lock","sha":"568bc5956806e4aed616ba1416be9f34c6297153"},{"name":"Gopkg.toml","path":"test/Gopkg.toml","sha":"0b963bee63cabb891409e7bc306361206047d368"},{"name":"README.md","path":"test/README.md","sha":"dd3f97e937dd02cdd9142d0c25006bd6367e7fef"},{"name":"aws_helpers.go","path":"test/aws_helpers.go","sha":"f686b13f45c0deafbec5215d251c8936e30de421"},{"name":"terratest_helpers.go","path":"test/terratest_helpers.go","sha":"61cb21eeaa80d5c93a2eb1d61964991b6710a770"},{"name":"tls_helpers.go","path":"test/tls_helpers.go","sha":"9b95b015104a0c7a684f6f3af999407218121619"},{"name":"vault_cluster_auth_test.go","path":"test/vault_cluster_auth_test.go","sha":"6dc38ca9feb145131336742a05305a63716a663d"},{"name":"vault_cluster_autounseal_test.go","path":"test/vault_cluster_autounseal_test.go","sha":"6378645baf5b1882e25cc1a9a6ea33c2a499670a"},{"name":"vault_cluster_enterprise_test.go","path":"test/vault_cluster_enterprise_test.go","sha":"4b2ca281392b651c889ea0a6f9b4c4afb703ddee"},{"name":"vault_cluster_private_test.go","path":"test/vault_cluster_private_test.go","sha":"9b4c9c7e3c58a9b87df4ab34952b9f908f890f1b"},{"name":"vault_cluster_public_test.go","path":"test/vault_cluster_public_test.go","sha":"adeceaf1a85f323c920117c27992048335bd38a8"},{"name":"vault_cluster_s3_backend_test.go","path":"test/vault_cluster_s3_backend_test.go","sha":"cb028cf873c350aeb24bf5b01e9574790cf2fddb"},{"name":"vault_helpers.go","path":"test/vault_helpers.go","sha":"68cf62618b5510e55577780c65b48528c39a2c44"},{"name":"vault_main_test.go","path":"test/vault_main_test.go","sha":"905a37d2df09a4053104f163ddbd8d0d8bbab28d"}]},{"name":"variables.tf","path":"variables.tf","sha":"c1e78c623452213f943f69d3a1fac13b3bc3d3d9"}]},"detailsContent":"<h1 class=\"preview__body--title\" id=\"vault-authentication-using-aws-iam-role-example\">Vault authentication using AWS IAM role example</h1><div class=\"preview__body--border\"></div><p>This example shows how to use the AWS IAM role attached to a resource to authenticate\nto a <a href=\"/repos/v0.16.0/terraform-aws-vault/modules/vault-cluster\" class=\"preview__body--description--blue\">vault cluster</a>.</p>\n<p>Vault provides multiple ways to authenticate a human or machine to Vault, known as\n<a href=\"https://www.vaultproject.io/docs/auth/index.html\" class=\"preview__body--description--blue\" target=\"_blank\">auth methods</a>. For example, a human can authenticate with a Username\n& Password or with GitHub.</p>\n<p>Among those methods you will find <a href=\"https://www.vaultproject.io/docs/auth/aws.html\" class=\"preview__body--description--blue\" target=\"_blank\">AWS</a>. The way it works is that Vault\nunderstands AWS as a trusted third party, and relies on AWS itself for affirming\nif an authentication source such as an EC2 Instance or other resources like a Lambda\nFunction are legitimate sources or not.</p>\n<p>There are currently two ways an AWS resource can authenticatate to Vault: <code>ec2</code> and <code>iam</code>.\nIn this example, we demonstrate the <a href=\"https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method\" class=\"preview__body--description--blue\" target=\"_blank\">AWS IAM Auth Method</a>.</p>\n<p><strong>Note</strong>: To keep this example as simple to deploy and test as possible and because we are\nfocusing on authentication, it deploys the Vault cluster into your default VPC and default subnets,\nall of which are publicly accessible. This is OK for learning and experimenting, but for\nproduction usage, we strongly recommend deploying the Vault cluster into the private subnets\nof a custom VPC.</p>\n<h2 class=\"preview__body--subtitle\" id=\"running-this-example\">Running this example</h2>\n<p>You will need to create an <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html\" class=\"preview__body--description--blue\" target=\"_blank\">Amazon Machine Image (AMI)</a> that has both Vault and Consul\ninstalled, which you can do using the <a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-consul-ami\" class=\"preview__body--description--blue\">vault-consul-ami example</a>). All the EC2\nInstances in this example (including the EC2 Instance that authenticates to Vault) install\n<a href=\"http://www.thekelleys.org.uk/dnsmasq/doc.html\" class=\"preview__body--description--blue\" target=\"_blank\">Dnsmasq</a> (via the <a href=\"/repos/terraform-aws-consul/modules/install-dnsmasq\" class=\"preview__body--description--blue\">install-dnsmasq module</a>) or\n<a href=\"/repos/terraform-aws-consul/modules/setup-systemd-resolved\" class=\"preview__body--description--blue\">setup-systemd-resolved</a> (in the case of Ubuntu 18.04) so that all DNS queries\nfor <code>*.consul</code> will be directed to the Consul Server cluster. Because Consul has knowledge of\nall the Vault nodes (and in some cases, of other services as well), this setup allows the EC2\nInstance to use Consul's DNS server for service discovery, and thereby to discover the IP addresses\nof the Vault nodes.</p>\n<h3 class=\"preview__body--subtitle\" id=\"quick-start\">Quick start</h3>\n<ol>\n<li><code>git clone</code> this repo to your computer.</li>\n<li>Build a Vault and Consul AMI. See the <a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-consul-ami\" class=\"preview__body--description--blue\">vault-consul-ami example</a> documentation for\ninstructions. Make sure the <code>install_auth_signing_script</code> variable is <code>true</code>.\nMake sure to note down the ID of the AMI.</li>\n<li>Install <a href=\"https://www.terraform.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Terraform</a>.</li>\n<li>Open <code>variables.tf</code>, set the environment variables specified at the top of the file, and fill in any other variables\nthat don't have a default. Put the AMI ID you previously took note into the <code>ami_id</code> variable.</li>\n<li>Run <code>terraform init</code>.</li>\n<li>Run <code>terraform apply</code>.</li>\n<li>Run the <a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-examples-helper/vault-examples-helper.sh\" class=\"preview__body--description--blue\">vault-examples-helper.sh script</a> to\nprint out the IP addresses of the Vault server and some example commands you can run to interact with the cluster:\n<code>../vault-examples-helper/vault-examples-helper.sh</code>.</li>\n<li>Run <code>curl <auth-instance-ip>:8080</code> to check if the client instance is fetching the secret from Vault properly</li>\n</ol>\n<h3 class=\"preview__body--subtitle\" id=\"vault-authentication-using-iam-user-or-role\">Vault Authentication using IAM user or role</h3>\n<p>IAM auth is a process in which Vault leverages AWS STS (Security Token Service) to\nidentify the AWS IAM principal (user or role) attached to an AWS resource such as\nan ECS Task or a Lambda Function that originates the login request. You can still\nuse the <code>iam</code> method for EC2 instances attached to a role, like we do in this example,\nbut for a login method specifically for EC2 instances, please refer to the\n<a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-ec2-auth\" class=\"preview__body--description--blue\"><code>ec2</code> auth method example</a>.</p>\n<p>The workflow is that the client trying to authenticate will create a request to\nthe method <code>GetCallerIdentity</code> of the AWS STS API (but not yet send it). This\nmethod basically answers the question "Who am I?". This request is then signed\nwith the AWS credentials of the client. The signed result is then sent with the\nlogin request to the Vault Server. When the Vault server receives a login request\nwith the <code>iam</code> method, it can execute the STS request without actually knowing\nthe contents of the signed part. It then receives a response from STS identifying\nwho signed it, which the Vault Server then can check against the ARN of the IAM\nprincipal bounded to a previously created Vault Role and decide if it should be\nallowed to authenticate or not.</p>\n<p><img src=\"/repos/images/v0.16.0/terraform-aws-vault/examples/vault-iam-auth/images/iam-auth.png\" alt=\"auth diagram\" class=\"preview__body--diagram\"></p>\n<p>It is important to notice that, when the Vault Server receives this encrypted STS\nAPI request attached to a login request, to be able to execute it and perform the\nlogin, the cluster needs to have AWS Policies that will allow the cluster to execute\nthe following actions: <code>iam:GetRole</code> or <code>iam:GetUser</code>, and <code>sts:GetCallerIdentity</code>.</p>\n<h3 class=\"preview__body--subtitle\" id=\"configuring-a-vault-server\">Configuring a Vault server</h3>\n<p>Before we try to authenticate, we must be sure that the Vault Server is configured\nproperly and prepared to receive requests. First, we must make sure the Vault server\nhas been initialized (using <code>vault operator init</code>) and unsealed (using <code>vault operator unseal</code>).\nNext, we must enable Vault to support the AWS auth method (using <code>vault auth enable aws</code>).\nAfter that, we enable the Vault kv secrets engine at the path <code>secret</code> (note that this engine\nwas enabled by default in previous versions < 1.1.0). Finally, we must define the correct\nVault Policies and Roles to declare which IAM Principals will have access to which resources\nin Vault.</p>\n<p><a href=\"https://www.vaultproject.io/docs/concepts/policies.html\" class=\"preview__body--description--blue\" target=\"_blank\">Policies</a> are rules that grant or forbid access and actions to certain paths in\nVault. With one or more policies on hand, you can then finally create the authentication role.</p>\n<p>When you create a Role in Vault, you define the Policies that are attached to that\nRole and for how long tokens issued for that Role will be valid.</p>\n<p>In our example we create a simple Vault Policy that allows writing and reading from\nsecrets in the path <code>secret</code> namespaced with the prefix <code>example_</code>, and then create\na Vault Role that allows authentication from AWS resources attached to a certain IAM Role.\nYou can read more about Role creation and check which other configurations you can\nuse on auth <a href=\"https://www.vaultproject.io/api/auth/aws/index.html#create-role\" class=\"preview__body--description--blue\" target=\"_blank\">here</a>.</p>\n<pre>vault<span class=\"hljs-built_in\"> policy </span>write <span class=\"hljs-string\">\"example-policy\"</span> -<<EOF\npath <span class=\"hljs-string\">\"secret/example_*\"</span> {\n capabilities = [<span class=\"hljs-string\">\"create\"</span>, <span class=\"hljs-string\">\"read\"</span>]\n}\nEOF\n\nvault write \\\n auth/aws/role/example-role\n <span class=\"hljs-attribute\">auth_type</span>=iam \\\n <span class=\"hljs-attribute\">policies</span>=example-policy \\\n <span class=\"hljs-attribute\">max_ttl</span>=500h \\\n <span class=\"hljs-attribute\">bound_iam_principal_arn</span>=<ARN>\n</pre>\n<p>See the whole example script at <a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-iam-auth/user-data-vault.sh\" class=\"preview__body--description--blue\">user-data-vault.sh</a>.</p>\n<h3 class=\"preview__body--subtitle\" id=\"authenticating-from-a-client\">Authenticating from a client</h3>\n<h4 id=\"with-an-http-request\">With an HTTP request</h4>\n<p>The <a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-consul-ami\" class=\"preview__body--description--blue\">vault-consul-ami</a> includes a <a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-consul-ami/auth/sign-request.py\" class=\"preview__body--description--blue\">python script</a> called\n<code>sign-request.py</code>. We use python here instead of bash to take advantage of the\n<code>boto3</code> AWS SDK library. This script is a modified version of the Python 2.x example\nposted by J. Thompson, the author of Vault's IAM auth method, at the Vault mailing\nlist. It uses <code>boto3</code> to create a request to the AWS Security Token Service API\nwith the action "GetCallerIdentity" and then signs the request using the AWS credentials.\nThe same pattern should work with the AWS SDK in any other supported language such\nas Go, Java or Ruby, for example. For more details on the IAM auth method, there's\na talk by J. Thompson called <a href=\"https://www.hashicorp.com/resources/deep-dive-vault-aws-auth-backend\" class=\"preview__body--description--blue\" target=\"_blank\">Deep Dive into Vault's AWS Auth Backend</a>.</p>\n<pre>signed_request=<span class=\"hljs-constructor\">$(<span class=\"hljs-params\">python</span> <span class=\"hljs-operator\">/</span><span class=\"hljs-params\">opt</span><span class=\"hljs-operator\">/</span><span class=\"hljs-params\">vault</span><span class=\"hljs-operator\">/</span><span class=\"hljs-params\">scripts</span><span class=\"hljs-operator\">/</span><span class=\"hljs-params\">sign</span>-<span class=\"hljs-params\">request</span>.<span class=\"hljs-params\">py</span> <span class=\"hljs-params\">vault</span>.<span class=\"hljs-params\">service</span>.<span class=\"hljs-params\">consul</span>)</span>\n</pre>\n<p>Once we have the encrypted request created by the python script, we can pass it\nin the body of the login request we will send to the Vault Server.</p>\n<pre>iam_request_url=<span class=\"hljs-variable\">$</span>(echo <span class=\"hljs-variable\">$signed_request</span> | jq <span class=\"hljs-literal\">-r</span> .iam_request_url)\niam_request_body=<span class=\"hljs-variable\">$</span>(echo <span class=\"hljs-variable\">$signed_request</span> | jq <span class=\"hljs-literal\">-r</span> .iam_request_body)\niam_request_headers=<span class=\"hljs-variable\">$</span>(echo <span class=\"hljs-variable\">$signed_request</span> | jq <span class=\"hljs-literal\">-r</span> .iam_request_headers)\n\n\n<span class=\"hljs-keyword\">data</span>=<span class=\"hljs-variable\">$</span>(cat <<EOF\n{\n <span class=\"hljs-string\">\"role\"</span>:<span class=\"hljs-string\">\"<span class=\"hljs-variable\">$VAULT_ROLE_NAME</span>\"</span>,\n <span class=\"hljs-string\">\"iam_http_request_method\"</span>: <span class=\"hljs-string\">\"POST\"</span>,\n <span class=\"hljs-string\">\"iam_request_url\"</span>: <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$iam_request_url</span>\"</span>,\n <span class=\"hljs-string\">\"iam_request_body\"</span>: <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$iam_request_body</span>\"</span>,\n <span class=\"hljs-string\">\"iam_request_headers\"</span>: <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$iam_request_headers</span>\"</span>\n}\nEOF\n)\n\ncurl -<span class=\"hljs-literal\">-request</span> POST -<span class=\"hljs-literal\">-data</span> <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$data</span>\"</span> https://vault.service.consul:<span class=\"hljs-number\">8200</span>/v1/auth/aws/login<span class=\"hljs-string\">\"\n</span></pre>\n<p>After sending the login request to Vault, Vault will execute the STS request to\nverify the client's identity with AWS and return a JSON object with your login\ninformation containing the <code>client_token</code>. The client token is an ephemeral token\nthat you will send with your future operations requests to Vault. It can expire,\nbe rotated, or become invalid for some other reason and you might be required to\nauthenticate again.</p>\n<p>To see the full example script for authenticating, check the <a href=\"/repos/v0.16.0/terraform-aws-vault/examples/vault-iam-auth/user-data-auth-client.sh\" class=\"preview__body--description--blue\">client user data script</a>.</p>\n<h4 id=\"with-vault-cli-tool\">With Vault cli tool</h4>\n<p>If vault cli is installed we can perform the login operation with it. The <code>VAULT_ADDR</code>\nenvironment variable has to be set and you need to have AWS credentials in some form.\nThe vault cli will look for credentials configured in the standard locations such as\nenvironment variables, ~/.aws/credentials, IAM instance profile, or ECS task role, in\nthat order. The way the it works is the same as with an HTTP request. The vault cli\ntool uses the golang AWS SDK to the create the STS API request and sign it with the\ncredentials for you. It's important to note that the <code>role</code> value being passed is\nthe Vault Role name, not the AWS IAM Role name.</p>\n<pre>export VAULT_ADDR=https:<span class=\"hljs-comment\">//vault.service.consul:8200</span>\nvault login -<span class=\"hljs-function\"><span class=\"hljs-keyword\">method</span>=<span class=\"hljs-title\">aws</span> <span class=\"hljs-title\">header_value</span>=<span class=\"hljs-title\">vault</span>.<span class=\"hljs-title\">service</span>.<span class=\"hljs-title\">consul</span> <span class=\"hljs-title\">role</span>=<span class=\"hljs-title\">vault</span>-<span class=\"hljs-title\">role</span>-<span class=\"hljs-title\">name</span>\n</span></pre>\n","repoName":"terraform-aws-vault","repoRef":"v0.13.4","serviceDescriptor":{"serviceName":"HashiCorp Vault","serviceRepoName":"terraform-aws-vault","serviceRepoOrg":"hashicorp","cloudProviders":["aws"],"description":"Deploy a Vault cluster. Supports automatic bootstrapping, Consul and S3 backends, self-signed TLS certificates, and auto healing.","imageUrl":"vault.png","licenseType":"open-source","technologies":["Terraform","Bash"],"compliance":[],"tags":[""]},"serviceCategoryName":"Secrets management","fileName":"README.md","filePath":"/examples/vault-iam-auth","title":"Repo Browser: HashiCorp Vault","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}