What You’ll Learn

What You’ll Need

vault

What Is Vault?

Vault is a tool for securely accessing secrets. A secret is anything to which you want to tightly control access, such as API keys, passwords, or certificates. Vault provides a unified interface to any secret while providing tight access control and recording a detailed audit log.

Once Vault is installed, you need to start it. There are two options: one that runs Vault storage in memory and another that starts the server with a pre-existing config file.

vault

Option #1: Start it up in dev mode by supplying the following cmd in Terminal:

vault server -dev

⚠️ This option runs Vault storage in memory; once the server is stopped, your config and keys are lost.

⚠️ If this is the option you choose, make sure you capture the UNSEAL key and ROOT TOKEN that are provided.

Option #2: Start it up with a pre-existing config file by supplying the following cmd in Terminal:

vault server -config config.hcl 

An example Vault config file can be found here.

Here’s how config.hcl looks:

	{
	"listener": [{
	"tcp": {
	"address" : "0.0.0.0:8200",
	"tls_disable" : 1
	}
	}],
	"api_addr": "http://0.0.0.0:8200",
	"storage": {
	    "file": {
	    "path" : "vault/data"
	    }
	 },
	"max_lease_ttl": "10h",
	"default_lease_ttl": "10h",
	"ui":true
	}

⚠️ Note that the Vault config file must be located in a folder to which you have read and write access permissions.

Locate the provided Postman Collection folder in the cloned repository under Postman Collection.

import the Vault.postman_collection and Vault-Env.postman_environment into Postman and the env variable and start initializing Vault using its APIs.

Here’s where you can find the Postman Collection.

Assuming you choose to run Vault using Option #2, you will need to initialize Vault only once on the initial run.

In Postman in the Vault Collection, execute the following requests:

  1. init vault: This will provide you with the UNSEAL Key and Root Token. Save these values.
  2. unseal vault: This will do what it says—unseal the vault before you can start accessing your secrets.
  3. enable KV secret engine: The KV secrets engine is used to store arbitrary secrets within the configured physical storage. In this case, we are creating a new mount named kv-v1. Think of this as your path to secrets.

At this point, you have everything you need to start storing API keys, authentication credentials, and tokens within your Vault instance.

You don’t want to give your application Root access. Instead, you want to register an AppRole to authenticate your app against your instance of Vault.

In the provided Postman Collection:

  1. Add AppRole will set up a new AppRole authentication method within Vault.
  2. Add ACL Policy: Vault is driven by policies to govern role-based access. In this case, you are creating a policy to give access to the kv-v1 secret engine mount you created previously.

This is what the ACL policy my-policy looks like:

# Dev servers have version 1 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "kv-v1/devnet/dnac/*" {
  capabilities = ["create", "update","read"]
}

3.Bind policy to role does what is says in that it will bind my-policy to the AppRole you created and call it my-role.

To generate a new CLIENT TOKEN, you first need to fetch your Role ID and generate a new Secret ID based on the role.

In the provided Postman Collection:

  1. Get Role ID fetches the my-role ID created above.
  2. Create Secret ID uses the my-role ID to generate a new Secret ID.
  3. Fetch Client Token generates a client_token for writing, reading, and updating secrets in the mount to which the ACL granted permission—in this case, kv-v1/devnet/dnac/*. Use this in your application to authenticate and capture it!

Now that you have all the pieces of the puzzle in place (steps 1 to 4 only need to be configured once), you can now start storing secrets to be utilized by your application.

  1. Post KV Secret uses the client_token to create a new secret. In this case, we are using Cisco DNA Center Sandbox and writing the secret to the mount path kv-v1/devnet/dnac/sb1, with POST http://{{vault}}/v1/kv-v1/devnet/dnac/sb1 in Postman.

⚠️ You will need to remember your mount paths from the POST endpoint above in order to access your secrets.

The provided sample code will:

  1. Access Vault using the HVAC library, and fetch the secret.
  2. Authenticate against the Cisco DNA Center Always-On Sandbox.
  3. Pull a list of managed devices.

Note: Python 3.11 is required for the script to function in the sandbox. This is due to the dnacentersdk module uses the imp module which was deprecated in 3.11 (but still works) and no longer exists in Python 3.12.

Requirements
python3 -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt

⚠️ Put the UNSEAL KEY and CLIENT TOKEN into environment variables.

Terminal
export CLIENT_TOKEN=<PLACE_YOUR_CLIENT_TOKEN_HERE>
export UNSEAL_KEY=<PLACE_YOUR_UNSEAL_KEY_HERE>
Python
import hvac
import os
from dnacentersdk import DNACenterAPI

# Instantiate new Vault client
client = hvac.Client()

# Capture the unseal key when initializing your Vault Server
vault_unseal_key = 'REPLACE_WITH_KEYS_VALUE_FROM_INIT_POST'

# Capture the client token provided by your admin (in this case, see the provided Postman Collection POST init vault request)
vault_client_token = 'REPLACE_WITH_ROOT_TOKEN_FROM_INIT_POST'

# Define your mount point and path where your secrets are saved
vault_mount_point = 'kv-v1'
vault_path = '/devnet/dnac/sb1'

Congratulations! You have now integrated your application with a centralized Vault that holds some of, if not all, your API credentials and tokens in a secure fashion. Imagine automating a multidomain environment where you have different API calls to different endpoints; juggling an auth token can be tedious and time consuming. Vault makes your life simple—cool!

Learn More