> For the complete documentation index, see [llms.txt](https://docs.keeper.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.keeper.io/keeperpam/secrets-manager/about/secrets-manager-configuration.md).

# Secrets Manager Configuration

## About

Each Keeper Secrets Manager SDK and integration uses a "configuration" to store connection tokens, encryption keys, identifiers and domain information used to authenticate and decrypt data from the Keeper Secrets Manager APIs.

Secrets Manager configurations are created from [One Time Access Tokens](/keeperpam/secrets-manager/about/one-time-token.md) and have a one to one relationship with[ client devices](/keeperpam/secrets-manager/about/terminology.md#client-device).

#### Configuration Uniformity

All Keeper Secrets Manager SDKs and integrations use the same configuration format. Raw configurations are in JSON format, though some integrations accept base64 format.

## Creating a Secrets Manager Configuration

### In the Keeper Vault

A Secrets Manager configuration can be created in the Keeper Vault when creating a new Secrets Manager device.

First navigate to the Secrets Manager tab, and select an Application from the list.

<figure><img src="/files/41CYiWalZsmOkG1uKLaR" alt=""><figcaption></figcaption></figure>

Then, select the "Devices" tab in the right-hand application pane, and click "Edit" to go into edit mode.

<figure><img src="/files/Ma7y76D2XldvThptfccp" alt=""><figcaption></figcaption></figure>

From the edit view, you can click "Add Device" to create a new Secrets Manager device to the application.

The Add Device menu will appear. Enter a name for this device, and then select "Configuration File" from the method dropdown.

<figure><img src="/files/Cm3fTj6QDBw4lXxBmnmc" alt=""><figcaption></figcaption></figure>

After Configuration File is selected, you are given options for receiving the configuration. You can choose to generate a configuration in Base64 or json format, and download the configuration to a file, or copy it to the clipboard.

<figure><img src="/files/MvqNrJCOHHSHqH4wTMeL" alt=""><figcaption></figcaption></figure>

Most Secrets Manager integrations use a base64 string, but you may need a json file in some circumstances.

When ready, click the download or copy button to receive you configuration. Note that when you do this the first time, the device will be created. You are able to download or copy the configuration multiple times.

<figure><img src="/files/WKDJQHFVA9N0sMiHnMVl" alt=""><figcaption></figcaption></figure>

### Using a SDK/Integration

Many Keeper Secrets Manager SDKs and Integrations support creating their own configuration file. You need to pass a One Time Access Token, and the configuration is created automatically.

#### SDK Example

Below is an example of how to use the[ Python SDK ](/keeperpam/secrets-manager/developer-sdk-library/python-sdk.md)to create a configuration file. The configuration is created when Secrets Manager is initialized with a One Time Access Token.

```python
from keeper_secrets_manager_core import SecretsManager
from keeper_secrets_manager_core.storage import FileKeyValueStorage

secrets_manager = SecretsManager(
    token='<One Time Access Token>',
    config=FileKeyValueStorage('config.json')
)
```

In this example, the configuration is being saved to a file named "config.json"

{% hint style="info" %}
When using a SDK to create a configuration, you only need to initialize and create the configuration file once. After the file has been created, you can use the file to initialize the SDK and remove the One Time Access Token.
{% endhint %}

#### Integration Example

Below is in example of using the Keeper Secrets Manager[ Jenkins Plugin](/keeperpam/secrets-manager/integrations/jenkins-plugin.md).

![](/files/nJ7FHX76K8CwdlUAbKoR)

The Jenkins plugin takes a One Time Access Token to initialize and creates a configuration automatically behind-the-scenes. In this example, simply enter a One Time Access Token in the form and click 'OK'.

### Using a CLI Tool

A Secrets Manager configuration can be initialized from a One Time Access Token using the Secrets Manager CLI as well as the Commander CLI tools. Some Keeper Secrets Manager integrations require a pre-initialized configuration and you will need to use the CLI tools to create a configuration in these cases.

#### Secrets Manager CLI

The [Secrets Manager CLI (KSM) ](/keeperpam/secrets-manager/secrets-manager-command-line-interface.md)tool can initialize a One Time Access Token and create a configuration.

To do this, run the `init` command

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

```bash
# initialize a configuration in JSON format and display it
$ ksm init default <One Time Access Token>

# initialize a configuration in k8s format and display it
$ ksm init k8s <One Time Access Token>

# initialize a JSON configuration and save it to a file
$ ksm init default --plain <One Time Access Token> > <FILENAME>
```

{% endtab %}

{% tab title="Example" %}

```bash
# initialize a configuration in JSON and display it
$ ksm init default US:KBChlYeZ15wLzvhLVXmT61euw0DJO0cTVfkD-b-qesw

# initialize a configuration in k8s format and display it
$ ksm init k8s US:KBChlYeZ15wLzvhLVXmT61euw0DJO0cTVfkD-b-qesw

# initialize a configuration and save it to a file
$ ksm init default --plain US:KBChlYeZ15wLzvhLVXmT61euw0DJO0cTVfkD-b-qesw > "ksm-config.json"
```

{% endtab %}
{% endtabs %}

#### Commander CLI

[Commander CLI ](/keeperpam/commander-cli/overview.md)can be used to initialize a One Time Access Token and create Secrets Manager configuration.

Use the `secrets-manager client add` Command with `--config-init` to create a configuration. Configurations can be created in json or base64 formats, or in integration-specific formats in some cases. (see the [integrations documentation](/keeperpam/secrets-manager/integrations.md) for more information on what format each integration accepts)

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

```bash
my vault> secrets-manager client add --app <APP NAME> --config-init <FORMAT>
```

{% endtab %}

{% tab title="Example" %}

```bash
# create a json configuration
secrets-manager client add --app MyApp --config-init json --unlock-ip

# create a base64 configuration
secrets-manager client add --app MyApp --config-init b64 --unlock-ip

# create a Kubernetes configuration
secrets-manager client add --app MyApp --config-init k8s --unlock-ip
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
When initializing a configuration in Commander, typically `--unlock-ip` should be included in the command. If it is not included, the client device will be locked to the IP Address that Commander is using.
{% endhint %}

## Binding Lifecycle

A configuration moves through three states. Knowing which one you are in matters whenever you store a configuration somewhere other than a local file, because its contents change after the first successful call.

* **Initialized** — the constructor has run but no network call has happened. The configuration holds only what the one-time token carried. *No token has been redeemed yet.*
* **Bound** — the first API call (for example, the first `get_secrets`) redeems the one-time token. The server response is written back into the configuration. The application key and client identifier are added and the one-time token is removed. *The token is now consumed and cannot be reused.*
* **Reused** — every later call, and every later process that loads the bound configuration, authenticates with the stored keys and skips redemption entirely.

{% hint style="info" %}
The constructor does not contact Keeper. A one-time token is redeemed by the **first API call**, not by creating the client. This is why generating a configuration "for later use" requires at least one read operation to bind the token.
{% endhint %}

### What the configuration holds in each state

These are the JSON configuration keys. For the encryption role of each key, see [Security & Encryption Model](/keeperpam/secrets-manager/about/security-encryption-model.md).

<table><thead><tr><th width="186.71484375">Configuration key</th><th width="133.30078125">Initialized</th><th>Bound</th><th>Notes</th></tr></thead><tbody><tr><td><code>hostname</code></td><td>Yes</td><td>Yes</td><td>Keeper region; set when the configuration is created</td></tr><tr><td><code>clientKey</code></td><td>Yes</td><td>Removed</td><td>The one-time token's secret value (the token you pass to the constructor is <code>REGION:clientKey</code>); used on the first call to derive <code>clientId</code> and unwrap <code>appKey</code>, then removed</td></tr><tr><td><code>privateKey</code></td><td>Yes</td><td>Yes</td><td>Client device private key; signs every request; never removed</td></tr><tr><td><code>serverPublicKeyId</code></td><td>Optional</td><td>Yes</td><td>Identifies the Keeper public key used for the transmission wrapper</td></tr><tr><td><code>clientId</code></td><td>—</td><td>Added</td><td>Client device identifier derived from the redeemed token</td></tr><tr><td><code>appKey</code></td><td>—</td><td>Added</td><td>Application key that decrypts your secrets; returned on the first call</td></tr><tr><td><code>appOwnerPublicKey</code></td><td>—</td><td>Added when returned</td><td>Owner public key, used for creating and updating records</td></tr></tbody></table>

### Persisting and rebuilding a bound configuration

When the configuration lives in an external store (a database, a cloud secret, a KMS-wrapped blob) rather than a local file, persist it **after** it has bound:

1. Construct the client with the one-time token.
2. Make one call (for example `get_secrets`) to bind it.
3. Read the now-bound configuration back out and save it to your store.
4. In later processes, load the bound configuration from your store and construct the client from it — no token needed.

{% hint style="danger" %}
**Persist after binding, not before.** If you save a still-initialized configuration and then build a second client from that copy, both clients try to redeem the same one-time token and only one succeeds. Make one successful call first, then persist.
{% endhint %}

```python
import json
from keeper_secrets_manager_core import SecretsManager
from keeper_secrets_manager_core.storage import InMemoryKeyValueStorage

# my_store is your external store (database, cloud secret, KMS-wrapped blob)

# First run: redeem the token, then read the bound configuration back out
config = InMemoryKeyValueStorage()
sm = SecretsManager(token="US:ONE_TIME_TOKEN", config=config)
sm.get_secrets()                              # binds; the token is consumed here

bound = config.read_storage()                 # dict keyed by configuration field names
my_store.save("ksm-config", json.dumps(bound))

# Later process: rebuild from the bound configuration, no token required
restored = InMemoryKeyValueStorage(my_store.load("ksm-config"))
sm = SecretsManager(config=restored)
secrets = sm.get_secrets()
```

{% hint style="info" %}
Each SDK page shows the same persist-and-rebuild step using that language's storage class.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/secrets-manager/about/secrets-manager-configuration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
