Sync secrets from an external vault

Copy secrets from an external vault into the Secrets & Variables of a True
Platform project. This guide uses Azure Key Vault as the example source. The
same steps apply to other vaults.

The API creates, reads, or deletes one entry in each call. There is no batch
call. There is no update call. To change a value, delete the entry and create it
again. A sync therefore sends one or two calls for each secret.

You need curl, jq, and Bash. The Azure example also needs the Azure CLI,
signed in to an identity that can read the secrets.

1. Set up authentication and project context

Use your tenant host, https://<tenant>.katalon.io, without a trailing slash.
Authenticate with HTTP Basic: leave the username empty and use your Katalon API
key as the password. See
Authenticate with the v2 API.
Your key's user must have access to the account and project.

Send x-project-id (numeric project ID) on every request. The project ID
selects the project that receives the secrets.

Set KATALON_API_HOST, KATALON_API_KEY, and KATALON_PROJECT_ID in your
environment. Keep the API key in a secret store. Do
not enable shell tracing (set -x), because it prints the values. This helper
sends the key through standard input, not through process arguments. If the key
contains " or \, write them as \" and \\ for curl's configuration format.

katalon_request() {
  : "${KATALON_API_KEY:?Missing API key}"
  printf 'user = ":%s"\n' "${KATALON_API_KEY}" |
    curl --config - --silent --show-error --fail-with-body \
      --header "Accept: application/json" \
      --header "x-project-id: ${KATALON_PROJECT_ID:?Missing project ID}" \
      "$@"
}

2. List the entries that the project has now

List secrets and variables
returns every entry that applies to the project, in one response:

entries="$(katalon_request "${KATALON_API_HOST:?Missing tenant host}/v2/sh/params")"
printf '%s' "${entries}" | jq -r '.items[] | [.kind, .logicalKey, (.projectId // "account")] | @tsv'

The response never contains a secret value. A secret entry has masked and a
ref such as APP_PASSWORD. A variable entry has its value.

An entry without projectId is an account default that the project inherits.
Do not delete account defaults in a sync. Create a project entry with the same
key instead. The project entry takes precedence in test runs.

The list returns up to 1000 entries and has no paging.

3. Create or replace one secret

The function below reads one secret value from standard input. It writes one
key to the project:

  1. If the project has its own entry with this key, the function deletes it.
  2. The function creates the secret with the new value.

Secrets and variables share one set of keys. A create call returns 409 if the
key exists in the project, so the delete must come first.

put_secret() {
  key="$1"
  body="$(jq -Rs --arg key "${key}" '{kind: "SECRET", logicalKey: $key, value: sub("\n$"; "")}')"
  old_id="$(printf '%s' "${entries}" | jq -r --arg key "${key}" --argjson project "${KATALON_PROJECT_ID}" \
    '.items[] | select(.logicalKey == $key and .projectId == $project and .scope == {}) | .id')"
  if [ -n "${old_id}" ]; then
    katalon_request --request DELETE "${KATALON_API_HOST}/v2/sh/params/${old_id}"
  fi
  katalon_request --request POST \
    --header "Content-Type: application/json" \
    --data-binary @<(printf '%s' "${body}") \
    "${KATALON_API_HOST}/v2/sh/params"
}

The function sends the request body through a file descriptor. The secret value
does not appear in process arguments. It removes one final newline from the
input, because command-line tools such as the Azure CLI add one.

The calls are
Delete a secret or variable
and
Create a secret or variable.
The create response has masked: true and no value.

CAUTION: Do not start test runs in the project during a sync. A run that starts
after a delete and before the create does not get that key.

4. Copy the secrets from Azure Key Vault

Set AZURE_KEY_VAULT to the name of your key vault. This loop reads each enabled
secret and writes it to the project with the same name:

az keyvault secret list --vault-name "${AZURE_KEY_VAULT:?Missing key vault name}" \
  --query "[?attributes.enabled].name" --output tsv |
  while IFS= read -r name; do
    az keyvault secret show --vault-name "${AZURE_KEY_VAULT}" --name "${name}" \
      --query value --output tsv | put_secret "${name}"
  done

A key in True Platform has 1 to 128 letters, digits, underscores, dots, or
hyphens. Azure Key Vault secret names fit this rule. To use a different key in
True Platform, change the name that you pass to put_secret.

Run the sync again when a value changes in the external vault. Each run replaces
the project entry for each key. It does not delete project entries for secrets
that you removed from the external vault. To remove one, find its id in the
list and call
Delete a secret or variable.

5. Use the secrets in test runs

Katalon passes every secret and variable of the project to each cloud test run.
You do not send the values again at run time.

  • In an automated test run, each entry arrives as a global variable with the
    same key. Give the entry the key that your execution profile uses.
  • In a variable or secret value, KEY inserts the value of another entry.
    A variable cannot refer to a secret.

For manual test runs and Run with AI, see
Secrets and variables in test runs.

Troubleshooting

  • 409 with duplicate_param: the project already has an entry with this key.
    Delete it first, then create it again.
  • 400 with invalid_request: the key does not match the allowed characters, or
    a required field is missing.
  • 403: check that your key's user has access to the account and project. Check
    that the entry belongs to the project in x-project-id. An account default
    needs the account role OWNER or ADMIN to delete.
  • A secret value is never returned by this API. To check that a sync worked,
    compare the keys in the list with the names in your external vault.

Did this page help you?