This is a simple web blog to demo use cases with Hashicorp Vault. The app communicates directly with Vault using the API. This is for local demos only. web-blog-demo on Gitlab is used in the cloud on K8s.
It uses python, flask, bootstrap, mongodb, consul, and vault.
sudo mongod --port 27017 --dbpath /Users/sam/Deployments/HashiCorp/mongo_data
From the mongo client inside the admin database run the following:
use admin
db.createUser(
{
user: "sam",
pwd: "test123", // or cleartext password
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
}
)
Exit the mongo client
sudo mongod --auth --port 27017 --dbpath /Users/sam/Deployments/HashiCorp/mongo_data
mongo --port 27017 --authenticationDatabase "admin" -u "sam" -p "test123"
Start the vault server using a config file.
vault server -config=vaultConfig.hcl
Content of the config file are below:
storage "file" {
path = "/Users/sam/Deployments/HashiCorp/vault_data"
}
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = 1
}
disable_mlock = true
export VAULT_ADDR='http://127.0.0.1:8200'
vault operator init -key-shares=1 -key-threshold=1
You get the following output. In production you typically would use Vault's PGP and Keybase.io support to encrypt each of these keys so only one person has access to one key only.
Unseal Key 1: 258G83eRO8SMqFWBRs9Bn+8yAdK7HVgtMiAkgOdh5iA=
Initial Root Token: s.ewt0JUqVxTVnU7fW04ZiKiYh
Run the following command to unseal
vault operator unseal
vault login s.ewt0JUqVxTVnU7fW04ZiKiYh
vault secrets enable database
vault write database/config/my-mongodb-database \
plugin_name=mongodb-database-plugin \
allowed_roles="my-role" \
connection_url="mongodb://{{username}}:{{password}}@127.0.0.1:27017/admin" \
username="sam" \
password="test123"
Configure a role that maps a name in Vault to a MongoDB command that executes and creates the database credential
vault write database/roles/my-role \
db_name=my-mongodb-database \
creation_statements='{ "db": "admin", "roles": [{ "role": "readWriteAnyDatabase" }, {"role": "read", "db": "foo"}] }' \
default_ttl="10s" \
max_ttl="24h"
vault read database/creds/my-role
Change the X-Vault-Token
value below to work for yours.
$ curl \
--header "X-Vault-Token: s.ewt0JUqVxTVnU7fW04ZiKiYh" \
http://127.0.0.1:8200/v1/database/creds/my-role
{
"data": {
"username": "root-1430158508-126",
"password": "132ae3ef-5a64-7499-351e-bfe59f3a2a21"
}
}
Change the X-Vault-Token
value below to yours.
response = requests.get(
'http://127.0.0.1:8200/v1/database/creds/my-role',
params={'q': 'requests+language:python'},
headers={'X-Vault-Token': 's.ewt0JUqVxTVnU7fW04ZiKiYh'},
)
json_response = response.json()
Database.USER = json_response['data']['username']
Database.PASSWORD = json_response['data']['password']
Database.URI = f'mongodb://{Database.USER}:{Database.PASSWORD}@{Database.SERVER}:{Database.PORT}'
- Make sure you're logged out of the app. Have the VS code screen with the teriminal output showing. Also have the VS code screen side by side to the Chrome screen. My email is sam and password is test123 to access the app.
- Comment and uncomment the lines in
databse.py
and.env
to show the static hard-coded creds scenario. - Log into the app
- Show the stdout in VS code's terminal showing the hard-coded username and password are the same as those in the
.env
file. - Browse the Blogs page to show that the creds don't expire.
- Log out of the app
- Comment and uncomment the lines in
databse.py
and.env
to show the dynamic secrets scenario using Vault - Log into the app
- Show the stdout in VS code's terminal showing the auto-generated username and password by vault.
- Browse the Blogs page to show that the creds expire and we get a message saying
mongoDB auth failed due to creds expiring. Rotating creds now
. Then we get new creds. - Pivot over to a terminal with the mongo client running. Make sure you're logged in as an admin. Run the commands:
use admin
andshow users
. Show how the creds appear and disappear based on the timeout. You will need to browse the web blog to generate new creds.