Azure DevOps with Secrets Safe | PS
Azure DevOps is a comprehensive set of development tools and services provided by Microsoft that supports collaboration and streamlines the software development lifecycle. It offers a range of features and capabilities to facilitate communication, planning, coding, testing, and deployment of software projects.
The Azure DevOps extension allows for the retrieval of ASCII secrets from an instance of Secrets Safe.
The Secrets Safe Azure DevOps extension supports retrieval of secrets from BeyondInsight/Password Safe versions 23.1 or greater.
For this extension to retrieve a secret for use in each Azure DevOps pipeline, the Secrets Safe instance must be preconfigured with the secret in question and an account must be authorized to read it.
Manage Secrets with Secrets Safe
This extension allows for both the retrieval and creation of secrets in BeyondTrust Secrets Safe, enabling secure secret management throughout your Azure DevOps pipelines.
New in Version 2.0.0
Important informationVersion 2.0.0 introduced breaking changes. The SecretsSafeSecret task has been removed and replaced with two separate tasks:
- SecretsSafeGetSecret@2 - For retrieving secrets from Secrets Safe
- PasswordSafeGetManagedAccount@2 - For retrieving managed account credentials from Password Safe.
If you are upgrading from version 1.x, you need to update your pipeline YAML files to use the new task names.
Prerequisites
- The Secrets Safe Azure DevOps extension supports retrieval of secrets from BeyondInsight/Password Safe versions 23.1 or greater.
- For this extension to retrieve a secret for use in each Azure DevOps pipeline, the Secrets Safe instance must be preconfigured with the secret in question and an account must be authorized to read it.
Configure Password Safe to allow Azure DevOps to retrieve secrets
The following sections outline how to set up Password Safe to allow Azure DevOps to retrieve ASCII secrets.
This setup provides a quick start guide to help you set up Password Safe.
Set up API key and user account
- Create an API registration in BeyondInsight (does not require a user password).
For more information, see Configure: API registration.
- Create or use an existing Secrets Safe group.
- Create or use an existing BeyondInsight user.
- Add the API registration to the group.
- Add the user to the group.
- Add the Secrets Safe feature to the group.
Managed accounts setup
- Create or use an existing access policy that has View Password Auto Approve set.
- Add the All Managed Accounts Smart Group to the BeyondInsight group.
- Add the Access Policy to the All Managed Accounts Smart Group role, and ensure that both requestor and approver are set.
- Create or use an existing managed system.
- Create or use an existing managed account associated with the managed system.
- Configure the managed account with the API Enabled and Max Concurrent Requests Unlimited options checked.
Configure Azure DevOps
The following sections outline how to set up Azure DevOps to retrieve ASCII secrets.
This setup provides a quick start guide to help you set up Azure DevOps.
Configure Secrets Safe service connection
It's possible to configure either a Basic or using OAuth Authentication.
Configure a service connection using Basic Authentication for the Secrets Safe pipeline task
Basic Authentication Service Connection fields:
| Field name | Description |
|---|---|
| Server URL | The URL for the Secrets Safe instance from which to request a secret. |
| API Username | The username of a BeyondInsight user who has been granted permission to use the API key for the API request to the Secrets Safe instance. |
| API Key | The API key configured in BeyondInsight for your application. For use when authenticating to Secrets Safe. |
| Certificate Key (optional) | Certificate private key (key.pem). For use when authenticating with an API key using a client certificate. See the Extract client secret section below. |
| Certificate (optional) | Content of the certificate (cert.pem) for use when authenticating with an API key using a client certificate. |
| Skip Server Certificate Verification (optional) | Indicates whether to verify the certificate authority on the Secrets Safe instance. For use when authenticating to Secrets Safe. |
Configure a service connection using OAuth for the Secrets Safe pipeline task
OAuth Service Connection Fields:
| Field name | Description |
|---|---|
| Server URL | The URL for the Secrets Safe instance from which to request a secret. |
| Client ID | The Client ID configured in BeyondInsight. |
| Client Secret | The Client Secret configured in BeyondInsight. |
| Certificate Key (optional) | Certificate private key (key.pem). For use when authenticating with an API key using a client certificate. See the Extract client secret section below. |
| Certificate (optional) | Content of the certificate (cert.pem) for use when authenticating with an API key using a client certificate. |
| Skip Server Certificate Verification (optional) | Indicates whether to verify the certificate authority on the Secrets Safe instance. For use when authenticating to Secrets Safe. |
Extract client certificate and key
Download the PFX certificate from Secrets Safe and extract the certificate and the key to be pasted into the service connection.
Example
openss1 pkcs12 -in client_certificate.pfx -nocerts -out ps_key.pem -nodes
openss1 pkcs12 -in client_certificate.pfx -clcerts -nokeys -out ps_cert.pem
Copy all text from the ps_key.pem file to the service connection Certificate Key field. Copy all text from the ps_cert.pem to the service connection Certificate field.
Create Folder Task Configuration
A task for creating folders in BeyondTrust Secrets Safe.
This task creates a new folder in Secrets Safe and optionally stores the folder ID in a pipeline variable for use in subsequent tasks (such as creating secrets in that folder).
Task Fields:
| Field name | Description |
|---|---|
| Secrets Safe service connection | Select the Secrets Safe service connection to use. |
| Folder Name | Name of the folder to create. |
| Folder Description (optional) | Description for the folder.Parent Folder ID - (optional) UUID of the parent folder. Leave empty to create in root folder. |
| User Group ID (optional) | User group ID. Default value is 0. |
| Pipeline Variable Name (optional) | Name of the pipeline variable to store the created folder ID for use in subsequent tasks. |
Example
- task: SecretsSafePostFolder@2
displayName: 'Create Build Secrets Folder'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
folderName: 'Build-$(Build.BuildId)'
folderDescription: 'Secrets for build $(Build.BuildId)'
parentFolderId: '00000000-0000-0000-0000-000000000000'
pipelineVariableName: 'FOLDER_ID'Create Credential Secret Task Configuration
A task for creating credential secrets (username/password) in BeyondTrust Secrets Safe.
This task creates a credential secret in a specified folder. The secret can have owners, notes, and associated URLs.
Task Fields:
| Field name | Description |
|---|---|
| Secrets Safe service connection | Select the Secrets Safe service connection to use. |
| API Version | API version to use: 3.0, 3.1, or 3.2. Default is 3.0. Version 3.0 uses different owner format. |
| Folder ID | UUID of the target folder where the secret will be created. |
| Title | Title of the credential secret (1-256 characters). |
| Username | Username for the credential |
| Password | Password for the credential (can be a pipeline variable). |
| Owners | JSON array of owners. Format depends on API version:
|
| Description - (optional) | Additional information about the secret (max value: 256 characters). |
| Notes - (optional) | Notes about the secret (max value: 4000 characters). |
| URLs - (optional) | JSON array of URLs. Example: [{"Url": "https://example.com"}] |
| Pipeline Variable Name - (optional) | Variable name to store the created secret ID. |
Example
- task: SecretsSafePostCredentialSecret@2
displayName: 'Store Deploy Credentials'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
apiVersion: '3.0'
folderId: '$(FOLDER_ID)'
title: 'Deploy User'
username: 'deploy-user'
password: '$(DeployPassword)'
owners: |
[
{
"UserId": 2,
"Name": "John Doe",
"Email": "[email protected]",
"OwnerType": "User"
}
]
Create Text Secret Task Configuration
A task for creating text secrets in BeyondTrust Secrets Safe.
This task creates a text secret (such as API tokens, configuration values) in a specified folder.
Task Fields:
| Field name | Description |
|---|---|
| Secrets Safe service connection | Select the Secrets Safe service connection to use. |
| API Version | API version to use: 3.0, 3.1, or 3.2. Default is 3.0. Version 3.0 uses different owner format. |
| Folder ID | UUID of the target folder where the secret will be created. |
| Title | Title of the credential secret (1-256 characters). |
| Owners | JSON array of owners. Format depends on API version:
|
| Description - (optional) | Additional information about the secret (max value: 256 characters). |
| Notes - (optional) | Notes about the secret (max value: 4000 characters). |
| URLs - (optional) | JSON array of URLs. Example: [{"Url": "https://example.com"}] |
| Pipeline Variable Name - (optional) | Variable name to store the created secret ID. |
Example
- task: SecretsSafePostTextSecret@2
displayName: 'Store API Token'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
apiVersion: '3.0'
folderId: '$(FOLDER_ID)'
title: 'API Token'
text: '$(ApiToken)'
owners: |
[
{
"UserId": 2,
"Name": "John Doe",
"Email": "[email protected]",
"OwnerType": "User"
}
]
Create File Secret Task Configuration
A task for creating file secrets in BeyondTrust Secrets Safe.
This task uploads a file from your build agent and stores it as a secret in Secrets Safe.
Task Fields:
| Field name | Description |
|---|---|
| Secrets Safe service connection | Select the Secrets Safe service connection to use. |
| API Version | API version to use: 3.0, 3.1, or 3.2. Default is 3.0. Version 3.0 uses different owner format. |
| Folder ID | UUID of the target folder where the secret will be created. |
| Title | Title of the credential secret (1-256 characters). |
| Owners | JSON array of owners. Format depends on API version:
|
| File Path | Path to the file on the build agent to upload as a secret. |
| Description - (optional) | Additional information about the secret (max value: 256 characters). |
| Notes - (optional) | Notes about the secret (max value: 4000 characters). |
| Pipeline Variable Name - (optional) | Variable name to store the created secret ID. |
Example
- task: SecretsSafePostFileSecret@2
displayName: 'Store SSL Certificate'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
apiVersion: '3.1'
folderId: '$(FOLDER_ID)'
title: 'Production SSL Cert'
filePath: '$(Build.SourcesDirectory)/certs/prod-cert.pem'
owners: |
[
{
"UserId": 2,
"Name": "John Doe",
"Email": "[email protected]"
}
]
description: 'SSL certificate for production environment'Retrieve Secrets Safe secret task
A task must be configured to retrieve secrets from Secrets Safe.
Pick the service connection, and enter the path and title of the requested secret. Specify the name of the pipeline variable to populate. The pipeline variable is created and set at runtime by the task, it will contain your retrieved Secrets Safe secret base64 encoded. Reuse of the variable name in multiple tasks overwrites the existing secret.
Important informationSecret retrieval types are base64 encoded only. Reuse of the variable name in multiple tasks overwrites the existing secret. We support encoding of text data only.
Secrets Safe secrets are base64 encoded and saved to the pipeline variable. When using the variable in the pipeline the variable must be decoded.
ExampleDecode Variable
`$(variableFromPipeLine) | base64 –-decode
- We support encoding of text data only.
WarningTake precautions to not accidentally log the secret in the pipeline log after you base64 decode the secret. It is important that security-minded engineers review pipeline composition before changes are run with access to secrets.
Task fields:
| Field name | Description |
|---|---|
| Secrets Safe service connection | Select the Secrets Safe service connection to use. |
| API Version | API version to use: 3.0 or 3.1. Default is 3.0. |
| Secret Path | Path to the Secrets Safe secret. For example folder1/folder2. |
| Secret Title | Title of the Secrets Safe secret found at the path specified above. |
| File Path | Path to the file on the build agent to upload as a secret. |
| Separator | Path separator character. Default is '/'. |
| Decrypt | Whether to decrypt the secret. Default is true. |
| Pipeline Variable Name | A pipeline variable created and set at runtime that contains your retrieved secret. Reuse of the variable name in multiple tasks overwrites the existing secret. |
Example
- task: SecretsSafeGetSecret@2
displayName: 'Get Database Password'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
apiVersion: '3.0'
secretPath: '/Production/Databases'
secretTitle: 'PostgreSQL Admin'
separator: '/'
decrypt: true
pipelineVariableName: 'DB_PASSWORD'Retrieve Secrets Safe secret managed account
A task for retrieving managed account credentials from BeyondTrust Password Safe.
Pick the service connection, enter the managed system, and account for the requested secret. Specify the name of the pipeline variable to populate. The pipeline variable is created and set at runtime by the task, it contains your retrieved secret. Reuse of the variable name in multiple tasks overwrites the existing secret.
Task fields:
| Field name | Description |
|---|---|
| Secrets Safe service connection | Select the Secrets Safe service connection to use. |
| Managed System | System managed by Password Safe. |
| Managed Account | Account associated with the managed system. |
| Pipeline Variable Name | A pipeline variable created and set at runtime that contains your retrieved secret. Reuse of the variable name in multiple tasks overwrites the existing secret. |
Example
- task: PasswordSafeGetManagedAccount@2
displayName: 'Get Server Admin Password'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
managedSystem: 'PROD-WEB-01'
managedAccount: 'root'
pipelineVariableName: 'SERVER_PASSWORD'
Complete Pipeline Example
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
# Step 1: Create a folder for build secrets
- task: SecretsSafePostFolder@2
displayName: 'Create Build Secrets Folder'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
folderName: 'Build-$(Build.BuildId)'
folderDescription: 'Secrets for build $(Build.BuildId)'
parentFolderId: '00000000-0000-0000-0000-000000000000'
pipelineVariableName: 'FOLDER_ID'
# Step 2: Store deployment credentials
- task: SecretsSafePostCredentialSecret@2
displayName: 'Store Deploy Credentials'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
apiVersion: '3.0'
folderId: '$(FOLDER_ID)'
title: 'Deploy User'
username: 'deploy-user'
password: '$(DeployPassword)'
owners: |
[
{
"UserId": 2,
"Name": "John Doe",
"Email": "[email protected]",
"OwnerType": "User"
}
]
# Step 3: Store API token
- task: SecretsSafePostTextSecret@2
displayName: 'Store API Token'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
apiVersion: '3.0'
folderId: '$(FOLDER_ID)'
title: 'API Token'
text: '$(ApiToken)'
owners: |
[
{
"UserId": 2,
"Name": "John Doe",
"Email": "[email protected]",
"OwnerType": "User"
}
]
# Step 4: Retrieve a managed account
- task: PasswordSafeGetManagedAccount@2
displayName: 'Get Server Admin Password'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
managedSystem: 'PROD-WEB-01'
managedAccount: 'root'
pipelineVariableName: 'SERVER_PASSWORD'
# Step 5: Retrieve an existing secret
- task: SecretsSafeGetSecret@2
displayName: 'Get Database Password'
inputs:
connectedServiceName: 'MySecretsSafeConnection'
apiVersion: '3.0'
secretPath: '/Production/Databases'
secretTitle: 'MainDB Admin'
pipelineVariableName: 'DB_PASSWORD'
decrypt: true
# Use the retrieved secrets in deployment
- script: |
echo "Deploying application with retrieved secrets..."
# Secrets are available as $(SERVER_PASSWORD), $(DB_PASSWORD), etc.
displayName: 'Deploy Application'Updated 10 days ago
