Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Secure DevOps with Pulumi and Azure AD
The 425 Show profile imageChristos Matskas
Christos Matskas forThe 425 Show

Posted on

     

Secure DevOps with Pulumi and Azure AD

Pulumi, Terraform, Bicep etc are tools that enable developers and IT Pros to build and deploy infrastructure to the cloud using code. Infrastructure as Code is a great way to implement elaborate solutions using tools and languages you already know (in most cases).

We recently invited Sean Whitesell on the #425Show to show us how to get started with Pulumi and Azure. If you wish to catch the video, it's now available on YouTube

This blog expands on that streams and focuses on how to securely deploy infrastructure to Azure using Pulumi and Azure Key Vault.

When it comes to protecting sensitive information and secrets in Pulumi, there are two main options:

  1. Using a Service Principal to query Azure Key Vault at deployment time
  2. Using an encryption provider to store secrets

1.1 Create a service principal to use for the deployment:

First of all, we need to create a Service Principal in Azure AD. Open the Azure CLI and type the following:

az loginaz ad sp create-for-rbac -n pulumi-deployment-sp --scopes /subscriptions/<YourSubscriptionId>
Enter fullscreen modeExit fullscreen mode

The result should look like this:

{  "appId": "1fdd1348-ccb0-4ec5-9799-edd14dd72e13",  "displayName": "pulumi-deployment-sp",  "name": "http://pulumi-deployment-sp",  "password": "<it's a secret>",  "tenant": "e801a3ad-3690-4aa0-a142-1d77cb360b07"}
Enter fullscreen modeExit fullscreen mode

Make sure to keep this information safe as we'll need to use it later in the set up

1.2 Configure the Key Vault Access policy

The Service Principal can now be used to deploy resource but doesn't have access to our Key Vault secrets. We will use Key Vault to store the sensitive information such as passwords, keys and connection strings to decouple the Pulumi code and the config settings. That way, the code becomes a lot more portable and IT Admins can audit the usage of secrets to ensure there's no foul play.

In the Azure portal, open your Key Vault and navigate to theAccess Policies blade. Add a new Policy as per the image below:

Alt Text

The Service Principal should now be able to List and Get secrets from our Key Vault

1.3 Configure Pulumi to authenticate to Azure using a Service Principal

Next, we need to set up Pulumi to use the Service Principal in order to authenticate to the Azure Resource Manager to deploy our resources. Since Pulumi uses Terraform behind the scenes, the environment variables that we need to configure are exactly the same as per thisTerraForm document

In our PowerShell session (I don't want these stored permanently on my machine) we set up the following environment variables using the output information that was provided when we created our Service Principal:

$env:ARM_CLIENT_ID="<Service Principal App ID>"$env:ARM_CLIENT_SECRET="<Service Principal secret/password>"$env:ARM_SUBSCRIPTION_ID="<Subscription ID>"$env:ARM_TENANT_ID="<Azure AD Tenant ID>"
Enter fullscreen modeExit fullscreen mode

1.4 The actual code

To access our Azure Key Vault secrets during the deployment process, we can use the following code:

import * as pulumi from "@pulumi/pulumi";import * as azure from "@pulumi/azure";interface Data{    azurerm_key_vault: {        id:string    }};let config = new pulumi.Config();let data = config.requireObject<Data>("data");const sql_username_secret = azure.keyvault.getSecret({    name: "pulumi-sql-username",    keyVaultId: data.azurerm_key_vault.id});const sql_password_secret = azure.keyvault.getSecret({    name: "pulumi-sql-password",    keyVaultId: data.azurerm_key_vault.id});export const sql_username = sql_username_secret.then(secret => secret.value);export const sql_password = sql_password_secret.then(secret => secret.value);
Enter fullscreen modeExit fullscreen mode

In case you're wondering where we got thedata object, this is something we initialize using the Pulumi CLI. Alternatively, we can edit thePulumi.<environment>.yaml directly. Currently, thedata object holds the Azure Key Vault resource id which we can set via the Pulumi CLI with this command:

 pulumi config set --path 'data.azurerm_key_vault.id' /subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.KeyVault/vaults/<myKeyVaultName>
Enter fullscreen modeExit fullscreen mode

Running this command will update thePulumi.dev.yaml file like this:

config:  azure:environment: public  azure:location: WestUS  pulumiwithaad:data:    azurerm_key_vault:      id: /subscriptions/d801110....
Enter fullscreen modeExit fullscreen mode

If we run thePulumi up command with the code provided above, we should receive the following output

Alt Text

2. Using the KeyVault Secrets provider for Pulumi

The other option, to keep our config settings secret, is to use an Secrets Encryption Provider to encrypt our sensitive data. By default, this is provided out of the box by the Pulumi Service but there is an option to explicitly set your own Encryption Provider. The available options are:

  • default
  • passphrase
  • awskms
  • azurekeyvault
  • gcpkms
  • hashivault

Of course, I'll chose to go with the Azure Key Vault provider because I can then use Managed Identities or Service Principals to run my deployment tasks.

There are a few steps needed to achieve this. For local development, we need to:

2.1 Enable Azure Key Vault auth via the CLI

First we need to configure the following environment variable and set it totrue. Open the PowerShell session you will be running your tasks and execute the following command:

$env:AZURE_KEYVAULT_AUTH_VIA_CLI = "true"
Enter fullscreen modeExit fullscreen mode

Next, we need to ensure that the Azure CLI is using correct Service Principal. To do this, we can run the following command. In the same PowerShell session log in to the Azure CLI with the following command:

az login --service-principal --username <Service Principal Client Id> --tenant <Azure AD Tenant Id> --password <Service Principal Client Secret>
Enter fullscreen modeExit fullscreen mode

Alternatively, we could use a certificate to authenticate our Service Principal, which is more secure than passing credentials around.

2.2 Configure the Secrets Provider

Next we need to update Pulumi to use Key Vault as the secrets provider. This can be accomplished by running the following command in the Pulumi CLI:

pulumi stack change-secrets-provider "azurekeyvault://<yourKeyVaultName>.vault.azure.net/keys/<TheKeyToUseForEncryptionDecryption>"
Enter fullscreen modeExit fullscreen mode

Alt Text

2.3. Update the Access Policy in Key Vault

If we try to run our Pulumi script now, it's guaranteed that we'll receive an 'Unauthorized' error message. That's because our Service Principal needs to be able to use the designated Key Vault key to encrypt and decrypt data.

Alt Text

To fix this error, we need to update the Azure Key Vault Access Policy as per the image below:

Alt Text

  • Add a Key Vault backed secret to our config file

2.4 Add a secret

With Pulumi primed to use Key Vault as its secret provider, we can now add a new secret to our code. Open the Pulumi CLI and run the following command:

pulumi config set --secret someOtherSecret Hunter2!

This will add an entry:pulumiwithaad:someOtherSecret in ourPulumi.dev.yaml file as well as references to ourSecrets Provider andEncryptedKey

secretsprovider: azurekeyvault://<myKeyVault>.vault.azure.net/keys/pulumiKeyencryptedkey: aGxiU1Jq...<omitted for brevity>...VHVLNUE=config:  azure:environment: public  azure:location: WestUS  pulumiwithaad:data:    azurerm_key_vault:      id: /subscriptions/d8011108-23b2-40d8-8bc4-1f3f77abe795/resourceGroups/dotnetconf/providers/Microsoft.KeyVault/vaults/cmdeploymentdemo  pulumiwithaad:someOtherSecret:    secure: v1:6oxydcsaDaemg43V:fV6Oy11srnDjxdlRVwsPb5xMo6nS/y6Q
Enter fullscreen modeExit fullscreen mode

If we runpulumi preview then we can see how our secret is set as expected:

Alt Text

In our Pulumi code, we can reference the secret by calling:

const kvSecret = config.requireSecret("someOtherSecret");
Enter fullscreen modeExit fullscreen mode

We are now ready to deploy our SQL server to Azure! Let's do this:
Pulumi up

Alt Text

It works!

Source Code

You can find this sample code on thisGitHub repo

Summary

Sean was great on the show and we learned quite a bit about Pulumi and how to use it with Azure AD. This blog post took things a bit further to explain how to further lock down and secure your DevOps pipeline by removing secrets and relying on Service Principals and Azure Managed Identity to authenticate to Azure and run your deployment. Let us know in the comments if you have any questions!

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
muzammilaalpha profile image
muzammilaalpha
Web developer
  • Location
    india
  • Joined

Good post!

CollapseExpand
 
christosmatskas profile image
Christos Matskas
Program Manager in the Microsoft Identity Dev Advocacy team. Programmer, speaker and all around geek
  • Location
    Redmond, WA
  • Work
    Program Manager at Microsoft
  • Joined

Thanks@muzammilaalpha! please share the love :)

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

More fromThe 425 Show

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp