# Azure DevOps Extension

![](https://762006384-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MJXOXEifAmpyvNVL1to%2F-MkdGjPJbTbFffW4s1-f%2F-MkdGtOxU6O3kUM7r2jV%2Fazuredevops-plugin-header.jpg?alt=media\&token=151310a1-d682-4973-ab09-b9815c8cf9cb)

## Features

* Retrieve secrets from the Keeper Vault from an Azure DevOps pipeline
* Set secret credentials as build arguments or environment variables
* Copy secure files from the Keeper Vault

{% hint style="info" %}
For a complete list of Keeper Secrets Manager features see the [Overview ](https://docs.keeper.io/en/keeperpam/secrets-manager/overview)
{% endhint %}

## Prerequisites

This page documents the Secrets Manager Azure DevOps integration.  In order to utilize this integration, you will need:

* Keeper Secrets Manager access (See the [Quick Start Guide](https://docs.keeper.io/en/keeperpam/secrets-manager/quick-start-guide) for more details)
  * Secrets Manager addon enabled for your Keeper account
  * Membership in a Role with the Secrets Manager enforcement policy enabled
* A Keeper [Secrets Manager Application](https://docs.keeper.io/en/keeperpam/about/terminology#application) with secrets shared to it&#x20;
  * See the [Quick Start Guide](https://docs.keeper.io/en/keeperpam/quick-start-guide#2.-create-an-application) for instructions on creating an Application
* An initialized Keeper [Secrets Manager Configuration](https://docs.keeper.io/en/keeperpam/secrets-manager/about/secrets-manager-configuration)&#x20;
  * The Azure DevOps integration accepts JSON and Base64 format configurations

## Installation

### Install the Keeper Secrets Manager Extension

Download from the [Visual Studio Marketplace here](https://marketplace.visualstudio.com/items?itemName=KeeperSecurity.keeper-secrets-manager) or search for "Keeper Secrets Manager"

![](https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FVvqLlBdgCg8KCBGkcqeM%2Fmarketplace%20image%20cropped.png?alt=media\&token=cff51556-9ff4-4e05-8f7b-bb374d16f36f)

Enable the extension for your Azure organization by selecting an organization and clicking "Download".

![](https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FHuh9CWdwe0laT7gQ3SBe%2Fchoose%20org.png?alt=media\&token=bf61e101-20a2-4229-9dde-11f3532cc616)

## Access Secrets From Azure Pipelines

In order to access secrets from the Keeper Vault, add a task to your Azure Pipelines YAML configuration file.  Then query your records for the desired fields.\
Secret queries use [Keeper Notation](https://docs.keeper.io/en/keeperpam/secrets-manager/about/keeper-notation) and have the following syntax `KeeperNotation > destination` where the destination location is defined by its prefix `var:`, `out:` or `file:` see the examples below.

{% hint style="warning" %}
Since v1.0.4 extension allows use of a search by title syntax, where UID portion could be replaced with the record title and must be escaped according to Keeper Notation rules then it must follow YAML format specifications for escaping special characters.
{% endhint %}

### Create a Keeper Secrets Manager Task

Keeper Secrets Manager tasks look like this:

```
- task: ksmazpipelinetask@1
  inputs:
    keepersecretconfig: $(secret_config)
    secrets: |
      6ya_fdc6XTsZ7i4x9Jcodg/field/password > var:var_password
      6ya_fdc6XTsZ7i4x9Jcodg/field/password > out:out_password
      6ya_fdc6XTsZ7i4x9Jcodg/field/password > out_password2
      6ya_fdc6XTsZ7i4x9Jcodg/file/cert.pem > file:/tmp/mycert.pem

```

In this example, `6ya_fdc6XTsZ7i4x9Jcodg` is the Record UID.  In order to add a task, you can create a task using a Task Form, or add it manually.

#### Add Task Using a Task Form

Search the Tasks menu for "Keeper Secrets Manager" to open the task form.

![](https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FSIUOkIjVALVzmtOYLF18%2Ffind%20task.png?alt=media\&token=75fa26c0-83a9-48e8-b9c0-ebe8de0eb48c)

To fill in the task form and create a Keeper Secrets Manager Task, you will need:

* A [Keeper Secrets Manager Configuration](https://docs.keeper.io/en/keeperpam/secrets-manager/about/secrets-manager-configuration)&#x20;
  * The Azure DevOps Extension accepts JSON and base64 configurations.&#x20;
* One or more [Secret queries](#keeper-secret-queries) (See query syntax below)

![](https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FWIoTCReEZPjRwPEB64hS%2Ffill%20task.png?alt=media\&token=2ae6fb1d-ed5d-4f84-8a7a-a512f1b0b24e)

While it is possible to simply copy a Keeper Secrets Manager configuration into the pipeline, we  recommend keeping the Secrets Manager configuration in an Azure Key Vault that is accessible to your Azure Pipeline. See [Microsoft's documentation](https://docs.microsoft.com/en-us/azure/key-vault/general/overview) to learn more about Azure Key Vault.

Submit the form to add a task to your configuration automatically.

#### Manually add Task

To add a task manually to the pipeline configuration, follow this syntax:

{% tabs %}
{% tab title="Syntax" %}

```
- task: <Task Name>
  inputs:
    keepersecretconfig: <Secrets Manager Configuration>
    secrets: |
      <Secrets Queries>
```

{% endtab %}

{% tab title="Example" %}

```
- task: ksmazpipelinetask@1
  inputs:
    keepersecretconfig: $(secret_config)
    secrets: |
      6ya_fdc6XTsZ7i7x9Jcodg/field/password > pazzword
      6ya_fdc6XTsZ7i7x9Jcodg/field/login > LOGIN
      6ya_fdc6XTsZ7i7x9Jcodg/file/build-vsix.sh > file:/tmp/build-vsix.sh
```

{% endtab %}
{% endtabs %}

### Keeper Secret Queries

Queries for secrets in the Keeper Vault use the following syntax:

#### Get a Standard Field Value

Syntax

```
[UID]/field/[FIELD NAME] > [VARIABLE NAME]
```

Example

```
6ya_fdc6XTsZ7i7x9Jcodg/field/password > my_password
```

#### Get a Custom Field Value

Syntax

```
[UID]/custom_field/[FIELD NAME] > [VARIABLE NAME]
```

Example

```
6ya_fdc6XTsZ7i7x9Jcodg/custom_field/notes > MyNotes
```

#### Get a Two-Factor Code

Syntax

`[UID]/field/oneTimeCode > [VARIABLE NAME]`

Example

```
6ya_fdc6XTsZ7i7x9Jcodg/field/oneTimeCode > MyOneTimeCode
```

#### Get a File

Syntax

```
[UID]/file/[SECRET FILE NAME] > file:[OUTPUT FILE NAME]
```

Example

```
6ya_fdc6XTsZ7i7x9Jcodg/file/cert.pem > file:secret-cert.pem
```

####

#### Variable Types

When saving a secret from the Keeper vault as a variable on your Pipeline, there are a few options for how to set those variables, depending on your needs.

**OUT**

`out` (default) sets the secret to a variable which is accessible in any jobs in the pipeline. If you do not define a variable type, `out` will be used by default.

```
6ya_fdc6XTsZ7i7x9Jcodg/field/password > pazzword
6ya_fdc6XTsZ7i7x9Jcodg/field/password > out:my_password
```

**VAR**

`var` sets the secret to a local variable, usable within the same pipeline job.

```
6ya_fdc6XTsZ7i7x9Jcodg/field/password > var:my_password
```

**FILE**

`file` sets the contents to a file.  Usually used to access certificates and other files from the Keeper Vault.

```
6ya_fdc6XTsZ7i7x9Jcodg/file/build-vsix.sh > file:/tmp/build-vsix.sh
```

**ENVIRONMENT VARIABLE**

`env` set the secret as an environment variable which the build machine can access.

To do this, you first need to set the secret to a pipeline variable, then set it as an environment variable in the bash task.

```
- task: ksmazpipelinetask@1
  name: getKeeperSecrets
  inputs:
    keepersecretconfig: $(sm-config)
    secrets: |
      6ya_fdc6XTsZ7i7x9Jcodg/field/password > var:var_password
      
- bash: |
        echo "Using the mapped env variable: $MY_MAPPED_ENV_VAR_PASSWORD"
    env:
        $MY_MAPPED_ENV_VAR_PASSWORD: $(var_password)
```

## Example Usage

### Get Secrets From Keeper

This example pipeline sets secrets from the Keeper Vault to variables and echoes them.  Note that echoed passwords are masked.

```yaml
trigger:
- master

pool:
  vmImage: ubuntu-latest

steps:

- task: ksmazpipelinetask@1
  name: setKsmSecretsStep
  inputs:
    keepersecretconfig: $(sm-config)
    secrets: |
      6ya_fdc6XTsZ7i7x4Jcodg/field/password > var:var_password
      6ya_fdc6XTsZ7i7x4Jcodg/field/password > out_password2
      6ya_fdc6XTsZ7i7x4Jcodg/field/password > out:out_password
      6ya_fdc6XTsZ7i7x4Jcodg/field/oneTimeCode > var:MyOneTimeCode
      6ya_fdc6XTsZ7i7x4Jcodg/file/build-vsix.sh > file:/tmp/build-vsix.sh

- bash: |
    echo "Using an input-macro works                : $(var_password)"
    echo "Using an output variable (default method) : $(setKsmSecretsStep.out_password2)"
    echo "Using an output variable                  : $(setKsmSecretsStep.out_password)"
    echo "Using an output variable for totp         : $(setKsmSecretsStep.out_password)"
    echo "Using the mapped env var                  : $(MyOneTimeCode)"
    echo "Check injected secret file                : $(file /tmp/build-vsix.sh)"
  env:
    MY_MAPPED_ENV_VAR_PASSWORD: $(var_password) # the recommended way to map to an env variable
  name: display_secret_values
```

### Use Secrets in Multiple Jobs

This example gets passwords and files from Keeper, and utilizes those passwords and files in another job.&#x20;

```yaml
trigger:
- master

pool:
  vmImage: ubuntu-latest

jobs:
- job: ksmSecrets
  displayName: "Inject KSM Secrets"

  steps:

  - task: ksmazpipelinetask@1
    name: setKsmSecretsStep
    inputs:
      keepersecretconfig: $(sm-config)
      secrets: |
        6ya_fdc6XTsZ7i7x9Jcodg/field/password > var:var_password
        6ya_fdc6XTsZ7i7x9Jcodg/field/password > out:out_password
        6ya_fdc6XTsZ7i7x9Jcodg/field/password > out_password2
        6ya_fdc6XTsZ7i7x9Jcodg/file/mykey.pub > file:/tmp/public_key.pem
        6ya_fdc6XTsZ7i7x9Jcodg/file/mykey.pem > file:/tmp/private_key.pem

  - bash: |
      echo "Using an input-macro works                : $(var_password)"
      echo "Using an output variable (default method) : $(setKsmSecretsStep.out_password2)"
      echo "Using an output variable                  : $(setKsmSecretsStep.out_password)"
      echo "Using the mapped env var                  : $MY_MAPPED_ENV_VAR_PASSWORD"
      echo "Check injected secret file                : $(file /tmp/public_key.pem)"
    env:
      MY_MAPPED_ENV_VAR_PASSWORD: $(var_password) # the recommended way to map to an env variable
    name: display_secret_values

  - bash: |
      cat << EOF > decrypted.txt
      This is a decrypted message
      EOF
    name: create_text_file

  - bash: cat decrypted.txt
    name: view_decrpyted_content


  - bash: openssl rsautl -encrypt -inkey /tmp/public_key.pem -pubin -in decrypted.txt -out ecrypted.bin
    name: encrypte_file

  - bash: cat ecrypted.bin
    name: view_encrpyted_content

  - bash: openssl rsautl -decrypt -inkey /tmp/private_key.pem -in ecrypted.bin -out decrypted2.txt
    name: decrpyt_content

  - bash: cat decrypted2.txt
    name: view_decrpyted2_content


- job: encryptFileTest
  dependsOn: ksmSecrets
  variables:
    # map the output variable from A into this job
    # Note:
    #   that files can't be shared between jobs each agent can run only one job at a time
    #   one job is an independent running individual, the communication between different 
    #   jobs requires the use of "middleware", like variable, artifact and etc.
    pwdFromKsmSecrets: $[ dependencies.ksmSecrets.outputs['setKsmSecretsStep.out_password'] ]

  steps:
    - bash: |
        echo "password retrieved from job 'ksmSecrets', step 'pwdFromKsmSecrets', out variable 'setKsmSecretsStep.out_password':$(pwdFromKsmSecrets)"
```
