Akeyless Azure DevOps Extension
This extension provides seamless integration with Akeyless REST API, allowing your Azure DevOps pipelines to securely fetch secrets and inject them as pipeline variables at runtime.
This eliminates the need to hardcode sensitive credentials in your repositories, enhancing your security posture.
The extension currently includes:
- Akeyless Service Connection: A custom service connection type to configure your Akeyless Vault access details.
- Akeyless Auth Task: A pipeline task to authenticate with Akeyless.
- Akeyless Fetch Secrets Task: A pipeline task to retrieve one or more secrets from Akeyless Vault and expose them as pipeline variables.
- Akeyless Get Dynamic Secret Value Task: A pipeline task to retrieve a dynamic secret from the Akeyless Gateway and expose it as a pipeline variable.
- Akeyless Get Rotated Secret Value Task: A pipeline task to retrieve a rotated secret from the Akeyless Gateway and expose it as a pipeline variable.
Any Akeyless API operations performed by this extension will be registered as Source: Azure-DevOps-Extension
Installation
To get started, you need to install the Akeyless Azure DevOps Extension from the Visual Studio Marketplace into your Azure DevOps organization.
- Navigate to your Azure DevOps organization.
- Click on the Organization settings icon (bottom-left corner).
- Under "Extensions", click on Extensions.
- Click on Browse marketplace.
- Search for "Akeyless".
- Click on the extension and then click Get it free or Install.
- Select your organization and complete the installation process.
Create an Akeyless Service Connection
Before using the task in your pipelines, you need to configure a Service Connection that allows Azure DevOps to authenticate with your Akeyless Vault.
- Navigate to your Azure DevOps project.
- Click on Project settings (bottom-left corner).
- Under "Pipelines", click on Service connections.
- Click New service connection.
- Search for and select the Akeyless service connection type.
- Click Next.
- Configure the service connection parameters:
- Server URL (Base Path): Enter the base URL of your Akeyless Gateway or Akeyless SaaS API (e.g., https://api.akeyless.io, https://my.gw/api/v2).
- Access ID: Your Akeyless Access ID.
- Service connection name: Give your connection a descriptive name (e.g., my-akeyless-vault, mge_prod). This name will be used in your pipeline YAML.
- Description: (Optional) Provide a brief description.
- Grant access permission to all pipelines: (Recommended for ease of use, or configure specific pipeline permissions later).
- Click Save to create the service connection.
Sample Azure Pipelines YAML
API Key Authentication
This example demonstrates how to authenticate and fetch secrets to retrieve multiple secrets and then use them in a subsequent script, such as initializing an AI agent.
# More info in https://aka.ms/yaml
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: akeyless-auth@0
name: AkeylessAuth
inputs:
connectedServiceName: 'mge_prod'
access-key: "${{ variables.AKEYLESS_ACCESS_KEY }}"
- task: akeyless-get-secrets-value@0
displayName: 'Fetch Akeyless Secrets for AI Agent'
name: fetch
inputs:
connectedServiceName: 'mge_prod'
token: "$(AkeylessAuth.akeylessToken)"
secretsPaths: 'api_key=/ai/agent/api-key,model_id=/ai/agent/model-id,endpoint_config=/ai/agent/config/endpoint'
- script: |
echo "--- Initializing Agent ---"
python initialize_ai_agent.py \
--api-key "$(fetch.api_key)" \
--model-id "$(fetch.model_id)" \
--endpoint "$(fetch.endpoint_config)"
echo "Agent initialization complete."
displayName: 'Initialize agent with Fetched Secrets'
Key Points:
- The
secretsPaths
input accepts a comma-separated list of key/value pairs where the key is the name of the output Azure DevOps Pipeline variable and the value is secret path.
- Secrets are automatically marked as secret variables in the pipeline, meaning their values will be masked in logs.
JWT Authentication
The Pipeline below provides an example for using the JWT authentication flow by using the JWT provided by
Azure:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: AzureCLI@2
inputs:
azureSubscription: "${{ variables.SUBSCRIPTION_ID }}"
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
TOKEN_RESPONSE=$(az account get-access-token \
--resource "${{ variables.ENTRA_CLIENT_ID }}" \
--tenant "${{ variables.ENTRA_TENANT_ID }}" \
--query '{accessToken:accessToken}' -o json)
JWT_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.accessToken')
if [ -z "$JWT_TOKEN" ]; then
echo "##vso[task.logissue type=error]Failed to retrieve JWT token from Microsoft Entra ID."
exit 1
fi
echo "Microsoft Entra ID JWT token retrieved successfully (masked)."
echo "##vso[task.setvariable variable=ENTRA_JWT;isSecret=true]$JWT_TOKEN"
- task: akeyless-auth@0
name: AkeylessAuth
inputs:
connectedServiceName: 'mge_prod_jwt'
jwt: "$(ENTRA_JWT)"
- task: akeyless-get-secrets-value@0
displayName: 'Fetch Akeyless Secrets for AI Agent'
inputs:
connectedServiceName: 'mge_prod'
token: "$(AkeylessAuth.akeylessToken)"
secretsPaths: 'api_key=/ai/agent/api-key,model_id=/ai/agent/model-id,endpoint_config=/ai/agent/config/endpoint'
- script: |
echo "--- Initializing Agent ---"
python initialize_ai_agent.py \
--api-key "$(api_key)" \
--model-id "$(model_id)" \
--endpoint "$(endpoint_config)"
echo "Agent initialization complete."
displayName: 'Initialize agent with Fetched Secrets'
- The Akeyless Authentication Method is automatically parsed from the supplied Access ID in the Service Connection.
Dynamic Secret Example
This example demonstrates how to fetch a dynamic secret, which generates credentials on-demand:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: akeyless-auth@0
name: AkeylessAuth
inputs:
connectedServiceName: 'mge_prod'
access-key: "${{ variables.AKEYLESS_ACCESS_KEY }}"
- task: akeyless-get-dynamic-secret-value@0
name: dbDynamicSecret
displayName: 'Fetch Akeyless Dynamic Secret for PostgreSQL'
inputs:
connectedServiceName: 'mge_prod'
token: "$(AkeylessAuth.akeylessToken)"
name: '/dynamic/postgres/credentials'
timeout: 30
- script: |
echo "--- Connecting to PostgreSQL ---"
# Parse the dynamic secret response
username=$(echo "$(dbDynamicSecret.dynamicSecretValue)" | jq -r '.user')
password=$(echo "$(dbDynamicSecret.dynamicSecretValue)" | jq -r '.password')
ttl=$(echo "$(dbDynamicSecret.dynamicSecretValue)" | jq -r '.ttl_in_minutes')
id=$(echo "$(dbDynamicSecret.dynamicSecretValue)" | jq -r '.id')
python connect_postgres.py \
--username "$username" \
--password "$password"
echo "PostgreSQL connection established with dynamic credentials."
displayName: 'Connect to PostgreSQL with Dynamic Credentials'
The task akeyless-get-dynamic-secret-value
outputs a JSON response with the following structure:
{
"id":"tmp_p-[REDACTED]",
"password":"HXE@[REDACTED]",
"ttl_in_minutes":"60",
"user":"tmp_p-[REDACTED]"
}
Rotated Secret Example
This example demonstrates how to fetch a single rotated secret, which is automatically rotated by Akeyless:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: akeyless-auth@0
name: AkeylessAuth
inputs:
connectedServiceName: 'mge_prod'
access-key: "${{ variables.AKEYLESS_ACCESS_KEY }}"
- task: akeyless-get-rotated-secret-value@0
displayName: 'Fetch Akeyless Rotated Secret for Database'
name: dbRotatedSecret
inputs:
connectedServiceName: 'mge_prod'
token: "$(AkeylessAuth.akeylessToken)"
name: '/rotated/pgsql/password'
- script: |
echo "--- Connecting to PostgresSQL ---"
# Parse the rotated secret response
username=$(echo "$(dbRotatedSecret.rotatedSecretValue)" | jq -r '.username')
password=$(echo "$(dbRotatedSecret.rotatedSecretValue)" | jq -r '.password')
python connect_postgres.py \
--username "$username" \
--password "$password"
echo "Database connection established."
displayName: 'Connect to Database with Rotated Credentials'
The task akeyless-get-rotated-secret-value
outputs a JSON response with the following structure:
{
"username":"tmp_p-[REDACTED]",
"password":"HXE@[REDACTED]",
}
Known Limitations
- We currently only support API Key and JWT authentication methods.