In my previous blog, I talked about managing static secrets with HashiCorp Vault using the Vault token. Let's move one step further.
Using AppRole for authentication in HashiCorp Vault offers several advantages over using traditional Vault tokens:
Limited Access Scope: When you create an AppRole, you can define a specific policy associated with it to restrict the access scope. In contrast, traditional tokens may have broader access to all paths and operations permitted by the policies attached to them.
Shorter Lifespan: AppRole Secret IDs have a shorter lifespan compared to traditional Vault tokens. This means that even if the Secret ID is compromised, its usability is limited to the validity period, which is usually short. Tokens, on the other hand, may have a longer lifespan, making them riskier if leaked or stolen.
Dynamic Secret Generation: When using AppRole, you can dynamically generate Secret IDs for each authentication request. This ensures that each instance or entity using the AppRole has a unique Secret ID, which enhances security and reduces the risk of token reuse.
Revocation: AppRoles provide easy revocation of access. If there is a need to revoke access for a specific entity or service, you can revoke the associated Secret ID without affecting other entities using the AppRole. In contrast, revoking a traditional Vault token affects all entities using that token.
Enhanced Security: AppRole is designed specifically for application authentication, which minimizes the risk of exposing the primary Vault token. Traditional tokens, if exposed, could potentially grant broader access to sensitive data in Vault.
While AppRole provides these advantages, it's essential to handle Role IDs and Secret IDs securely, just like any other sensitive credentials.
Authentication using AppRole
Set up the Vault Provider: Configure the Vault provider which allows Terraform to communicate with HashiCorp Vault.
provider "vault" { address = "https://your_vault_url.com" }
Authentication: Let's set up an authentication mechanism using the AppRole method to fetch the token securely. For this, we will use CLI commands.
Login into Vault using cmd:
SET VAULT_ADDR=https://your_vault_url.com vault login <VAULT_TOKEN> vault secrets list
Enable the AppRole auth method:
vault auth enable approle
Create an ACL (Access Control List) policy in Vault: Policies in Vault are written in HCL (HashiCorp Configuration Language) or JSON format and define the access permissions for different paths and operations within Vault.
Here's an example of a simple policy named
terraform-variables
that allows read access to a specific path and creates new child tokens. Despite the auth method being AppRole, Terraform still use tokens and it will issue itself a new token that is a child of the vault token, with a short TTL to limit the exposure of any requested secrets.path "terraform/data/variables/*" { capabilities = ["read"] } path "auth/token/create" { capabilities = ["update"] }
Create an AppRole and associate the policy: Once you have the policy ready, you can associate it with the AppRole. The token generated will be temporary because we have specified TTL.
vault write auth/approle/role/my-role token_policies="terraform-variables" token_ttl=30m token_max_ttl=1h
Verify the association: After associating the policy, you can verify the association.
vault read auth/approle/role/my-role
Get Role ID:
vault read auth/approle/role/my-role/role-id
Get Secret ID:
vault write -f auth/approle/role/my-role/secret-id
Note: The Secret ID is only shown once during its generation, and you should copy it and keep it secure. If you lose the Secret ID, you will need to generate a new one.
Keep in mind that both the Role ID and Secret ID are sensitive pieces of information that grant access to the associated AppRole. Ensure that you handle them securely
Export Role ID and Secret ID as environment variables: Export the Role ID and Secret ID as environment variables in your shell. These will be used by Terraform to authenticate with Vault.
export VAULT_ROLE_ID="your-role-id" export VAULT_SECRET_ID="your-secret-id"
Update Terraform configuration to use the AppRole authentication:
provider "vault" { address = "https://your_vault_url.com" skip_tls_verify = true skip_child_token = true // Authentication using AppRole auth_login { path = "auth/approle/login" parameters = { role_id = var.vault_role_id secret_id = var.vault_secret_id } } } variable "vault_role_id" {} variable "vault_secret_id" {}
Accessing Secrets: Now that Terraform is authenticated with Vault, you can access secrets by using the
vault_generic_secret
data source.For example, let's say you have a secret named "RDS" with username and password stored in Vault.
data "vault_generic_secret" "rds" { path = "terraform/variables/RDS" } resource "aws_db_instance" "this" { for_each = local.rds_db identifier = each.value.name engine = each.value.engine engine_version = each.value.engine_version instance_class = each.value.instance_class allocated_storage = each.value.allocated_storage username = data.vault_generic_secret.rds.data.rds_username password = data.vault_generic_secret.rds.data.rds_password vpc_security_group_ids = var.vpc_security_group_ids db_subnet_group_name = aws_db_subnet_group.this[each.value.name].id availability_zone = var.availability_zone multi_az = var.multi_az publicly_accessible = var.publicly_accessible tags = merge( { "Name" = format("%s", each.value.name) }, var.tags ) }
In this example, we're using the Vault provider to access the secret at the path "terraform/variables/RDS" and extracting the username and password from it. These values for username and password can then be used in the AWS DB instance resource.
Apply Terraform: When you run
terraform apply
, Terraform will use the AppRole authentication method and fetch the token securely using the provided Role ID and Secret ID.
Conclusion
By using AppRole authentication, you can avoid exposing sensitive tokens directly in your Terraform configuration. Instead, they are fetched securely from the environment variables, making your setup more secure. Just remember to keep the Role ID and Secret ID well protected and manage their access carefully.