add vault integration
							parent
							
								
									dda094f168
								
							
						
					
					
						commit
						2dc35d8c0b
					
				@ -0,0 +1,2 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
 | 
			
		||||
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="none"><path fill="#FFD814" d="M0 0l7.971 15.516L16 0H0zm6.732 6.16h-1.27V4.89h1.27v1.27zm0-1.906h-1.27V2.985h1.27v1.269zm1.904 3.81h-1.27v-1.27h1.27v1.27zm0-1.905h-1.27V4.89h1.27v1.27zm0-1.905h-1.27V2.985h1.27v1.269zm1.894 1.905H9.26V4.89h1.27v1.27zM9.26 4.254V2.985h1.27v1.269H9.26z"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 506 B  | 
											
												Binary file not shown.
											
										
									
								| 
		 After Width: | Height: | Size: 202 KiB  | 
@ -0,0 +1,64 @@
 | 
			
		||||
---
 | 
			
		||||
display_name: vault
 | 
			
		||||
description: Authenticates with Vault and injects secrets into the environment.
 | 
			
		||||
icon: ../.icons/vault.svg
 | 
			
		||||
maintainer_github: coder
 | 
			
		||||
verified: true
 | 
			
		||||
tags: [helper, integration, vault]
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Hashicorp Vault
 | 
			
		||||
 | 
			
		||||
This module authenticates with Vault and injects secrets into the environment.
 | 
			
		||||
> **Note:** This module does not cover setting up and configuring Vault. For that, see the [Vault documentation](https://www.vaultproject.io/docs).
 | 
			
		||||
 | 
			
		||||
```hcl
 | 
			
		||||
module "vault" {
 | 
			
		||||
    source = "https://registry.coder.com/modules/vault"
 | 
			
		||||
    vault_addr = "https://vault.example.com"
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
 | 
			
		||||
### Configure Vault integration with a custom Vault auth id
 | 
			
		||||
 | 
			
		||||
See [docs](https://coder.com/docs/v2/latest/admin/external-auth) for more information what are external auth ids.
 | 
			
		||||
 | 
			
		||||
```hcl
 | 
			
		||||
module "vault" {
 | 
			
		||||
    source = "https://registry.coder.com/modules/vault"
 | 
			
		||||
    vault_addr = "https://vault.example.com"
 | 
			
		||||
    vault_auth_id = "my-auth-id"
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Configure Vault integration and automatically fetch secrets from Vault
 | 
			
		||||
 | 
			
		||||
Configure Vault integration and automatically fetch secrets from Vault and inject them into the workspace environment. This works by specifying the `secrets` variable with a list of secrets paths and keys to fetch from Vault. Multiple secrets can be specified by using a map of secret paths to a list of keys to fetch from each secret. For more information, see the [Vault documentation](https://www.vaultproject.io/api-docs/secret/kv/kv-v2#read-secret-version).
 | 
			
		||||
 | 
			
		||||
```hcl
 | 
			
		||||
For more information, see the [Vault documentation](https://www.vaultproject.io/docs/secrets/kv/kv-v2).
 | 
			
		||||
 | 
			
		||||
```hcl
 | 
			
		||||
module "vault" {
 | 
			
		||||
    source     = "https://registry.coder.com/modules/vault"
 | 
			
		||||
    vault_addr = "https://vault.example.com"
 | 
			
		||||
    secrets    = {
 | 
			
		||||
        "secret/data/foo" = ["FOO", "BAR"]
 | 
			
		||||
        "secret/data/bar" = ["BAZ"]
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Configure Vault integration and install a specific version of the Vault CLI
 | 
			
		||||
 | 
			
		||||
```hcl
 | 
			
		||||
module "vault" {
 | 
			
		||||
    source = "https://registry.coder.com/modules/vault"
 | 
			
		||||
    vault_addr = "https://vault.example.com"
 | 
			
		||||
    vault_cli_version = "1.15.0"
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
@ -0,0 +1,61 @@
 | 
			
		||||
terraform {
 | 
			
		||||
  required_version = ">= 1.0"
 | 
			
		||||
 | 
			
		||||
  required_providers {
 | 
			
		||||
    coder = {
 | 
			
		||||
      source  = "coder/coder"
 | 
			
		||||
      version = ">= 0.12"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Add required variables for your modules and remove any unneeded variables
 | 
			
		||||
variable "agent_id" {
 | 
			
		||||
  type        = string
 | 
			
		||||
  description = "The ID of a Coder agent."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variable "vault_addr" {
 | 
			
		||||
  type        = string
 | 
			
		||||
  description = "The address of the Vault server."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variable "vault_auth_id" {
 | 
			
		||||
  type        = string
 | 
			
		||||
  description = "The ID of the Vault auth method to use."
 | 
			
		||||
  default     = "vault"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variable "secrets" {
 | 
			
		||||
  type        = map(string)
 | 
			
		||||
  description = "A map of secrets to set as environment variables."
 | 
			
		||||
  default     = {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variable "vault_cli_version" {
 | 
			
		||||
  type        = string
 | 
			
		||||
  description = "The version of Vault to install."
 | 
			
		||||
  default     = "latest"
 | 
			
		||||
  # validate the version is in the format 0.0.0 or latest
 | 
			
		||||
  validation {
 | 
			
		||||
    condition     = can(regex("^(latest|[0-9]+\\.[0-9]+\\.[0-9]+)$", var.vault_version))
 | 
			
		||||
    error_message = "Vault version must be in the format 0.0.0 or latest"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
resource "coder_script" "vault" {
 | 
			
		||||
  agent_id     = var.agent_id
 | 
			
		||||
  display_name = "vault"
 | 
			
		||||
  icon         = "/icon/vault.svg"
 | 
			
		||||
  script = templatefile("${path.module}/run.sh", {
 | 
			
		||||
    VAULT_ADDR : var.vault_addr,
 | 
			
		||||
    VAULT_TOKEN : data.coder_external_auth.vault.access_token,
 | 
			
		||||
    VERSION : var.vault_cli_version,
 | 
			
		||||
    SECRETS : jsonencode(var.secrets),
 | 
			
		||||
  })
 | 
			
		||||
  run_on_start = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
data "coder_external_auth" "vault" {
 | 
			
		||||
  id = var.vault_auth_id
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,81 @@
 | 
			
		||||
#!/usr/bin/env sh
 | 
			
		||||
 | 
			
		||||
BOLD='\033[0;1m'
 | 
			
		||||
 | 
			
		||||
# Check if vault is installed
 | 
			
		||||
if ! command -v vault &> /dev/null; then
 | 
			
		||||
    printf "$${BOLD}Installing vault CLI ...\n\n"
 | 
			
		||||
    # check if wget is installed
 | 
			
		||||
    if ! command -v wget &> /dev/null; then
 | 
			
		||||
        printf "wget is not installed. Please install wget in your image.\n"
 | 
			
		||||
        exit 1
 | 
			
		||||
    fi
 | 
			
		||||
    # check if unzip is installed
 | 
			
		||||
    if ! command -v unzip &> /dev/null; then
 | 
			
		||||
        printf "unzip is not installed. Please install unzip in your image.\n"
 | 
			
		||||
        exit 1
 | 
			
		||||
    fi
 | 
			
		||||
    # check if VERSION is latest
 | 
			
		||||
    if [ "${VERSION}" = "latest" ]; then
 | 
			
		||||
        INSTALL_VERSION=$(curl -s https://releases.hashicorp.com/vault/ | grep -oP '[0-9]+\.[0-9]+\.[0-9]' | tr -d '<>' | head -1)
 | 
			
		||||
    else
 | 
			
		||||
        INSTALL_VERSION=${VERSION}
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    # download vault
 | 
			
		||||
    wget -O vault.zip https://releases.hashicorp.com/vault/$${INSTALL_VERSION}/vault_$${INSTALL_VERSION}_linux_amd64.zip
 | 
			
		||||
    unzip vault.zip
 | 
			
		||||
    sudo mv vault /usr/local/bin
 | 
			
		||||
    rm vault.zip
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
printf "🥳 Installation comlete!\n\n"
 | 
			
		||||
 | 
			
		||||
# Set up Vault address and token
 | 
			
		||||
export VAULT_ADDR=${VAULT_ADDR}
 | 
			
		||||
export VAULT_TOKEN=${VAULT_TOKEN}
 | 
			
		||||
 | 
			
		||||
# Verify Vault address and token
 | 
			
		||||
printf "🔎 Verifying Vault address and token ...\n\n"
 | 
			
		||||
vault status
 | 
			
		||||
 | 
			
		||||
# Set secrets if $SECRETS is set
 | 
			
		||||
if [ -z "${SECRETS}" ]; then
 | 
			
		||||
    printf "\n🔑 No secrets to set ...\n\n"
 | 
			
		||||
    exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
printf "\n🔑 Fetching secrets ...\n\n"
 | 
			
		||||
 | 
			
		||||
# Check if jq is installed
 | 
			
		||||
if ! command -v jq >/dev/null; then
 | 
			
		||||
    echo "jq is not installed. Please install jq to automatically set the secrets."
 | 
			
		||||
    exit 0 # exit with 0 to prevent failure (this is not a hard requirement, a user can still set the secrets manually)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Decode the JSON string to a temporary file
 | 
			
		||||
echo "$SECRETS" | jq '.' > temp.json
 | 
			
		||||
 | 
			
		||||
# Iterate through the keys and values in the JSON file
 | 
			
		||||
for key in $(jq -r 'keys[]' temp.json); do
 | 
			
		||||
    path=$(echo $key | tr -d \")
 | 
			
		||||
    # Fetch the secrets from Vault
 | 
			
		||||
    secrets=$(vault kv get -format=json $path)
 | 
			
		||||
    # Get the array of secret names from the JSON file
 | 
			
		||||
    sceret_names=$(jq -r ".$key[]" temp.json)
 | 
			
		||||
    # Convert the list of environment variables to an array
 | 
			
		||||
    IFS=', ' read -r -a sceret_array <<< "$sceret_names"
 | 
			
		||||
    # Set the environment variables with the secret values
 | 
			
		||||
    for secret_name in "${sceret_array[@]}"; do
 | 
			
		||||
        # Remove quotes from the variable name
 | 
			
		||||
        secret_name=$(echo $secret_name | tr -d \")
 | 
			
		||||
        # Assuming the secrets are stored in a key named 'data' in Vault
 | 
			
		||||
        secret_value=$(echo $secrets | jq -r ".data.data.$secret_name")
 | 
			
		||||
        export $secret_name=$secret_value
 | 
			
		||||
    done
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Remove the temporary file
 | 
			
		||||
rm temp.json
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue