Managing Configuration and Secrets
10 minIn Pulumi, each stack within your project has a settings file, and this file contains a collection of values intended to capture the configuration details needed to work with a particular environment. These can be plain-text values like server names, environment types (ex: dev, test, prod), region names and so on. They can also be sensitive values such as database passwords or service tokens.
In this tutorial, we'll demonstrate how to create and utilize configuration and secret values in Pulumi.
- How to create a plain-text configuration value
- How to create an encrypted secret configuration value
- How to view configuration details in the CLI
- How to access configuration values from within Pulumi program code
- The Pulumi CLI
- A Pulumi Cloud account and an access token
- One of Pulumi’s supported language runtimes installed
Create a new project#
To start, login to the Pulumi CLI. Next, create a new project by running the pulumi new <language> command, making sure to replace <language> with the supported language of your choice:
# example using pythonpulumi new pythonThis command will walk you through creating a new Pulumi project.
Enter a value or leave blank to accept the (default), and press <ENTER>.Press ^C at any time to quit.
project name (pulumi-dev):project description (A minimal Python Pulumi program):Created project 'pulumi-dev'
Please enter your desired stack name.To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`).stack name (dev): pulumi/devCreated stack 'dev'
Installing dependencies...
Creating virtual environment...Finished creating virtual environmentUpdating pip, setuptools, and wheel in virtual environment.........Finished installing dependencies
Your new project is ready to go!
To perform an initial deployment, run `pulumi up`This will create simple Pulumi program without any resources or configuration details.
Create configuration values#
In a Pulumi project, you can locally store and retrieve configuration values using the pulumi config set <key> [value] command. To demonstrate, run the following command to create a configuration value with a key of myEnvironment and a value of development:
pulumi config set myEnvironment developmentThis value will be stored in your project’s stack settings file Pulumi.<your-stack-name>.yaml as shown below:
# Contents of Pulumi.<your-stack-name>.yaml fileconfig: pulumi-dev:myEnvironment: developmentYou can also list the configuration values for your stack in the command line. To do so, run the pulumi config command:
pulumi config
KEY VALUEmyEnvironment developmentpulumi:tags {"pulumi:template":"python"}To retrieve a specific configuration value, run the pulumi config get <key> command as shown below:
pulumi config get myEnvironmentdevelopmentCreate secret values#
Pulumi supports encrypting specific values as “secrets” for extra protection. Pulumi Cloud transmits and stores state files over a secure connection, but once received the files are viewable in plain-text. By encrypting secrets, Pulumi ensures that these values never appear as plain-text in your state file. By default, the encryption method uses automatic, per-stack encryption keys provided by Pulumi Cloud, but you can also use a provider of your own choosing instead.
To encrypt a configuration value before runtime, you will need to run the pulumi config set <key> [value] --secret command. To demonstrate how this works, you’ll create a configuration value named myPassword. Run the CLI command pulumi config set myPassword <value-of-password>, making sure to pass the --secret flag, and also making sure to replace <value-of-password> with an actual value as shown below:
pulumi config set myPassword demo-password-123 --secretNow run the pulumi config command again, and you will see that, unlike the value for myEnvironment, the value for myPassword is hidden:
pulumi config get myEnvironment
KEY VALUEmyEnvironment developmentmyPassword [secret]pulumi:tags {"pulumi:template":"python"}If you open your project’s stack settings file (e.g. Pulumi.<your-stack-name>.yaml), you will notice that the password value is also encrypted there:
config: generic-python:myEnvironment: development generic-python:myPassword: secure: AAABADd5YzRaVuzxM08i5z2CJ3LGkQau5e5Lhk+1Gtj37qv6zKkFr8KxmN6X+w/XMg==Reference values in code#
Within your Pulumi program code, configuration values can be retrieved for a given stack using the following:
Config.getorConfig.requirefor raw configuration valuesConfig.getSecretorConfig.requireSecretfor secret values
To demonstrate, update your Pulumi program code with the following:
import * as pulumi from "@pulumi/pulumi"
// Create a new Pulumi Configconst config = new pulumi.Config()
// Retrieve the values of "region" and "apiKey"const region = config.get("region")const apiKey = config.getSecret("apiKey")
// Export values as stack outputexport const Region = regionexport const ApiKey = apiKeyimport pulumi
# Import the configuration valuesconfig = pulumi.Config()
# Retrieve the values of "region" and "apiKey"region = config.get("region")api_key = config.get_secret("apiKey")
# Export the values as an outputpulumi.export('Region', region)pulumi.export("ApiKey", api_key)package main
import ( "github.com/pulumi/pulumi/sdk/v3/go/pulumi" "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config")
func main() { pulumi.Run(func(ctx *pulumi.Context) error { // Create a Pulumi Config config := config.New(ctx, "")
// Retrieve the value of "region" and "apiKey" region := config.Get("region") apiKey := config.GetSecret("apiKey")
// Export values as outputs ctx.Export("Region", pulumi.String(region)) ctx.Export("ApiKey", pulumi.StringOutput(apiKey)) return nil })}using Pulumi;using System.Threading.Tasks;using System.Collections.Generic;
class Program{ static async Task<int> Main(string[] args) { return await Deployment.RunAsync(() => { // Import the configuration values var config = new Config();
// Retrieve the value of "region" and "apiKey" var region = config.Get("region"); var apiKey = config.GetSecret("apiKey");
// Return a dictionary of outputs return new Dictionary<string, object?> { ["Region"] = region, ["ApiKey"] = apiKey }; }); }}package myproject;
import com.pulumi.Pulumi;import com.pulumi.core.Output;
public class App { public static void main(String[] args) { Pulumi.run(ctx -> { // Create a Pulumi Config var config = ctx.config();
// Retrieve the values of "region" and "apiKey" var region = config.get("region"); var apiKey = config.getSecret("apiKey");
// Export the values as a stack outputs ctx.export("Region", Output.of(region)); ctx.export("ApiKey", Output.of(apiKey)); }); }}Save your file and then run the pulumi up command.
pulumi up -y
Type Name Status + pulumi:pulumi:Stack python-dev created (0.54s)
Outputs: myEnvironment: "development" Password : [secret]
Resources: + 1 created
Duration: 2sYou can see that the configuration values were successfully imported into the program and exported as outputs, and you can see that the value of Password, which comes from the secret configuration value myPassword, is still not visible.
Clean Up#
Before moving on, tear down the resources that are part of your stack to avoid incurring any charges.
- Run
pulumi destroyto tear down all resources. You’ll be prompted to make sure you really want to delete these resources. A destroy operation may take some time, since Pulumi waits for the resources to finish shutting down before it considers the destroy operation to be complete. - To delete the stack itself, run
pulumi stack rm. Note that this command deletes all deployment history from the Pulumi Service.
Next Steps#
In this tutorial, you created raw and secret configuration values in your project’s stack. You also accessed these values via your Pulumi program code.
To learn more about managing and utilizing configuration and secrets in Pulumi, take a look at the following resources:
- Learn more about more about how to centralize your configuration and secrets in the Pulumi ESC documentation.
- Learn more about stack outputs and references in the Stack Outputs and References tutorial.