ex) vault 상태 확인
vault status -> docker exec -it vault sh -c 'export VAULT_TOKEN="root" && vault status'
ex) secret 추가, 정책 추가, 사용자 인증 설정, 사용자 추가, etc 등
mkdir vault-docker
cd vault-docker
version: '3.7'
services:
vault:
image: vault:1.13.2 # Specify a known version
container_name: vault
restart: unless-stopped
environment:
VAULT_DEV_ROOT_TOKEN_ID: root
VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
ports:
- "8200:8200"
cap_add:
- IPC_LOCK
volumes:
- ./vault-data:/vault/file
command: vault server -dev -dev-root-token-id="root"
docker-compose up -d
To give a user broader access, such as viewing secrets stored in the secret/ path, you need to create a policy that allows access to those secrets.
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
version: '3.7'
services:
vault:
image: vault:1.13.2
container_name: vault
ports:
- "8200:8200"
environment:
VAULT_DEV_ROOT_TOKEN_ID: root
VAULT_TOKEN: "root" # Add this line for set up env VAULT_TOKEN on bash of container
cap_add:
- IPC_LOCK
volumes:
- ./vault-data:/vault/file
- ./:/vault/config # This mounts the current directory
command: vault server -dev -dev-root-token-id="root"
docker exec -it vault vault policy write secret-policy /vault/config/secret-policy.hcl
vault auth enable userpass
# one by one user
vault write auth/userpass/users/your-username password="yourPassword" policies="default,secret-policy"
# to all uesrs => List of users to assign the policy to
# how to give each of them qunique password?
# shell file
Option 1: Associative Array (Bash 4.0+)
declare -A USERS_PASSWORDS
# Define users and their unique passwords
USERS_PASSWORDS=(
["user1"]="password1"
["user2"]="password2"
["user3"]="password3"
)
for user in "${!USERS_PASSWORDS[@]}"; do
password="${USERS_PASSWORDS[$user]}"
vault write auth/userpass/users/$user password="$password" policies="default,secret-policy"
done
Option 2: Parallel Arrays (Bash Pre-4.0)
USERS=("user1" "user2" "user3")
PASSWORDS=("password1" "password2" "password3")
for i in "${!USERS[@]}"; do
user="${USERS[$i]}"
password="${PASSWORDS[$i]}"
vault write auth/userpass/users/$user password="$password" policies="default,secret-policy"
done
Option 3: Generate Random Passwords
USERS=("user1" "user2" "user3")
for user in "${USERS[@]}"; do
password=$(openssl rand -base64 12) # Generate a random 12-character password
echo "Creating user $user with password $password"
vault write auth/userpass/users/$user password="$password" policies="default,secret-policy"
done
version: '3.7'
services:
vault:
image: vault:1.13.2 # Specify a known version
container_name: vault
restart: unless-stopped
environment:
VAULT_ADDR: "http://127.0.0.1:8200" # Add this line for http access on dev mode
VAULT_TOKEN: "root" # Add this line for set up env VAULT_TOKEN on bash of container
ports:
- "8200:8200"
cap_add:
- IPC_LOCK
volumes:
- ./vault-data:/vault/file # Persistent volume for Vault data
- ./config:/vault/config # This mounts the current directory
command: vault server -config=/vault/config/vault.hcl # Use production config here
networks:
- vault-network
volumes:
vault-data:
external: false # Persistent volume for Vault data
networks:
vault-network:
external: true
docker-compose up -d
docker exec -it vault vault operator init
docker exec -it vault vault operator unseal <unseal_key_1>
docker exec -it vault vault operator unseal <unseal_key_2>
docker exec -it vault vault operator unseal <unseal_key_3>
To give a user broader access, such as viewing secrets stored in the secret/ path, you need to create a policy that allows access to those secrets.
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
vault policy write secret-policy secret-policy.hcl
vault auth enable userpass
You need to configure Vault to support the AppRole authentication method and create a role that Vault Agent can use to authenticate.
vault kv put secret/my-django-secret secret_key="your-django-secret-key"
vault kv put secret/db-creds db_name="your-db-name" username="your-username" password="your-password" host="localhost" port="5432"
# root/config/secret-agent-policy.hcl
path "secret/*" {
capabilities = ["read", "list"]
}
3.Upload the policy:
vault policy write secret-policy secret-policy.hcl
vault auth enable approle
vault write auth/approle/role/my-role policies="secret-policy"
vault read auth/approle/role/my-role/role-id
vault write -f auth/approle/role/my-role/secret-id
Use the generated role_id and secret_id to authenticate Vault Agent.
mkdir vault-agent
vault-agent/docker-compose.yml
version: '3.7'
services:
vault-agent:
image: vault:1.13.2
container_name: vault-agent
cap_add:
- IPC_LOCK # Adding IPC_LOCK capability to allow memory locking
volumes:
- ./vault-agent-config:/etc/vault-agent
- ../../developments/sample_project/django_rest_framework/project/config:/django_rest_framework/project/config # This mounts the DRF config directory
- ./role-id:/etc/vault-agent/role-id # Mount the role-id file
- ./secret-id:/etc/vault-agent/secret-id:rw # Mount the secret-id file # Ensure it's mounted as read-write
command: vault agent -config=/etc/vault-agent/agent.hcl
networks:
- vault-network
networks:
vault-network:
external: true
n the vault-agent-config/ directory, create a configuration file for Vault Agent. This file will define how Vault Agent authenticates with Vault and where to render the secrets.
vault-agent/vault-agent-config/agent.hcl
auto_auth {
method "approle" {
mount_path = "auth/approle"
config = {
role_id_file_path = "/etc/vault-agent/role-id"
secret_id_file_path = "/etc/vault-agent/secret-id"
remove_secret_id_file_after_reading = false
}
}
}
template {
source = "/etc/vault-agent/templates/settings.tpl"
destination = "/app/project/config/settings_vault.py"
}
vault {
address = "http://vault:8200"
}
# Enabling the agent to dynamically update secrets and keep running
exit_after_auth = false
nano role-id
vault-agent/secret-id
nano secret-id
he template file instructs Vault Agent on how to retrieve secrets from Vault and how to render them into a configuration file.
In the vault-agent-config/templates/ directory, create the following template file:
vault-agent/vault-agent-config/templates/settings.tpl
# Django settings from Vault
SECRET_KEY = "{{ with secret "secret/my-django-secret" }}{{ .Data.data.secret_key }}{{ end }}"
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': "{{ with secret "secret/db-creds" }}{{ .Data.data.db_name }}{{ end }}",
'USER': "{{ with secret "secret/db-creds" }}{{ .Data.data.username }}{{ end }}",
'PASSWORD': "{{ with secret "secret/db-creds" }}{{ .Data.data.password }}{{ end }}",
'HOST': "{{ with secret "secret/db-creds" }}{{ .Data.data.host }}{{ end }}",
'PORT': "{{ with secret "secret/db-creds" }}{{ .Data.data.port }}{{ end }}",
}
}
vault-agent-docker/
├── vault-agent-config/
│ ├── templates/
│ │ └── settings.tpl
│ ├── agent.hcl
│ ├── role-id
│ └── secret-id
├── docker-compose.agent.yml
├── role-id
└── secret-id
To determine where to place the DRF configuration directory (where Vault Agent will render secrets), let’s consider the following:
What Vault Agent Will Render: Vault Agent will render secrets, such as Django settings (e.g., SECRET_KEY, database credentials), into a file. This file needs to be accessible by your Django application.
Best Location for Django Settings: Django settings are typically placed in the settings.py file located in the project/ directory (based on your structure). Therefore, it makes sense to place the rendered configuration file close to where settings.py is located.
Recommendation
Place the DRF config directory that Vault Agent will use inside the project/ directory where your settings.py is located. This ensures that your Django project can easily import the rendered settings from Vault Agent.
Add a new directory called config/ under the project/ directory. This will be where Vault Agent renders secrets.
In your docker-compose.yml, ensure that this directory is mounted so that Vault Agent can write to it.
sample_project/
├── django_rest_framework/
│ ├── app/
│ ├── media/
│ ├── project/
│ │ ├── __init__.py
│ │ ├── asgi.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ ├── wsgi.py
│ │ ├── config/ # <--- New directory for Vault Agent-rendered secrets
│ ├── static/
│ ├── user/
│ ├── venv/
│ ├── Dockerfile
│ ├── manage.py
│ ├── requirements.txt
├── nginx/
│ ├── conf.d/
│ ├── Dockerfile
│ ├── nginx.conf
│ ├── .env.local
│ └── docker-compose.local.yml
In your docker-compose.yml file for DRF, make sure you mount the project/config/ directory so that Vault Agent can write to it:
services:
web:
image: django:latest
container_name: drf
volumes:
- ./project/config:/app/project/config # Mount the config directory
command: sh -c "python manage.py runserver 0.0.0.0:8000"
ports:
- "8000:8000"
networks:
- vault-network
In your settings.py file, import the secrets rendered by Vault Agent:
try:
from .config.settings_vault import *
except ImportError:
pass
This will ensure that your Django application picks up the secrets that Vault Agent renders in the config/ directory.
To allow communication between Vault, Vault Agent, and DRF, ensure they all use the same Docker network:
docker network create vault-network
3.Check Docker Networks:
Run the following command to check if both containers are in the same network:
docker network inspect vault-network
Ensure that all services such as vault, vault-agent, drf are listed as connected to this network.
path-to-vault/docker-compose -f docker-compose-vault.yml up -d
path-to-vault-agent/docker-compose -f docker-compose-vault-agent.yml up -d
path-to-drf/docker-compose -f docker-compose-drf.yml up -d
docker ps -a
# settings.tpl
# Django Secret Key
SECRET_KEY = "{{ with secret "secret/my-django-secret" }}{{ .Data.data.secret_key }}{{ end }}"
# Database Credentials
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': '{{ with secret "secret/db-creds" }}{{ .Data.data.db_name }}{{ end }}',
'USER': '{{ with secret "secret/db-creds" }}{{ .Data.data.username }}{{ end }}',
'PASSWORD': '{{ with secret "secret/db-creds" }}{{ .Data.data.password }}{{ end }}',
'HOST': '{{ with secret "secret/db-creds" }}{{ .Data.data.host }}{{ end }}',
'PORT': '{{ with secret "secret/db-creds" }}{{ .Data.data.port }}{{ end }}',
}
}
# Variable![](https://velog.velcdn.com/images/sbkyo88/post/4ee7197c-c627-4bc7-b90c-0a21fc645034/image.png)
Structure:
{{ with secret "path/to/secret" }}
<use the secret data here>
{{ end }}
# Understanding .Data and .Data.data
{
"Data": {
"data": {
"var": "secret-value"
},
"metadata": {
"created_time": "2024-08-22T03:52:00Z",
"version": 1
}
}
}