Dynamic_Credentials.mp4
-
Configure Vault cluster & HVN in HCP using Terraform.
-
Terraform codes - LAMP-VAULT/1-Create-HVN-Cluster at main · myathway-lab/LAMP-VAULT (github.com)
resource "hcp_hvn" "mt-hcp-hvn" { hvn_id = var.hvn_id cloud_provider = var.cloud_provider region = var.region } resource "hcp_vault_cluster" "hcp_vault_cluster" { hvn_id = hcp_hvn.mt-hcp-hvn.hvn_id cluster_id = var.cluster_id tier = var.tier public_endpoint = true }
- Create AWS IAM user call “vault-admin” for Vault administration.
- Generate Access / Secret Keys for programmatic access.
- Attached Inline policy that grants specific permissions related to IAM user management for users whose names start with “vault-”.
- Full Terraform codes - https://github.com/myathway-lab/LAMP-VAULT/blob/main/2-create-aws-vaultadmin
-
TF Code
provider "aws" { region = var.aws_region } resource "aws_iam_user" "vault_admin" { name = var.user_name path = "/" tags = { Name = var.user_name } } resource "aws_iam_access_key" "vault_admin_accesskey" { user = aws_iam_user.vault_admin.name lifecycle { ignore_changes = [ user ] } } data "aws_iam_policy_document" "inline_po_vault" { statement { effect = "Allow" actions = [ "iam:AttachUserPolicy", "iam:CreateUser", "iam:CreateAccessKey", "iam:DeleteUser", "iam:DeleteAccessKey", "iam:DeleteUserPolicy", "iam:DetachUserPolicy", "iam:GetUser", "iam:ListAccessKeys", "iam:ListAttachedUserPolicies", "iam:ListGroupsForUser", "iam:ListUserPolicies", "iam:PutUserPolicy", "iam:AddUserToGroup", "iam:RemoveUserFromGroup" ] resources = [ "arn:aws:iam::0105xxxxxx30:user/vault-*" ] } } resource "aws_iam_user_policy" "inline_po_attach" { name = var.inline_po_name user = aws_iam_user.vault_admin.name policy = data.aws_iam_policy_document.inline_po_vault.json }
-
-
In this lab, we will use Dynamic creds which is generated by Vault to authenticate with AWS.
-
Dynamic creds are short-lived and automatically expire, reducing the risk of long-term exposure. Vault can automatically renew these credentials before they expire, ensuring continuous access without manual intervention. If needed, Vault can revoke the credentials at any time, immediately invalidating them.
-
Configure the AWS secrets engine in Vault with specified credentials, region, path, and lease settings. The lifecycle block tells Terraform to ignore changes to the
access_key
andsecret_key.
Vault will authenticate to AWS using “vault admin” account that we created in step2 2. Create AWS IAM User.resource "vault_aws_secret_backend" "aws" { description = "Vault AWS Secret Engine Resource for AWS Master Account" access_key = data.terraform_remote_state.vault_admin.outputs.vault_admin_accesskey secret_key = data.terraform_remote_state.vault_admin.outputs.vault_admin_secret_accesskey region = var.aws_region path = var.secret_path.master_secret_path default_lease_ttl_seconds = 600 max_lease_ttl_seconds = 3000 lifecycle { ignore_changes = [ access_key, secret_key ] } }
-
Configure a dynamic role in Vault’s AWS secrets engine that generates IAM user credentials with permissions to manage IAM, EC2, and STS resources.
resource "vault_aws_secret_backend_role" "iam_admin_dynamic_role" { backend = vault_aws_secret_backend.aws.path name = var.secret_role_name.master_iamadmin_role_name credential_type = var.credential_type.iam_user policy_document = <<EOT { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iam:*", "Resource": "*" }, { "Effect": "Allow", "Action": "ec2:*", "Resource": "*" }, { "Effect": "Allow", "Action": "sts:*", "Resource": "*" } ] } EOT }
-
Once we configured AWS secret engine & confirmed dynamic creds are able to generate, we will rotate
-
Full Terraform codes - https://github.com/myathway-lab/LAMP-VAULT/blob/main/3-create-vault-dynamic-roles
- The
data "vault_aws_access_credentials" "master_iamadmin_creds"
block fetches temporary AWS cred from Vault dynamic role which we created in 3. Create Vault Roles for AWS Dynamic Credentials. - Terraform will use this dynamic cred to authenticate with AWS.
- Then create network resources and security groups for EC2 instances which we will setup in 6. Create EC2 Instances.
- Terraform code - https://github.com/myathway-lab/LAMP-VAULT/blob/main/4-Create-VPC-SG
-
Create a VPC with specified IP range, tenancy, DNS settings.
resource "aws_vpc" "main" { cidr_block = var.cidr instance_tenancy = var.instance_tenancy enable_dns_hostnames = var.enable_dns_hostnames enable_dns_support = var.enable_dns_support tags = merge( { "Name" = var.name }, var.tags ) }
-
Create a public subnet within the above VPC, specifies the AZ, cidr_block and map_public_ip_on_launch to ensure that all the instances in this public subnet receive a public IP address. Create route table and associate.
resource "aws_vpc" "main" { cidr_block = var.cidr instance_tenancy = var.instance_tenancy enable_dns_hostnames = var.enable_dns_hostnames enable_dns_support = var.enable_dns_support tags = merge( { "Name" = var.name }, var.tags ) }
-
Create a public subnet within the above VPC, specifies the AZ, cidr_block and map_public_ip_on_launch to ensure that all the instances in this public subnet receive a public IP address. Create route table and associate.
################################################################################ # Publiс Subnet For Web Servers ################################################################################ resource "aws_subnet" "public" { count = local.len_public_subnets vpc_id = aws_vpc.main.id availability_zone = data.aws_availability_zones.azs.names[0] cidr_block = var.public_subnets[count.index] map_public_ip_on_launch = var.map_public_ip_on_launch tags = { Name = "Pub-Subnet-Web" } } resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id tags = { Name = "RouteTable-Web" } } resource "aws_route_table_association" "public" { count = local.len_public_subnets route_table_id = aws_route_table.public.id subnet_id = aws_subnet.public[count.index].id } resource "aws_route" "public_internet_gateway" { route_table_id = aws_route_table.public.id destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.this.id timeouts { create = "5m" } }
-
Create a private subnet within the above VPC, specifies the AZ, cidr_block. Create route table and associate.
############################################################################### # Private Subnets for DB Servers ################################################################################ resource "aws_subnet" "private" { count = local.len_private_subnets vpc_id = aws_vpc.main.id availability_zone = data.aws_availability_zones.azs.names[1] cidr_block = var.private_subnets[count.index] tags = { Name = "Pri-Subnet-DB" } } resource "aws_route_table" "private" { vpc_id = aws_vpc.main.id tags = { Name = "DB-RouteTable" } } resource "aws_route_table_association" "private" { count = local.len_private_subnets route_table_id = aws_route_table.private.id subnet_id = element(aws_subnet.private[*].id, count.index) } resource "aws_route" "private_nat_gateway" { route_table_id = aws_route_table.private.id destination_cidr_block = var.nat_gateway_destination_cidr_block nat_gateway_id = aws_nat_gateway.nat.id timeouts { create = "5m" } }
-
Create Internet gateway.
################################################################################ # Internet Gateway ################################################################################ resource "aws_internet_gateway" "this" { vpc_id = aws_vpc.main.id tags = merge( { "Name" = var.name }, var.tags, ) }
-
Create NAT gateway.
################################################################################ # NAT Gateway ################################################################################ resource "aws_eip" "nat" { domain = "vpc" depends_on = [aws_internet_gateway.this] } resource "aws_nat_gateway" "nat" { allocation_id = aws_eip.nat.id subnet_id = element( aws_subnet.public[*].id, 0 ) depends_on = [aws_internet_gateway.this] tags = { Name = "LAMP NAT" } }
-
Security Group for Web Servers
################################################################################ # Security Group for Web Servers ################################################################################ resource "aws_security_group" "Web-SecurityGroup" { name = "Web-SecurityGroup" description = "Allow inbound and outbound traffic for Web servers" vpc_id = aws_vpc.main.id tags = { Name = "Web-SecurityGroup" } } resource "aws_vpc_security_group_ingress_rule" "allow_http" { security_group_id = aws_security_group.Web-SecurityGroup.id cidr_ipv4 = "0.0.0.0/0" from_port = 80 ip_protocol = "tcp" to_port = 80 } resource "aws_vpc_security_group_ingress_rule" "allow_https" { security_group_id = aws_security_group.Web-SecurityGroup.id cidr_ipv4 = "0.0.0.0/0" from_port = 443 ip_protocol = "tcp" to_port = 443 } resource "aws_vpc_security_group_ingress_rule" "allow_ssh_to_all" { security_group_id = aws_security_group.Web-SecurityGroup.id cidr_ipv4 = "0.0.0.0/0" from_port = 22 ip_protocol = "tcp" to_port = 22 } resource "aws_vpc_security_group_egress_rule" "allow_all" { security_group_id = aws_security_group.Web-SecurityGroup.id cidr_ipv4 = "0.0.0.0/0" ip_protocol = "-1" # semantically equivalent to all ports }
-
Security Group for DB Servers
################################################################################ # Security Group for DB Servers ################################################################################ resource "aws_security_group" "DB-SecurityGroup" { name = "DB-SecurityGroup" description = "Allow inbound and outbound traffic for Db servers" vpc_id = aws_vpc.main.id tags = { Name = "DB-SecurityGroup" } } resource "aws_vpc_security_group_ingress_rule" "allow_ssh" { for_each = toset(var.public_subnets) security_group_id = aws_security_group.DB-SecurityGroup.id cidr_ipv4 = each.value from_port = 22 ip_protocol = "tcp" to_port = 22 } resource "aws_vpc_security_group_ingress_rule" "allow_vault" { security_group_id = aws_security_group.DB-SecurityGroup.id cidr_ipv4 = "172.25.16.0/20" from_port = 3306 ip_protocol = "tcp" to_port = 3306 } resource "aws_vpc_security_group_ingress_rule" "allow_websever" { security_group_id = aws_security_group.DB-SecurityGroup.id cidr_ipv4 = var.public_subnets[0] from_port = 3306 ip_protocol = "tcp" to_port = 3306 } resource "aws_vpc_security_group_egress_rule" "allow_http" { security_group_id = aws_security_group.DB-SecurityGroup.id cidr_ipv4 = "0.0.0.0/0" from_port = 80 ip_protocol = "tcp" to_port = 80 } resource "aws_vpc_security_group_egress_rule" "allow_https" { security_group_id = aws_security_group.DB-SecurityGroup.id cidr_ipv4 = "0.0.0.0/0" from_port = 443 ip_protocol = "tcp" to_port = 443 } resource "aws_vpc_security_group_egress_rule" "allow_vaultport" { security_group_id = aws_security_group.DB-SecurityGroup.id cidr_ipv4 = "0.0.0.0/0" from_port = 8200 ip_protocol = "tcp" to_port = 8200 }
-
-
Same as step 4, Terraform will use aws dynamic cred to authenticate with AWS.
-
Establishes a peering connection between an HVN and an AWS VPC.
-
Configures the necessary routes to enable communication between HVN and AWS VPC.
-
Full Terraform code - https://github.com/myathway-lab/LAMP-VAULT/blob/main/5-VPC-Peering
-
Create HVN to AWS Peering
###cretae hvn to aws peering### resource "hcp_aws_network_peering" "dev" { hvn_id = var.hvn_id peering_id = var.peering_id peer_vpc_id = var.peer_vpc_id peer_account_id = var.owner_id peer_vpc_region = var.peer_region }
-
To automatically accept the peering connection on the AWS.
resource "aws_vpc_peering_connection_accepter" "peer" { vpc_peering_connection_id = hcp_aws_network_peering.dev.provider_peering_id auto_accept = true }
-
Add Routes for HVN
resource "hcp_hvn_route" "hvn-to-aws-route" { hvn_link = data.hcp_hvn.hvn_vault.self_link hvn_route_id = "hvn-aws-route" destination_cidr = "10.0.0.0/16" target_link = hcp_aws_network_peering.dev.self_link }
-
Add Routes for AWS
resource "aws_route" "route_for_private" { route_table_id = var.private_routetb_id destination_cidr_block = data.hcp_hvn.hvn_vault.cidr_block vpc_peering_connection_id = aws_vpc_peering_connection_accepter.peer.id } resource "aws_route" "route_for_public" { route_table_id = var.public_routetb_id destination_cidr_block = data.hcp_hvn.hvn_vault.cidr_block vpc_peering_connection_id = aws_vpc_peering_connection_accepter.peer.id }
- Same as previous steps, Terraform will use dynamic creds generated from vault role to authenticate with AWS to deploy EC2 resources.
- Full Terraform codes - https://github.com/myathway-lab/LAMP-VAULT/blob/main/6-Create-EC2-Instances
- Refer Setup Apache/PHP server Setup MySQL server for detailed setup.
We will setup LAMP (Linux, Apache, MySQL, PHP) stack on AWS with separate EC2 instances for MySQL and Apache/PHP.
Whenever the Apache service needs to authenticate with DB, it talks to Vault. Then Vault authenticates with DB and generate DB dynamic creds.
In this lab, we will use Vault Agent with auto-auth to automatically renew the dynamic creds before expiring. This ensures that web server always has valid credentials.
Renewing the Vault Token: Vault agent uses vault aws auth role
vault-role-for-ec2role
to authenticate Vault server and obtain a Vault token. This token is then periodically renewed to ensure continuous access.Renewing Database creds: Vault agent reads the database credentials from
database/creds/db-role
and writes themvar/www/html/db-creds.json
This ensures that database credentials are always up-to-date.
vault-agent.hcl (Vault Agent Config)
exit_after_auth = false pid_file = "/var/run/vault-agent.pid" auto_auth { method "aws" { mount_path = "auth/aws" config = { type = "iam" role = "vault-role-for-ec2role" } } sink "file" { config = { path = "/var/www/html/vault-token-via-agent" } } } vault { address = "${vault_addr}" } template { source = "/etc/vault.d/db-creds-template.hcl" destination = "/var/www/html/db-creds.json" }
- High-level workflow
- Detailed workflow
- Expected Result: “Automatically renew the dynamic creds before expiring & Ensures web server always has valid credentials”.
-
Before we launch EC2, we need to create AWS IAM role named “aws-ec2role-for-vault-authmethod” for HCP Vault Dedicated auth method.
-
Then launch Web server in public subnet.
-
Attach a security group defined in ‣.
-
Attach “aws-ec2role-for-vault-authmethod” IAM role in web server.
-
Add user data.
**- Update the package manager & install Apache and PHP related packages.
- Configures Vault Agent with AWS IAM method.**
- Use Vault’s Auto-Auth method using AWS IAM roles to allow Vault to automatically authenticate and retrieve a token.
- Write PHP Code “/var/www/html/phptest.php” to test DB Connection.
- Write PHP Code “/var/www/html/usersubmission.php” to verify the DB dynamic user privileges to LAMP database.
-
Setup Web Sever
resource "aws_instance" "LAMP-WEB" { ami = "ami-01811d4912b4ccb26" instance_type = "t2.micro" key_name = var.key_name subnet_id = var.Pub-Subnet-Web vpc_security_group_ids = var.Web-SecurityGroup-id iam_instance_profile = var.iam_role associate_public_ip_address = true root_block_device { volume_size = 30 volume_type = "gp3" } user_data = templatefile("${path.module}/web_user_data.tpl", { vault_addr = var.vault_addr, db_ip = var.db_ip }) tags = { Name = "LAMP-WEB" } } resource "aws_eip" "LAMP-WEB-EIP" { vpc = true instance = aws_instance.LAMP-WEB.id }
-
web_user_data.tpl (user data for webserver)
#!/bin/bash set -e sudo hostnamectl set-hostname LAMP-WEB sudo apt-get update -y sudo apt-get install apache2 -y sudo apt-get install php libapache2-mod-php php-mysql php-curl php-gd php-json php-zip gpg wget -y sudo apt install mysql-client -y sudo wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt update && sudo apt install vault # Create the Vault agent configuration file sudo cat <<EOF > /etc/vault.d/vault-agent.hcl exit_after_auth = false pid_file = "/var/run/vault-agent.pid" auto_auth { method "aws" { mount_path = "auth/aws" config = { type = "iam" role = "vault-role-for-ec2role" } } sink "file" { config = { path = "/var/www/html/vault-token-via-agent" } } } vault { address = "${vault_addr}" } template { source = "/etc/vault.d/db-creds-template.hcl" destination = "/var/www/html/db-creds.json" } EOF sudo chown vault:vault /etc/vault.d/vault-agent.hcl sudo chmod 600 /etc/vault.d/vault-agent.hcl # Read the DB role creds sudo cat <<EOF > /etc/vault.d/db-creds-template.hcl { "username": "{{ with secret "database/creds/db-role" }}{{ .Data.username }}{{ end }}", "password": "{{ with secret "database/creds/db-role" }}{{ .Data.password }}{{ end }}" } EOF sudo chown vault:vault /etc/vault.d/db-creds-template.hcl sudo chmod 600 /etc/vault.d/vault-agent.hcl ##Run vault agent as service sudo cat <<EOF > /etc/systemd/system/vault-agent.service [Unit] Description=Vault Agent After=network.target [Service] Environment="VAULT_NAMESPACE=admin" Environment="VAULT_ADDR=${vault_addr}" ExecStart=/usr/bin/vault agent -config=/etc/vault.d/vault-agent.hcl Restart=on-failure [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vault-agent sudo systemctl start vault-agent #Configure PHP code for dynamic DB cred check sudo cat <<'EOF' > /var/www/html/phptest1.php <?php // Enable error reporting error_reporting(E_ALL); ini_set('display_errors', 1); // Path to the JSON file with database credentials $credsFile = '/var/www/html/db-creds.json'; // Read the JSON file $json = file_get_contents($credsFile); if ($json === false) { die("Failed to read credentials file."); } $creds = json_decode($json, true); if ($creds === null) { die("Failed to decode JSON."); } // Debugging output echo "Username: " . htmlspecialchars($creds['username']) . "<br>"; echo "Password: " . htmlspecialchars($creds['password']) . "<br>"; // Database connection parameters $servername = "${db_ip}"; // e.g., "localhost" or your server IP $username = $creds['username']; $password = $creds['password']; $dbname = "lamp"; // the name of your database // Create connection $conn = new mysqli($servername, $username, $password, $dbname); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } echo "Connected successfully to the database."; ?> EOF #Configure PHP code for dynamic cred to verify the access sudo cat <<'EOF' > /var/www/html/usersubmission.php <?php // Enable error reporting error_reporting(E_ALL); ini_set('display_errors', 1); // Path to the JSON file with database credentials $credsFile = '/var/www/html/db-creds.json'; // Read the JSON file $json = file_get_contents($credsFile); if ($json === false) { die("Failed to read credentials file."); } $creds = json_decode($json, true); if ($creds === null) { die("Failed to decode JSON."); } // Database connection parameters $servername = "10.0.2.217"; // e.g., "localhost" or your server IP $username = $creds['username']; $password = $creds['password']; $dbname = "lamp"; // the name of your database // Create connection $conn = new mysqli($servername, $username, $password, $dbname); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } echo "Connected successfully to the database.<br>"; // Handle form submission if ($_SERVER["REQUEST_METHOD"] == "POST") { $user = $_POST['username']; $email = $_POST['email']; $pass = $_POST['password']; // Insert data into the users table $sql = "INSERT INTO users (username, email, password) VALUES ('$user', '$email', '$pass')"; if ($conn->query($sql) === TRUE) { echo "New user created successfully. Below is the LAMP User List. <br>"; } else { echo "Error: " . $sql . "<br>" . $conn->error; } } // Retrieve and display all users $sql = "SELECT id, username, email FROM users"; $result = $conn->query($sql); if ($result->num_rows > 0) { echo "<h3>Users List</h3>"; echo "<table border='1'><tr><th>ID</th><th>Username</th><th>Email</th></tr>"; while($row = $result->fetch_assoc()) { echo "<tr><td>" . $row["id"]. "</td><td>" . $row["username"]. "</td><td>" . $row["email"]. "</td></tr>"; } echo "</table>"; } else { echo "0 results"; } $conn->close(); ?> <!DOCTYPE html> <html> <head> <title>Register User</title> </head> <body> <h3>Register User</h3> <form method="post" action=""> <label for="username">Username:</label> <input type="text" id="username" name="username" required><br><br> <label for="email">Email:</label> <input type="email" id="email" name="email" required><br><br> <label for="password">Password:</label> <input type="password" id="password" name="password" required><br><br> <input type="submit" name="submit" value="Register"> </form> </body> </html> EOF sudo systemctl restart vault-agent.service sudo systemctl restart apache2
-
Launch MySQL server in private subnet and attach a security group defined in ‣.
-
Add user data.
- Update the package manager & install MySQL related packages.
- Configure MySQL & allow remote client access.
- Create “lampuser” in DB.
- When webserver tries to access database, vault agent from webserver will read the DB-Role from Vault.
- DB-Role will use “lampuser” to authenticate with Database to generate dynamic user.
- So, we need to give “create user” and “drop” with “grant” privileges to “lampuser”.
-
Launch DB Sever
resource "aws_instance" "LAMP-MySQL" { ami = "ami-01811d4912b4ccb26" instance_type = "t2.micro" key_name = var.key_name subnet_id = var.Pri-Subnet-DB vpc_security_group_ids = var.DB-SecurityGroup-id private_ip = var.db_ip root_block_device { volume_size = 30 volume_type = "gp3" } user_data = templatefile("${path.module}/mysql_user_data.tpl", { mysql_root_password = var.mysql_root_password, mysql_lamp_password = var.mysql_lamp_password }) tags = { Name = "LAMP-MySQL" } }
-
mysql_user_data.tpl (user data for db server)
#!/bin/bash set -e sudo hostnamectl set-hostname LAMP-MySQL sudo apt-get update -y sudo apt-get install mysql-server -y # Secure MySQL installation sudo mysql_secure_installation <<EOF y 0 y y y y EOF # Login to MySQL with root user and empty password, then change the root password # root_password="${mysql_root_password}" root_password="${mysql_root_password}" sudo mysql -u root --execute="ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '$root_password'; FLUSH PRIVILEGES;" # Run additional MySQL commands lamp_password="${mysql_lamp_password}" sudo mysql -u root -p"$root_password" <<EOF CREATE DATABASE lamp; CREATE USER 'lampuser'@'%' IDENTIFIED BY '$lamp_password'; GRANT ALL PRIVILEGES ON lamp.* TO 'lampuser'@'%'; GRANT DROP ON mysql.* TO 'lampuser'@'%' WITH GRANT OPTION; GRANT CREATE USER ON *.* TO 'lampuser'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, password VARCHAR(255) NOT NULL ); EOF # Change the bind address to all to accept remote connection. sudo sed -i 's/^bind-address\s*=.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf # Restart the mysql after config change. sudo systemctl restart mysql
-
We need to make sure EC2 Webserver able to talk with vault to read the DB creds.
-
In Vault server, we will enable database secret engine, configure database connection and create role for dynamic creds.
-
Vault agent inside EC2 webserver will read the role and get dynamic creds from vault.
-
Full Terraform codes - https://github.com/myathway-lab/LAMP-VAULT/blob/main/7-Create-Vault-DB-Role
-
Enable database secrets engine at the path “database”
resource "vault_mount" "db" { path = "database" type = "database" description = "This is for mysql db secret engine." }
-
Sets up the connection to the MySQL database
resource "vault_database_secret_backend_connection" "lamp-mysql-db" { backend = vault_mount.db.path name = "lamp-mysql-db" allowed_roles = ["db-role"] verify_connection = true mysql{ connection_url = "{{username}}:{{password}}@tcp(${var.db_ip}:3306)/" username = var.lamp_username password = var.lamp_password } }
-
Defines a role that can create users in the MySQL database & grant all privileges to lamp database.
resource "vault_database_secret_backend_role" "db-role" { backend = vault_mount.db.path name = "db-role" db_name = vault_database_secret_backend_connection.lamp-mysql-db.name creation_statements = ["CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT ALL PRIVILEGES ON lamp.* TO '{{name}}'@'%';"] default_ttl = "180" max_ttl = "300" }
-
For AWS EC2 instances to authenticate with Vault, we can use AWS auth method. This method supports two types of authentications, “IAM Method” & “EC2 Method”.
-
In this scenario, we will use AWS auth IAM method using Vault Agent.
-
Please refer vault agent setup in Setup Apache/PHP server
-
Full Terraform codes - https://github.com/myathway-lab/LAMP-VAULT/blob/main/7-Create-Vault-DB-Role
-
Enable the AWS authentication method in Vault
resource "vault_auth_backend" "aws" { type = "aws" }
-
Configure the AWS client with the necessary access and secret keys to authenticate with Vault.
resource "vault_aws_auth_backend_client" "client" { backend = vault_auth_backend.aws.path access_key = data.vault_aws_access_credentials.master_iamadmin_creds.access_key secret_key = data.vault_aws_access_credentials.master_iamadmin_creds.secret_key }
-
Define a policy that grants read access to the database credentials at the specified path.
resource "vault_policy" "vault-policy-for-ec2role" { name = "vault-policy-for-ec2role" policy = <<EOT path "database/creds/db-role" { capabilities = ["read"] } EOT }
-
Create a role that allows EC2 instances with the specified IAM role to authenticate with Vault and obtain tokens with the defined policy.
resource "vault_aws_auth_backend_role" "vault-role-for-ec2role" { backend = vault_auth_backend.aws.path role = "vault-role-for-ec2role" auth_type = "iam" bound_iam_principal_arns = ["arn:aws:iam::01052xxxxxxx030:role/aws-ec2role-for-vault-authmethod"] token_ttl = 120 token_max_ttl = 300 token_policies = ["vault-policy-for-ec2role"] }