Accessing secrets using AppRoles on HashiCorp Vault

Accessing secrets using AppRoles on HashiCorp Vault

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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

  1. 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"
     }
    
  2. Authentication: Let's set up an authentication mechanism using the AppRole method to fetch the token securely. For this, we will use CLI commands.

    1. Login into Vault using cmd:

       SET VAULT_ADDR=https://your_vault_url.com 
      
       vault login <VAULT_TOKEN>
      
       vault secrets list
      
    2. Enable the AppRole auth method:

       vault auth enable approle
      
    3. 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"]
       }
      
    4. 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
      
    5. Verify the association: After associating the policy, you can verify the association.

       vault read auth/approle/role/my-role
      
    6. Get Role ID:

       vault read auth/approle/role/my-role/role-id
      
    7. 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

    8. 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"
      
    9. 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" {}
      
  3. 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.

  4. 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.