Vault integration and retrieving dynamic secrets
Challenge
Nomad provides a flexible workload orchestrator to deploy and manage different types of workloads. These workloads will likely need to authenticate with other services, such as an application API or database management system. Providing workloads with secure access to credentials for these services is critical to ensure secure operations.
Solution
Nomad can deploy these workloads while quickly and safely retrieving dynamic credentials by integrating with Vault. This integration allows your applications to retrieve dynamic credentials from Vault for various tasks and invalidate the credentials when finished.
In this tutorial, you deploy a web application that needs to authenticate against a PostgreSQL database to display data from a table to the user.
Prerequisites
To perform the tasks described in this guide, you must have the following installed:
Lab setup
Warning
Do not run services in development mode in production. Development mode starts a limited configuration and is used only for testing.
Deploy Nomad
Open a new terminal and start the Nomad development agent
If prompted, enter the password for your operating system.
Open a new terminal and export an environment variable for the Nomad server address.
Verify connectivity to the Nomad cluster.
The Nomad server is ready.
Deploy Vault
Open a terminal and start a Vault development server with
root
as the root token.The Vault development server defaults to running at
127.0.0.1:8200
. The server is now initialized and unsealed.Return to the terminal where you set the
NOMAD_ADDR
and export an environment variable for the Vault server address.Export an environment variable for the Vault token.
Verify connectivity to the Vault cluster.
Note
Note: For these tasks, you can use Vault's root token. However, we recommend that you use root tokens only for the initial setup or in emergencies.
The Vault server is ready.
You should now have 3 terminals open. One each for:
- Nomad running in dev mode
- Vault running in dev mode
- Working terminal to configure the environment with the
VAULT_ADDR
andNOMAD_ADDR
environment variables set
Configure Vault
Write a policy for Nomad server tokens
To use the Vault integration, you must provide a Vault token to your Nomad servers using a token with an appropriate policy for the Nomad servers.
Create a policy file for the Nomad server in a file named
nomad-server-policy.hcl
.Write a policy called
nomad-server
using thenomad-server-policy.hcl
file.
Create a role
You will now create a role in Vault for Nomad. The role allows you to manage access to Vault by attaching the policy that defines what actions are permitted.
Create a role file for the Nomad server in a file named
nomad-cluster-role.json
.The
access-tables
policy is listed in theallowed_policies
key. A job running in this Nomad cluster will only be allowed to use theaccess-tables
policy.Note
If you would like to allow all policies to be used by any job in the Nomad cluster except for the ones you specifically prohibit, then use the
disallowed_policies
key instead and simply list the policies that should not be granted. If you take this approach, be sure to includenomad-server
in the disallowed policies group. An example of this is shown below:Create the role named
nomad-cluster
.Create a policy file named
access-tables-policy.hcl
.Create the policy named
access-tables
.Generate the token for the Nomad server.
The
-orphan
flag is included when generating the Nomad server token above to prevent revocation of the token when its parent expires. Vault typically creates tokens with a parent-child relationship. When an ancestor token is revoked, all of its descendant tokens and their associated leases are revoked as well.The
nomad-server-policy.hcl
policy permits Nomad to renew the token when it expires.
Configure Nomad
With Vault configured, you will now configure Nomad for Vault.
Return to the terminal you started Nomad in dev mode and type
ctrl-c
to stop Nomad.Export an environment variable with the token generated in the previous step.
Export an environment variable with the Vault server address.
Create a Nomad configuration file that includes the Vault stanza to enable the integration.
Restart Nomad in dev mode and specify the config file.
Return to the terminal where you set the
NOMAD_ADDR
environment variable and confirm connectivity to the Nomad cluster.For production environments, Vault integration needs to be enabled on the client nodes as well. Configure the
vault
stanza in your Nomad clients' configuration file (located at/etc/nomad.d/nomad.hcl
). The Nomad clients do not need to be provided with a Vault token.
Deploy PostgreSQL
You will now configure a connection between Vault and a database server.
Create a Nomad job called
db.nomad.hcl
.Run the Nomad job to start the PostgreSQL database server.
Verify the job is running.
Configure Vault database secret engine
The Vault database secrets engine provides users and services the ability to generate dynamic, on-demand credentials instead of creating static, long-lived credentials.
Enable the database secrets engine
Retrieve the IP address of the
postgres-nomad-database
service and export an environment variable namedPOSTGRES_IP
.Create a file named
connection.json
with connection information to the PostgreSQL.The connection information allows Vault to connect to the database and create users with specific privileges. In a production setting, it is recommended to give Vault credentials with enough privileges to generate database credentials dynamically and manage their lifecycle.
Create the connection between Vault and PostgreSQL.
Create a file named
accessdb.sql
with a creation statement for PostgreSQL.The preceding SQL is used in the
creation_statements
parameter of the Vaultaccessdb
role to specify the privileges that the dynamic credentials being generated will possess. In this case, the dynamic database user will have broad privileges that include the ability to read from the tables that the application will need to access.Create a Vault role to manage database privileges.
Example output:
Test generating dynamic credentials with Vault.
Recall from the previous section that you specified a policy named
access-tables
in theallowed_policies
section of the Vault role. You will create this policy now and give it the capability to read from thedatabase/creds/accessdb
endpoint (the same endpoint you read from in the previous step to generate credentials for the database). You will then specify this policy in the Nomad job which will allow it to retrieve credentials for itself to access the database.Create a file named
access-tables-policy.hcl
.Create the
access-tables
policy in Vault.
Deploy a Nomad job
You are ready to deploy the web application and give it the necessary policy and configuration to communicate with the PostgreSQL database.
Create a file called
web-app.nomad.hcl
.There are a few key points to note here:
The job specifies the
access-tables
policy in the vault stanza of this job. The Nomad client receives a token with this policy attached. Recall from the previous step that this policy allows the application to read from thedatabase/creds/accessdb
endpoint in Vault and retrieve credentials.The job uses the template stanza's vault integration to populate the JSON configuration file that the application needs. Please note that although the job defines the template inline, you can use the template stanza in conjunction with the artifact stanza to download an input template from a remote source such as an S3 bucket.
The job templates use the
toJSON
function to ensure the password is encoded as a JSON string. Any templated value which may contain special characters (like quotes or newlines) should be passed through thetoJSON
function.Finally, note that the destination of the template is the secrets task directory. This ensures the data is not accessible with a command like
nomad alloc fs
or filesystem APIs.
Run the Nomad job.
Retrieve information about the
nomad-vault-demo
app.Verify the app is making a connection to the PostgreSQL database.
Example output:
Next steps
In this tutorial you deployed a PostgreSQL with Nomad as a job. You then created and secured the login credentials with Vault.