Skip to content

Commit

Permalink
[Learn] Vault Agent guide (hashicorp#80)
Browse files Browse the repository at this point in the history
* Terraform for Vault Agent guide

* Added the demo steps

* Added a note
  • Loading branch information
yhyakuna authored Nov 20, 2018
1 parent da1d23e commit 84de135
Show file tree
Hide file tree
Showing 14 changed files with 1,300 additions and 0 deletions.
19 changes: 19 additions & 0 deletions identity/vault-agent-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Compiled files
*.tfstate
*.tfstate.*

# Directories
.terraform/
.vagrant/

# Terraform Variables
*.tfvars

# SSH Keys
*.pem

# Backup files
*.bak

# Ignored Terraform files
*gitignore*.tf
176 changes: 176 additions & 0 deletions identity/vault-agent-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# Vault Agent Demo

These assets are provided to provision AWS resources to perform the steps described in the [Vault Agent](https://deploy-preview-257--hashicorp-learn.netlify.com/vault/identity-access-management/vault-agent) guide.

---

**NOTE:** The example Terraform in this repository is created for the demo purpose, and not suitable for production use. For production deployment, refer the following examples:

- [operations/provision-vault](https://github.com/hashicorp/vault-guides/tree/master/operations/provision-vault)
- [Terraform Module Registry](https://registry.terraform.io/modules/hashicorp/vault/aws/0.10.3)


## Demo Steps

1. Set this location as your working directory

1. Set your AWS credentials as environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`

1. Set the Terraform variable values in a file named `terraform.tfvars` (use `terraform.tfvars.example` as a base)

```shell
# SSH key name to access EC2 instances (should already exist)
key_name = "vault-test"

# All resources will be tagged with this
environment_name = "va-demo"

# If you want to use a different AWS region
aws_region = "us-west-1"
availability_zones = "us-west-1a"
```

1. Run Terraform:

```shell
# Pull necessary plugins
$ terraform init
$ terraform plan
# Output provides the SSH instruction
$ terraform apply
```

1. SSH into the Vault **server** instance: `ssh -i <path_to_key> ubuntu@<public_ip_of_server>`

1. On the **server** instance, run the following commands:

```shell
# At this point, Vault hasn't been initialized
$ vault status
# Initialize Vault
$ vault operator init -stored-shares=1 -recovery-shares=1 \
-recovery-threshold=1 -key-shares=1 -key-threshold=1 > key.txt
# Auto-unseal with AWS KMS is configured. So, just re-start the server
$ sudo systemctl restart vault
# Log in with initial root token
$ vault login $(grep 'Initial Root Token:' key.txt | awk '{print $NF}')
# Create a policy file
$ tee myapp.hcl <<EOF
path "secret/myapp/*" {
capabilities = ["read", "list"]
}
EOF
# Create a policy named, 'myapp'
$ vault policy write myapp myapp.hcl
# Write some secrets in 'secret/app/config' path
$ vault kv put secret/myapp/config \
ttl='30s' \
username='appuser' \
password='suP3rsec(et!'
# Enable aws auth method
$ vault auth enable aws
# Configure aws auth method
$ vault write -force auth/aws/config/client
# Be sure to get the Role ARN for ${var.environment_name}-vault-client, and replace <ROLE_ARN>
$ vault write auth/aws/role/dev-role-iam auth_type=iam \
bound_iam_principal_arn=<ROLE_ARN> \
policies=myapp \
ttl=24h
```
1. SSH into the Vault **client** instance: `ssh -i <path_to_key> ubuntu@<public_ip_of_client>`
1. On the **client** instance, run the following commands:
```shell
# Create the Vault Agent configuration file
$ tee /home/ubuntu/auto-auth-conf.hcl <<EOF
exit_after_auth = true
pid_file = "./pidfile"
auto_auth {
method "aws" {
mount_path = "auth/aws"
config = {
type = "iam"
role = "dev-role-iam"
}
}
sink "file" {
config = {
path = "/home/ubuntu/vault-token-via-agent"
}
}
}
EOF
# Run Vault Agent
$ vault agent -config=/home/ubuntu/auto-auth-conf.hcl -log-level=debug
```
1. Verify that the Auto-Auth works:
```shell
# Verify that a token was written to the configured sink location
$ more vault-token-via-agent
# Test to make sure that the token has appropriate policy attached
$ curl --header "X-Vault-Token: $(cat /home/ubuntu/vault-token-via-agent)" \
$VAULT_ADDR/v1/secret/myapp/config | jq
```
1. To demonstrate the Auto-Auth with response-wrapped token, execute the following command on the **client**.
```shell
# Add 'wrap_ttl' in the sink block
$ tee /home/ubuntu/auto-auth-conf.hcl <<EOF
exit_after_auth = true
pid_file = "./pidfile"
auto_auth {
method "aws" {
mount_path = "auth/aws"
config = {
type = "iam"
role = "dev-role-iam"
}
}
sink "file" {
wrap_ttl = "5m"
config = {
path = "/home/ubuntu/vault-token-via-agent"
}
}
}
EOF
# Re-run Vault Agent with updated configuration file
$ vault agent -config=/home/ubuntu/auto-auth-conf.hcl -log-level=debug
# Unwrap the wrapped token and set it as VAULT_TOKEN environment variable
$ export VAULT_TOKEN=$(vault unwrap -field=token $(jq -r '.token' /home/ubuntu/vault-token-via-agent))
# Test to make sure that the token has appropriate policy attached
$ curl --header "X-Vault-Token: $VAULT_TOKEN" $VAULT_ADDR/v1/secret/myapp/config | jq
```
1. Clean up
```plaintext
$ terraform destroy -force
$ rm -rf .terraform terraform.tfstate* private.key
```
27 changes: 27 additions & 0 deletions identity/vault-agent-demo/terraform-aws/aws.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//--------------------------------------------------------------------
// Providers

provider "aws" {
// Credentials set via env vars

region = "${var.aws_region}"
}

//--------------------------------------------------------------------
// Data Sources

data "aws_ami" "ubuntu" {
most_recent = true

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}

owners = ["099720109477"] # Canonical
}
98 changes: 98 additions & 0 deletions identity/vault-agent-demo/terraform-aws/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//--------------------------------------------------------------------
// Resources

## Vault Server IAM Config
resource "aws_iam_instance_profile" "vault-server" {
name = "${var.environment_name}-vault-server-instance-profile"
role = "${aws_iam_role.vault-server.name}"
}

resource "aws_iam_role" "vault-server" {
name = "${var.environment_name}-vault-server-role"
assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

resource "aws_iam_role_policy" "vault-server" {
name = "${var.environment_name}-vault-server-role-policy"
role = "${aws_iam_role.vault-server.id}"
policy = "${data.aws_iam_policy_document.vault-server.json}"
}

# Vault Client IAM Config
resource "aws_iam_instance_profile" "vault-client" {
name = "${var.environment_name}-vault-client-instance-profile"
role = "${aws_iam_role.vault-client.name}"
}

resource "aws_iam_role" "vault-client" {
name = "${var.environment_name}-vault-client-role"
assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

resource "aws_iam_role_policy" "vault-client" {
name = "${var.environment_name}-vault-client-role-policy"
role = "${aws_iam_role.vault-client.id}"
policy = "${data.aws_iam_policy_document.vault-client.json}"
}

//--------------------------------------------------------------------
// Data Sources

data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}

data "aws_iam_policy_document" "vault-server" {
statement {
sid = "ConsulAutoJoin"
effect = "Allow"

actions = ["ec2:DescribeInstances"]

resources = ["*"]
}

statement {
sid = "VaultAWSAuthMethod"
effect = "Allow"
actions = [
"ec2:DescribeInstances",
"iam:GetInstanceProfile",
"iam:GetUser",
"iam:GetRole"
],
resources = ["*"]
}

statement {
sid = "VaultKMSUnseal"
effect = "Allow"

actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:DescribeKey",
]

resources = ["*"]
}
}

data "aws_iam_policy_document" "vault-client" {
statement {
sid = "ConsulAutoJoin"
effect = "Allow"

actions = ["ec2:DescribeInstances"]

resources = ["*"]
}
}
16 changes: 16 additions & 0 deletions identity/vault-agent-demo/terraform-aws/kms.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//--------------------------------------------------------------------
// Resources

resource "aws_kms_key" "vault" {
description = "Vault unseal key"
deletion_window_in_days = 7

tags {
Name = "${var.environment_name}-vault-kms-unseal-key"
}
}

resource "aws_kms_alias" "vault" {
name = "alias/${var.environment_name}-vault-kms-unseal-key"
target_key_id = "${aws_kms_key.vault.key_id}"
}
14 changes: 14 additions & 0 deletions identity/vault-agent-demo/terraform-aws/network.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module "vault_demo_vpc" {
source = "terraform-aws-modules/vpc/aws"

name = "${var.environment_name}-vpc"
cidr = "10.0.0.0/16"

azs = ["${var.availability_zones}"]
private_subnets = ["10.0.1.0/24"]
public_subnets = ["10.0.101.0/24"]

tags = {
Name = "${var.environment_name}-vpc"
}
}
34 changes: 34 additions & 0 deletions identity/vault-agent-demo/terraform-aws/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
output "endpoints" {
value = <<EOF
Vault Server IP (public): ${join(", ", aws_instance.vault-server.*.public_ip)}
Vault Server IP (private): ${join(", ", aws_instance.vault-server.*.private_ip)}
For example:
ssh -i ${var.key_name}.pem ubuntu@${aws_instance.vault-server.0.public_ip}
Vault Client IP (public): ${aws_instance.vault-client.public_ip}
Vault Client IP (private): ${aws_instance.vault-client.private_ip}
For example:
ssh -i ${var.key_name}.pem ubuntu@${aws_instance.vault-client.public_ip}
EOF
}


# output "endpoints" {
# value = <<EOF

# Vault Server IP (public): ${aws_instance.vault-server.*.public_ip}
# Vault Server IP (private): ${aws_instance.vault-server.*.private_ip}

# For example:
# ssh -i ${var.key_name}.pem ubuntu@${aws_instance.vault-server.0.public_ip}

# Vault Client IP (public): ${aws_instance.vault-client.*.public_ip}
# Vault Client IP (private): ${aws_instance.vault-client.*.private_ip}

# For example:
# ssh -i ${var.key_name}.pem ubuntu@${aws_instance.vault-client.public_ip}
# EOF
# }
Loading

0 comments on commit 84de135

Please sign in to comment.