CI/CD Integrations provided with Keeper Secrets Manager
Keeper Secrets Manager integrates into popular CI/CD platforms and development environments. Use Keeper Secrets Manager to inject secrets into your build processes, and remove hard-coded credentials from your environments.
A collection of Ansible plugins that interact with Keeper Secrets Manager
Protect your AWS Access Keys with Keeper Secrets Manager
Go to AWS CLI Credential Process Documentation
Sync secrets from the Keeper Vault with AWS Secrets Manager
Go to AWS Secrets Manager Documentation
Protect your Keeper Secrets Manager configuration with AWS KMS.
Securely retrieve secrets from the Keeper Vault and use them in Azure DevOps pipelines. Remove hardcoded values, fetch secure files, and keep all your build credentials in the Keeper Vault.
Go to Azure DevOps Integration
Sync secrets from the Keeper Vault with Azure Key Vault.
Go to Azure Key Vault Sync Documentation
Protect your Keeper Secrets Manager configuration with Azure Key Vault.
Go to Azure Key Vault Encryption Documentation
Retrieve secrets from the Keeper Vault within BitBucket Pipelines.
Go to BitBucket Plugin Documentation
The Secrets Manager CLI can be used to pull secrets from a Docker image at runtime, or it can be used by building it into the docker image.
Go to Docker Image Documentation
Keeper Secrets Manager integrates with the Docker Runtime so that you can dynamically retrieve a secret from the vault when the container executes.
Go to Docker Runtime Documentation
A general purpose docker image to retrieve secrets.
Protect your Keeper Secrets Manager connections with the Entrust HSM
Go to Entrust HSM Documentation
This integration will let you sign git commits with an SSH key in your Keeper Vault (via Keeper Secrets Manager) rather than using a key stored on disk.
This action securely retrieves secrets from Keeper and places them to the desired destination of the GitHub Actions runner such as an environment variable, output parameters of the step or to a file.
Go to Github Actions Integration
Bring secret credentials into your GitLab Pipeline builds using Keeper's Secrets Manager GitLab plugin.
Sync secrets from the Keeper Vault with GCP Secret Manager.
Go to GCP Secret Manager Documentation
Protect your Keeper Secrets Manager connections with GCP Key Management.
Go to GCP Key Management Encryption Documentation
Use Keeper Secrets Manager with HashiCorp Vault as a Data Source
Go to Hashicorp Vault Documentation
Use Keeper Secrets Manager SDKs to bring secret credentials and files securely into Heroku builds.
The Jenkins plugin for Keeper Secrets Manager allows you retrieve secrets from the Keeper Vault and place the values into environmental variables or files within the builder and workflow pipelines.
Go to Jenkins Plugin Documentation
Store connection credentials in the Keeper Vault and easily use them in Connection Manager.
Go to Keeper Connection Manager Documentation
Keeper Secrets Manager can be integrated into your K8s cluster for accessing Keeper secrets in real-time across all pods.
Go to the Kubernetes External Secrets Operator Documentation
Go to the legacy Kubernetes Documentation
Store and retrieve secrets from the Linux Keyring
Go to the Linux Keyring Documentation
Integrate Keeper Secrets Manager into AI agents using this Docker container
Go to the MCP Documentation for Docker
Integrate Keeper Secrets Manager into AI agents using this Node module
Go to the MCP Documentation for Node
Use credentials from your Keeper Vault in Octopus Deploy workflows. Integrate with Keeper Secrets Manager to securely access all the platforms and services you connect to with Octopus Deploy.
Protect your Keeper Secrets Manager connections with Oracle Key Vault.
Go to Oracle Key Vault Encryption Documentation
Utilize PowerShell's Secret Management module to access secrets from Keeper.
Go to PowerShell Documentation
Retrieve credentials from the vault from the ServiceNow Management, Instrumentation, and Discovery (MID) Server integration.
Go to ServiceNow Documentation
Use secrets from the Keeper vault in TeamCity builds.
Retrieve secrets from the Keeper Vault within Teller environments.
The Keeper Terraform Plugin utilizes Keeper Secrets Manager to provide access to secret credentials saved in the Keeper Vault. The Keeper Terraform plugin allows for injecting secrets directly into Terraform builds securely using Keeper's zero-knowledge infrastructure.
Store and retrieve secrets from the Windows Credential Manager
Go to the Windows Credential Manager Documentation
Use credentials from your Keeper Vault in XSOAR workflows. Integrate with Keeper Secrets Manager to securely access all the platforms and services you connect to with XSOAR.
Use Keeper Secrets Manager in a CLI environment. Build scripts that securely utilize your secrets, or easily access Secrets Manager functionality from your terminal.
The Keeper Secrets Manager PowerShell plugin utilizes Microsoft PowerShell's Secret Management module to inject secrets from the Keeper Vault into your PowerShell scripts.
Go to PowerShell Documentation
The Keeper Secrets Manager CLI ("KSM CLI") provides core Secrets Manager Vault interaction from a terminal, shell script or any software that can be launched from a shell.
Use Keeper Secrets Manager with Ansible
Retrieve secrets from the Keeper vault to use in Ansible Playbooks
Update the value of secrets in the Keeper Vault from Ansible
Copy files from the Keeper Vault
Use Keeper Secrets Manager within Ansible Tower to fetch secret credentials and files in your Ansible Playbooks.
Check out the nested pages for using Secrets Manager with Ansible
How to use Keeper Secrets Manager to fetch secret credentials and files in your Ansible Playbooks
Store Keeper Secrets Manager configuration credentials in Ansible Tower and create reusable playbook templates that utilize Keeper Secrets Manager features.
A collection of Ansible plugins that interact with your Keeper account and can be used in your automations.
Retrieve secrets from the Keeper vault to use in Ansible Playbooks
Update the value of secrets in the Keeper Vault from Ansible
Create records from Ansible
Copy files from the Keeper Vault
This page documents the Secrets Manager Ansible integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper account
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The Ansible integration accepts both Base64 and JSON format configurations
Due to the flexibility of Ansible, where you install the plugins depends on your Ansible installation and playbook locations.
The collection can be found on the Ansible Galaxy website. You can install the collection with the follow command line.
$ ansible-galaxy collection install keepersecurity.keeper_secrets_manager
Ansible Galaxy collection uses long plugin names. The name is the collection name combined with the plugin name. For example, the keeper_copy
plugin name when using Ansible Galaxy is keeper_security.keeper_secrets_manager.keeper_copy
. If you want to use the short plugin name, add keepersecurity.keeper_secrets_manager
to the collections
block of your playbook.
- name: Keeper Copy
hosts: my_hosts
collections:
- keepersecurity.keeper_secrets_manager
tasks:
- name: Copy a password
keeper_copy:
uid: RECORD UID
...
The Ansible module for Keeper is installed with the command below. Make note of the location where the module is installed, as this will be needed in the Ansible playbook configuration.
$ pip3 install -U keeper_secrets_manager_ansible
Find the Keeper Secrets Manager Ansible Plugin source code in the GitHub repository.
The Keeper ansible plugins are installed in the site-packages directory of your version of Python or your current virtual environment. You can find the plugin locations using the following command:
$ keeper_ansible --config
# Below are the directory paths to action and lookup plugins.
ANSIBLE_ACTION_PLUGINS=...site-packages/keeper_secrets_manager_ansible/plugins/action_plugins
ANSIBLE_LOOKUP_PLUGINS=...site-packages/keeper_secrets_manager_ansible/plugins/lookup_plugins
Those paths can be used in your ansible.cfg.
[defaults]
action_plugins = ...site-packages/keeper_secrets_manager_ansible/plugins/action_plugins
lookup_plugins = ...site-packages/keeper_secrets_manager_ansible/plugins/lookup_plugins
Prior to proceeding with this guide, make sure you meet all the prerequisites and have the following:
KSM Application and it's One-Time Access Token
Keeper Ansible module installed
In order to use the Ansible plugin for Keeper Secrets Manager, a Keeper config file is required. Once you have a config file, the configuration values can be placed into the Ansible variable files. These variable files can be encrypted with Ansible vault.
Using the Keeper Ansible module and the generated One-Time Access Token, generate a Configuration file:
$ keeper_ansible --token XX:XXXXXX
Config file create at location client-config.json
This will generate the Keeper JSON configuration file in the current directory.
If you do not have your Python module bin path added your PATH environment variable, you can create a config with the following command.
$ python3 -m keeper_secrets_manager_ansible --token XX:XXXXXX
Config file create at location client-config.json
The default name for the JSON configuration file is client-config.json. The content of the file will look like the following:
{
"appKey" : "XXXXXXXX",
"appOwnerPublicKey": "XXXXXXX",
"clientId": "XXXXXXXX",
"hostname": "XXXXX",
"privateKey": "XXXXXXXX",
"serverPublicKeyId": "XX"
}
This config file allows your Ansible playbook to authenticate and retrieve designated secrets from the vault.
The Keeper Secrets Manager plugins can use multiple configuration methods. For example, the Base64 encode configuration can be used.
---
keeper_config: U09NRVRFc2R ... GFzZGFzZGFzZHNhWFQK==
Ansible can use the client-config.json config file directly. It can be specified in the Ansible variables using the keeper_config_file variable key.
---
keeper_config_file: /path/to/client-config.json
Another solution is to place the values in your client-config.json file into an Ansible variable file. For example, the values can be placed into the group_vars, host_vars, or in the task files:
---
keeper_app_key: XXXXX
keeper_client_id: XXXXX
keeper_token: XXXXX
keeper_private_key: XXXXX
keeper_app_owner_public_key: XXXXX
keeper_server_public_key_id: XX
For security, the group_vars or host_vars files can be encrypted with ansible-vault.
A list of valid Ansible Variables for the Keeper plugin are below:
Ansible Variable
JSON Key
Description
keeper_config
--
A Base64 encoded configuration string.
keeper_config_file
--
An alternative path and name for the JSON configuration file, if not current directory or named differently than client-config.json.
keeper_token
clientKey
The one time access token, also known as the client key. Only used to initialize the configuration.
keeper_client_id
clientId
The client id provided from Secrets Manager after the one time access token is used. Required.
keeper_app_key
appKey
The app key provided from the secret management service after the one time access token is used. Required.
keeper_private_key
privateKey
The private key provided from the secret management service after the one time access token is used. Required.
keeper_app_owner_public_key
appOwnerPublicKey
The public key used for creating records. Required if using the keeper_create
plugin.
keeper_server_public_key_id
serverPublicKeyId
Selects which public key to use when connecting to the server. If the server wants a different public key the SDK will handle switching. Not required, but will reduce number of web service calls.
keeper_hostname
hostname
The Secrets Manager backend hostname. Defaults to US. Supports "US", "EU", "AU" and "US_GOV" values depending on your Keeper data center location. Required.
keeper_log_level
--
Set the log level of the SDK. Acceptable levels are DEBUG, INFO, WARNING, ERROR, and CRITICAL. Defaults to ERROR.
keeper_record_cache_secret
--
Required for the keeper_cache_records
action. Used to encrypt records in cache. The value of this variable can be created in the playbook. See action example.
keeper_use_cache
--
Use a cache of the vault. Defaults to False. Cache file are only used as backup for network problems.
keeper_cache_dir
--
The directory to write and read the cache file.
keeper_record_types
--
An list of Keeper Commander record type definitions.
As an optional method, values can be passed in through the ansible-playbook
command. Example:
$ ansible-playbook my_playbook.yml \
-e "keeper_app_key=XXXXX" \
-e "keeper_client_id=XXXXX" \
-e "keeper_token=XXXXX" \
-e "keeper_private_key=XXXXX"
There are three Keeper action plugins and one lookup plugin.
For all the plugins, the following arguments are used. Either the uid
or title
is required.
uid
- The Record UID of the desired record.
title
- The Record Title of the desired record.
field
- Retrieve the value with specified label from the record.
custom_field
- Retrieve the value with the specific custom field name.
file
- Retrieve the file with the specified name from the record.
The uid
value is required, and you need either field
or file
populated.
Actions can either use Keeper Notation or the record UID or Title, combined with the task attributes array_index
and value_key
to get a specific value.
For example, a complex value like Phone number is an array of objects.
[
{
'number': '(555) 123-1234',
'type': 'Work',
'ext': '11'
},
{
'region': 'AD',
'number': '111-2223333',
'ext': '5555',
'type': 'Mobile'
}
]
The example, below is show how to use Keeper Notation and array_index
and value_key
to get the same result.
---
- name: Keeper Get
hosts: my_hosts
# Include line below if installed via ansible galaxy or use long plugin names.
# collections:
# - keepersecurity.keeper_secrets_manager
tasks:
- name: Get the second phone number using Keeper Notation
keeper_get:
notation: "RECORD UID/field/phone[1][number]"
register: second_number_notation
- name: Get the second phone number using array_index and value_key
keeper_get:
uid: "RECORD UID"
field: phone
array_index: 1
value_key: "number"
register: second_number_non_notation
The plugin keeper_cache_records
is used to retrieve a select amount of records to be stored in a cache. The cache can then be used by other actions. This is used to reduce the number of API calls by getting all required record up front.
---
- name: Cache records
hosts: my_hosts
# Include line below if installed via ansible galaxy or use long plugin names.
# collections:
# - keepersecurity.keeper_secrets_manager
tasks:
- name: Generate a Keeper Record Cache secret
keeper_password:
length: 64
register: keeper_record_cache_secret
no_log: True
- name: Store the Keeper Record Cache secret into variables.
set_fact:
keeper_record_cache_secret: "{{ keeper_record_cache_secret.password }}"
no_log: True
- name: Cache records. Will use keeper_record_cache_secret from above.
keeper_cache_records:
uids:
- RECORD UID
- RECORD UID
titles:
- My Record Title
- My Record Title Too
register: my_records
no_log: True
- name: Copy a file
keeper_copy:
cache: "{{ my_records.cache }}"
uid: RECORD UID
file: my_cert_file.crt
dest: /etc/special.crt
owner: root
group: root
mode: "0644"
backup: yes
The records can be retrieved by the record UID or by the record title. The result of the action is an encrypted serialization of the records. The result should be stored in Ansible by using the register variable so it can be used by other actions. The encrypted serialization of the records can be quite long. For security and reducing log noise, it is recommended to set no_log
to True.
keeper_cache_records
caches records only. It does not cache attached files. If an action attempts to retrieve an attached file from a record that came from the cache, an API call will be made to download the file.
Use templating to set the attributes in other actions. For example cache: "{{ my_records.cache }}"
keeper_cache_records
requires the keeper_record_cache_secret
to be set. This can be done in the host, group, task variables, or generated in a task and then set as a fact (variable). In the example above, the keeper_password
action is used to generate a password which is then stored as keeper_record_cache_secret
. The no_log
attribute is set to True to prevent the secret from being logged.
The cache will not update. The cache will not contain records created or updated after it has been generated. To get new records or changes in the cache, keeper_cache_records
will need to be called again.
uids
- A list of Keeper Vault record UID.
titles
- A list of titles of Keeper Vault records.
The attributes uids
and titles
can be used at the same time. At least one of them needs to be set.
keeper_copy
The plugin keeper_copy
is an extension of the built-in copy plugin. Example:
---
- name: Keeper Copy
hosts: my_hosts
# Include line below if installed via ansible galaxy or use long plugin names.
# collections:
# - keepersecurity.keeper_secrets_manager
tasks:
- name: Copy a password.
keeper_copy:
uid: RECORD UID
field: password
dest: /tmp/my_password
mode: "0600"
- name: Copy a file
keeper_copy:
uid: RECORD UID
file: my_cert_file.crt
dest: /etc/special.crt
owner: root
group: root
mode: "0644"
backup: yes
In the examples, a password will be copied from the Keeper vault record and stored in the file /tmp/my_password
on the remote system. It will use the Ansbile built-in copy plugin's mode attributes to changed the permissions of the file.
The last task example from above, the file "my_cert_file.crt" will be coped from the Keeper vault record and stored at the location "/tmp/special.crt". Several of the built-in copy plugin functions will be applied to the file.
uid
- A Keeper Vault record UID.
title
- Title of a Keeper Vault records.
notation
- Use Keeper Notation to get the field from a record.
The attributes uids
and titles
can be used at the same time. At least one of them needs to be set.
cache
- The record cache from the keeper_cache_records
action.
field
- Get the content from the standard Keeper Vault record.
custom_field
- Get the content from the custom Keeper Vault record.
file
- Get the content from the files attach to the Keeper Vault record by file title.
array_index
- Defaults to 0. If the field value contains multiple values, this attribute will allow you to select which item to return. The first item will have the array_index
of 0, and the next will be 1, etc.
value_key
- If the field value is a complex object, this will allow you to select the key of the key/value pair to return.
Additional optional attributes are the same as the built-in copy plugin attributes. The attributes src, remote_src
, and content
are not allowed and will be ignored.
keeper_get
The plugin keeper_get
will retrieve a field or file from a Keeper vault record. Example:
---
- name: Keeper Get
hosts: my_hosts
# Include line below if installed via ansible galaxy or use long plugin names.
# collections:
# - keepersecurity.keeper_secrets_manager
tasks:
- name: Get login name. Loading record from Keeper Vault.
keeper_get:
uid: RECORD UID
field: login
register: my_login
- name: Print login name
debug:
var: my_login.value
verbosity: 0
- name: Make a sudoer
copy:
dest: "/etc/sudoers.d/{{ my_login.value }}"
content: |
# Auto added by Ansible
{{ my_login.value }} ALL=(ALL:ALL) ALL
The keeper_get
plugin returns a dictionary. The key "value" in the dictionary will contain the desired field or file content. This plugin is normally paired with the Ansible register
instruction and the returned value is stored in memory so it can be accessed by other tasks.
In the example above, a record containing user's login name is retrieved. The login name is then stored under the name my_login. The second task will print the login name to your console for debug purposes. The third task will add a sudoer file for the login name with ability to execute all applications.
uid
- A Keeper Vault record UID.
title
- Title of a Keeper Vault records.
notation
- Use Keeper Notation to get the field from a record.
The attributes uids
and titles
can be used at the same time. At least one of them needs to be set.
cache
- The record cache from the keeper_cache_records
action.
field
- Get the value from the standard Keeper Vault record.
custom_field
- Get the value from the custom Keeper Vault record.
file
- Get the value from the files attach to the Keeper Vault record by file title.
allow_array
- By default is False. If set to True, an array of values will be returned. This is needed if the field contains multiple values such as Phone numbers. If True, array_index
and value_key
will be ignored.
array_index
- Defaults to 0. If the field value contains multiple values, this attribute will allow you to select which item to return. The first item will have the array_index
of 0, and the next will be 1, etc.
value_key
- If the field value is a complex object, this will allow you to select the key of the key/value pair to return.
keeper_get_record
The plugin keeper_get_record
will retrieve all the fields in the record and return them in a dictionary. Example:
---
- name: Keeper Get Record
hosts: my_hosts
# Include line below if installed via ansible galaxy or use long plugin names.
# collections:
# - keepersecurity.keeper_secrets_manager
tasks:
- name: Get a record from the vault.
keeper_get_record:
uid: RECORD UID
allow:
- login
- password
register: my_record
- name: Print login name
debug:
var: my_record.record.login[0]
verbosity: 0
The keeper_get_record
plugin returns a dictionary. The keys of the dictionary are the normalized field labels, or types. The keys will be alphanumeric and the underscore characters. If there are duplicate key, a number will be appended to the end of the key.
In the example above, a record is retrieved using the UID. The fields will be stored in a dictionary, in memory, using the register
instruction. Since the allow
attribute is used, the dictionary will only contain login and password .The field values can be accessed using the normal the templating in Ansible. The values will be stored as arrays. This is due to some fields returning arrays of the values, such as phone
.
uid
- A Keeper Vault record UID.
title
- Title of a Keeper Vault records.
Either uids
and titles
is required.
cache
- The record cache from the keeper_cache_records
action.
allow
- A list of keys to allow. If set, if the key is not in the list, it will not be inclued in the dictionary.
keeper_set
The keeper_set
plugin has the ability to write a value into an existing Keeper vault record. Example:
___
- name: Keeper Set
hosts: my_hosts
# Include line below if installed via ansible galaxy or use long plugin names.
# collections:
# - keepersecurity.keeper_secrets_manager
tasks:
- name: Get login name of new user.
keeper_get:
uid: RECORD UID
field: login
register: my_login
- name: Add new user of remote machine.
user:
name: "{{ my_login.value }}"
comment: "User {{ my_login.value }}"
register: new_user
- name: Update record with user's home directory in the Keeper Vault
keeper_set:
uid: RECORD UID
custom_field: my_home_directory
value: "{{ new_user.home }}"
In this example, a new user's login name is retreived. The new user is created on the remote system with the login name from the record. The home directory on the remote machine is then updated in the record.
The keeper_set
action does not have the ability of set individual values of an array or complex values. It simplely replaces the existing value with a new value. For example, for a Hostname and Port field type there is no way to just update the port. The entire value including the hostName needs to be included in the object value.
keeper_set
will set the update the record in the vault. It will not update the cache, if used. To update the cache, a step will need to run the keeper_cache_records
action again with the UID or Title of the record that was updated.
uid
- A Keeper Vault record UID.
title
- Title of a Keeper Vault records.
notation
- Use Keeper Notation to get the field from a record.
The attributes uids
and titles
can be used at the same time. At least one of them needs to be set.
cache
- The record cache. Used for getting the record, will not update the cache.
field
- Update the existing standard Keeper Vault record field.
custom_field
- Update the existing custom Keeper Vault record field.
keeper_create
The keeper_create
plugin creates a record in the Keeper vault. See the Field/Record Types document for available record types, and the field types used to build the records. The action plugin will return the record_uid
upon successful creation.
Example:
---
- name: Keeper Create
hosts: my_hosts
tasks:
- name: "Create A Record"
keeper_create:
shared_folder_uid: XXXXXX
record_type: login
generate_password: True
password_complexity:
length: 64
allow_symbols: False
title: "My New Record"
note: "Created by Ansible"
fields:
- type: login
value: johndoe@localhost
- type: url
value: https://localhost
custom_fields:
- type: text
label: "My Custom Label"
value: "My custom value"
register: my_new_record
- name: "New Record UID"
debug:
msg: "New record uid is {{ my_new_record.record_uid }}"
The following fields are required.
shared_folder_uid
- The Shared Folder UID from the vault. The record will be created within this folder.
record_type
- The type of record. This will included all the default record types. If the keeper_record_types
is set, those record types can be used.
title
- The title of record
The following fields are optional.
generate_password
- If set to true, any password field where the password has not been set, will be populated with a random generated password.
password_complexity
- Sets the complexity of the password. All parameters of password_complexity are optional.
length
- Length of password. Defaults to 64.
allow_lowercase
- Defaults to True. If set to False, no lowercase letters will be used.
allow_uppercase
- Defaults to True. If set to False, no uppercase letters will be used.
allow_digits
- Defaults to True. If set to False, no digits will be used.
allow_symbols
- Defaults to True. If set to False, no symbols will be used.
filter_characters
- A list of characters to exclude from the password. This allows to remove characters a services will reject. For example, '%' in SQL. If not set, the password will not be filtered.
notes
- Attach a note to the record.
Based on the Record Types, certain fields maybe required. Custom fields are optional. Both fields
and custom_fields
are an array of values.
fields/custom_fields
type
- Field type
label
- Label to display with the value.
value
- Field value. Can be a string or dictionary based on field type.
To create a record with a particular Custom Record Type, first export the custom record types using Keeper Commander and the record-type-info
command. KSM does not sync down the custom type definitions, so this must be added directly to the playbook as a variable.
Keeper Commander will output a JSON Array ("content"). Only the JSON object is required.
Example:
My Vault> record-type-info --format json -lr "My Custom"
[
{
"recordTypeId": 18,
"content": "{\"$id\":\"My Custom\",\"categories\":[\"login\"],
\"description\":\"SSH key template\",\"fields\":[
{\"$ref\":\"login\"},
{\"$ref\":\"keyPair\"},
{\"$ref\":\"password\",\"label\":\"passphrase\"},
{\"$ref\":\"host\"},
{\"$ref\":\"fileRef\"}]}"
}
]
In your Ansible YAML file, add the value of the "content" object to the variable key called keeper_record_types
. The variable is an array, and the JSON is to be treated as a string value. The pipe, after the array item, will treat the following JSON as a string. The variable will accept multiple record types.
Example:
- name: My Playbook
collections:
- keepersecurity.keeper_secrets_manager
hosts: "my_hosts"
vars:
keeper_record_types:
- |
{
"recordTypeId": 35,
"content": "{\"$id\":\"My Custom\",\"fields\":[{\"$ref\":\"fileRef\",\"label\":\"File or Photo\"},{\"$ref\":\"login\",\"label\":\"Login\"},{\"$ref\":\"password\",\"label\":\"Password\",\"required\":true,\"enforceGeneration\":false,\"privacyScreen\":false,\"complexity\":{\"length\":8,\"caps\":0,\"lowercase\":0,\"digits\":0,\"special\":0}},{\"$ref\":\"text\",\"label\":\"System Login\",\"required\":true},{\"$ref\":\"secret\",\"label\":\"System Password / Pin Code\"},{\"$ref\":\"url\",\"label\":\"Keeper VPN Wiki\",\"required\":true},{\"$ref\":\"url\",\"label\":\"Password Best Practices FAQ's and Tips\",\"required\":true}]}"
}
To check if this worked, the keeper_info
plugin can be used to show which record types are available.
When creating a record of a particular custom type, the Ansible task will reference the record type name in the record_type
parameter as seen below:
- name: "Create A Custom Record"
keeper_create:
shared_folder_uid: XXXXXXXXXXXX
record_type: "My Custom"
title: "Example Custom Record"
note: "Created by Ansible"
fields:
- type: login
label: Login
value: johndoe@localhost
- type: password
label: Password
value: "ABC123"
register: my_new_record
keeper_remove
v1.2.1 Released on: 10/27/2023
The keeper_remove plugin will remove a record from the Keeper vault.
---
- name: Keeper Remove
hosts: my_hosts
tasks:
- name: Remove by UID
keeper_remove:
uid: RECORD UID
- name: Remove by Title
keeper_remove:
title: RECORD TITLE
uid
- A Keeper Vault record UID.
title
- Title of a Keeper Vault records.
The attributes uid
and title
cannot be used at the same time. At least one of them needs to be set.
cache
- The record cache from the keeper_cache_records
action. The record will not be removed from the cache. The cache will be used for looking up the record title.
keeper_password
The keeper_password
plugin will generate a random password. The action plugin will return the password
.
Example:
---
- name: Keeper Password
hosts: my_hosts
tasks:
- name: Generate a long password
keeper_password:
length: 128
register: long_password
- name: Show long password
debug:
msg: "Long password {{ long_password.password }}"
- name: Generate an all digit password
keeper_password:
length: 32
allow_lowercase: False
allow_uppercase: False
allow_symbols: False
register: digit_password
- name: Show digit password
debug:
msg: "Digit password {{ digit_password.password }}"
- name: Generate a PostgreSQL password (no % character)
keeper_password:
length: 64
filter_characters:
- "%"
register: pg_password
- name: Show PostgreSQL password
debug:
msg: "PG password {{ pg_password.password }}"
All parameters are optional. If no parameters are set, the defaults will be used.
length
- Length of password. Defaults to 64.
allow_lowercase
- Defaults to True. If set to False, no lowercase letters will be used.
allow_uppercase
- Defaults to True. If set to False, no uppercase letters will be used.
allow_digits
- Defaults to True. If set to False, no digits will be used.
allow_symbols
- Defaults to True. If set to False, no symbols will be used.
filter_characters
- A list of characters to exclude from the password. This allows to remove characters a services will reject. For example, '%' in SQL. If not set, the password will not be filtered.
Based of record types, certain fields maybe required. Custom fields are optional. Both fields and custom_field are an array of values.
keeper_lookup
The keeper_lookup
plugin retrieves a field from the Keeper vault record and inserts the value into a text string. Example:
---
- name: Keeper Lookup
hosts: my_hosts
tasks:
- name: Write login to file. Get record from the Keeper Vault
copy:
content: "My login is {{ lookup('keeper', uid='RECORD UID', field='login') }}"
dest: "/tmp/my_login.txt"
no_log: True
- name: Using the array_index and value_key on complex values
debug:
msg: >-
Second phone number is
{{ lookup('keeper', uid='RECORD UID', custom_field='My Phone', array_index=1, value_key='number') }}
In the example above, the first task the content of a file is created by templating the login name of a user from a Keeper record.
The second task displays as debug the second phone of number from a field with a complex value using the array_index
and value_key
task attributes. An array_index
starts at 0, the next item in the araray will be 1, the next is 2, a so on. The value_key
is the name of key in a key/pair dictionary.
uid
- A Keeper Vault record UID.
title
- Title of a Keeper Vault records.
notation
- Use Keeper Notation to get the field from a record.
The attributes uids
and titles
can be used at the same time. At least one of them needs to be set.
cache
- The record cache. Used for getting multiple records, will not update the cache.
field
- Update the existing standard Keeper Vault record field.
custom_field
- Update the existing custom Keeper Vault record field.
file
- Get the value from the files attach to the Keeper Vault record by file title.
allow_array
- By default is False. If set to True, an array of values will be returned. This is needed if the field contains multiple values such as Phone numbers. If True, array_index
and value_key
will be ignored.
array_index
- Defaults to 0. If the field value contains multiple values, this attribute will allow you to select which item to return. The first item will have the array_index
of 0, and the next will be 1, etc.
value_key
- If the field value is a complex object, this will allow you to select the key of the key/value pair to return.
To avoid leaking secret values when using the lookup plugin, add 'no_log: True'
to the task. The stdout information will not be logged if the value is True.
If the plugin was installed by Ansible Galaxy the longer name is required for the lookup plugin (i.e. keepersecurity.keeper_secrets_manager.keeper). Listing collections appears not to work with lookup plugins.
To find out what fields and custom fields are available for a specific vault secret, use the Keeper Secrets Manager CLI "ksm secret get -u XXXX
" command. More info here.
keeper_init
The keeper_init
plugin initialize a configuration from a one time access token. This is similar to the keeper_ansible --keeper_token
command. The plugin accepts the following options.
token
- The one time access token. It's best to template this value and pass in the value.
filename
- The configuration file name to generate with config values. If not included, the configuration will not be created.
show_config
- A flag to indicate if the configuration values should be returned in the task log. By default this is False
. Only set to True if you are unable to generate the configuration via other methods or do not have access to a generated configuration file. If True, the configuration will be logged. This might not be a problem if running the playbook via the command line, however if running via Ansible Tower to will be log file which is retained.
---
- name: Keeper Lookup
hosts: localhost
connection: local
tasks:
- name: Init the one time access token
keeper_init:
token: "{{ keeper_token }}"
filename: "{{ keeper_config_file }}"
show_config: False
It's best not to hard code the token into the playbook since it's only good once. The token and the configuration file name can be passed into the playbook using the extra vars
.
$ ansible-playbook my_init_playbook.yml \
-e "keeper_token=US:XXX" \
-e "keeper_config_file=my_keeper_config.yml"
The above will generate a file similar to the one below. The content of the file can be copied into a configuration file used by ansible, and optionally encrypted by ansible-vault
.
keeper_app_key: +U5Ja ... 5FmXymVI=
keeper_client_id: Fokc ... WBdUPxPlBwzAKlMUgFZHqLg==
keeper_hostname: US
keeper_private_key: MIGHA ... yA7Oy
keeper_server_public_key_id: '10'
If the Keeper Secret Manager plugins were installed via Ansible Galaxy, a role called keeper_init_token
was installed to initialize the one-time access token. This role can be used in a playbook.
---
- name: Initialize One Time Access Token
hosts: localhost
connection: local
collections: keepersecurity.keeper_secrets_manager
roles:
- keeper_init_token
The role will use the following options set via extra variables.
keeper_token
- Required one-time access token.
keeper_config_file
- Generate a file containing the configuration. If not set, no file will be created.
keeper_show_config
= Default False. If set to True, it will show the config in the log if verbosity is enabled.
Either keeper_config_file
or keeper_show_config
should be used, else the token will initialize and you will not be able to view the resulting configuration.
The keeper_info action will display information about the Keeper ansible plugin. The results include a list of record types, field types, and versions of Python modules. In order to see the results, the verbosity level needed to be set at 1 or higher.
---
- name: Keeper Info
hosts: localhost
connection: local
tasks:
- name: Display Keeper Info
keeper_info:
This can be used to verify custom record types are being picked up by the plugins.
keeper_cleanup
The keeper_cleanup
plugin is used to clean up any files created by the keeper plugins. This is mainly used to delete a cache file, if you are using it. Disaster Recovey cache files are used when there are network problems as a fall back to get records. If you are running Ansible secret environment, there is no need to remove the Disaster Recovey cache. However this plugin gives you the ability to do so.
- name: Keeper Lookup
hosts: localhost
connection: local
vars:
keeper_use_cache: True
tasks:
... bunch of tasks
- name: Remove the cache file
keeper_cleanup:
keeper_redact
The keeper_redact
stdout callback plugin is used to redact secrets from the standard out logs. This will work for the keeper_redact
stdout callback plugin is used to redact secrets from the standard out logs. This will work for the keeper_copy
and keeper_get
plugins. It will not redact secret values for keeper_lookup
. For keeper_lookup
, use the no_log: True
directive.
To use the keeper_redact
plugin, enable it in your ansible.cfg.
[defaults]
stdout_callback = keeper_redact
# Use long name if install via Ansible Galaxy
# stdout_callback = keepersecurity.keeper_secrets_manager.keeper_redact
For example, the following task would return all the phone numbers in the custom field MyPhoneNumbers and place them into the variable phone_numbers.
- name: "Get Phone Numbers"
keeper_get:
uid: OlLZ6JLjnyMOS3CiIPHBjw
custom_field: MyPhoneNumbers
allow_array: True
register: phone_numbers
If the playbook was run with any verbosity, the values being placed into the variable would be displayed. This would leak the secrets to the log. If the keeper_redact
stdout callback plugin is enabled, the values in the log would be redacted.
TASK [Get Phone Numbers] **************************************************
ok: [my_server] => {
"value": [
{
"number": "****",
"type": "****",
"ext": "****"
},
{
"region": "****",
"number": "****",
"ext": "****",
"type": "****"
}
],
"changed": false
}
You can use the Keeper Secret Manager CLI ("ksm") to provide the decryption password for your Ansible vaults. This is done using the ANSIBLE_VAULT_PASSWORD_FILE environment variable or the vault_password_file in the ansible.cfg field to specify an executable file that will return a password.
A executable shell script can be created that returns the password using the "ksm" secret notation (learn more about ksm secret notation). For example, the below script will output a specific secret password for the given Record UID:
#!/bin/sh
ksm secret notation keeper://XXXX/field/password
Replace XXXX with the Vault Record UID. Running this script simply outputs the secret password.
To override the environmental variable "ANSIBLE_VAULT_PASSWORD_FILE", execute the following, replacing /path/to/script with the location of the above script.
$ ANSIBLE_VAULT_PASSWORD_FILE=/path/to/script.sh ansible-playbook playbook_with_vault.yml
Now, when Ansible needs to decrypt any vaults used by playbook_with_vault.yml
, it will execute that shell script. The shell script will retrieve the password from the Keeper Vault.
By default, the Ansible plugins will only display errors. If you use the Ansible verbosity level, different SDK logging will be displayed. An Ansible verbosity level of -v
will display any SDK messages INFO and higher, while a verbosity level of -vvv
will display any SDK messages DEBUG and higher.
This appears to be specific to Ansible running on MacOS. While running a playbook you may get the following error:
objc[6763]: +[__NSPlaceholderDate initialize] may have been in progress in
another thread when fork() was called. We cannot safely call it or ignore
it in the fork() child process. Crashing instead. Set a breakpoint on
objc_initializeAfterForkError to debug
This is known problem with Ansible. This can be fixed with the following environmental variable.
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ansible-playbook ...
TASK [Copy file from Keeper into the file] ********************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Exception: Keeper Ansible error: There is no config file and the Ansible variable contain no config keys. Will not be able to connect to the Keeper server.
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
A collection of Ansible plugins that interact with your Keeper account and can be used in your Ansible Tower automations.
Store Secrets Manager configurations securely in Ansible Tower
Use Ansible Tower to manager and launch Ansible projects utilizing the Secrets Manager Ansible plugin which features:
Retrieving secrets from the Keeper vault to use in Ansible Playbooks
Updating the value of secrets in the Keeper Vault from Ansible
Copying files from the Keeper Vault
The first step in using Ansible Tower with Keeper Secrets Manager is to get and initialize a Base64 configuration. The Secret Manager Configuration document will explain how to get a configuration using the Keeper Secret Manager CLI or Commander CLI.
Using Commander CLI, add a new device can generate a Base64 configuration without using a one time access token.
keeper secrets-manager client add --app MyApp --config-init b64
The Keeper Secrets Manager CLI requires a one-time access token. This can be obtained from the Web Vault by adding a new device to an application.
$ ksm init default US:XXXX
Another way using the keeper_init_token
role included in the Keeper Secrets Manager collection, which can used after Ansible Tower is setup. An example will appear at the end of this document.
The Base64 configuration can be added to the inventories, hosts, or templates variables sections. It can also be added to the playbook repository as an Ansible secret. The variable name is keeper_config.
With the Base64 KSM configuration we need to create a vault credential. Under the Resources menu, select Credentials and click Add.
Give your Vault Credential a name, select Vault from the Credential Type drop-down, type in the password that was used to encrypt the secrets.yml
file into the Vault Password field, then click Save.
The credential will be used when the Template is setup.
To use the Keeper Secrets Manager plugins in Ansible Tower an Execution Environment containing the Keeper Secrets Manager SDK is required. This SDK is included in the Docker image keeper/keeper-secrets-manager-tower-ee
. In your instance of Ansible Tower, select Execution Environment in the Administration menu, then click Add.
The Image value is docker.io/keeper/keeper-secrets-manager-tower-ee:latest
or docker.io/keeper/keeper-secrets-manager-tower-ee:<tag>
if there is a specific tag version.
The value for Pull should be set to Always pull container before running is you are using the latest tag. If you pin the tag to a specific tag version of keeper/keeper-secrets-manager-tower-ee
then set the value to Only pull the image if not present before running.
To use the Keeper Secrets Manager plugins in your projects, create a collections
directory in your source repository, if one does not already exists. Then create, or add to, the file requirements.yml
the following value.
---
collections:
- keepersecurity.keeper_secrets_manager
The Base64 KSM configuration can be stored in numerous places inside of Ansible Tower like in the inventories, hosts, and templates. The configuration is encrypted when stored in these locations.
For this project, the KSM configuration will be stored as an encrypted secret in the source repository. Add a YAML file called secrets.yml
in a directory called defaults
located in the root directory of the repository.
In this file add a key called keeper_config
with the Base64 configuration as it's value.
---
keeper_config: ewogICAgImNsaWVudElk ... Y0tleUlkIjogIjEwIgp9
Then encrypt the secrets.yml
file using ansible-vault
.
Remember the password, it will be needed in Tower for a Vault Credential.
$ ansible-vault encrypt secret.yml
New Vault password:
Confirm New Vault password:
Encryption successful
At this point, if you look at your secrets.yml file, it should be encrypted.
The directory structure should look like the following.
$ tree
.
├── collections
│ └── requirements.yml
├── defaults
│ └── secrets.yml
├── playbook_1.yml
└── playbook_2.yml
For our playbooks, the Keeper Secrets Manager collection is added to the playbook collections. The first task is to include the secrets.yml
using the built-in action include_vars
. That task also includes no_log: True
to prevent the KSM configuration from being logged. This task needs to be performed before any of the plugins from the Keeper Secrets Manager collection.
---
- name: Playbook One
hosts: all
collections:
- keepersecurity.keeper_secrets_manager
tasks:
- include_vars:
file: "defaults/secrets.yml"
no_log: True
- name: "Make User SSH Directory, if does not exists"
file:
path: "/home/user/.ssh"
state: directory
recurse: yes
- name: "Copy SSH Keys"
keeper_copy:
notation: "OlLZ6JLjnyMOS3CiIPHBjw/field/keyPair[{{ item.notation_key }}]"
dest: "/home/user/.ssh/{{ item.filename }}"
mode: "0600"
loop:
- { notation_key: "privateKey", filename: "id_rsa" }
- { notation_key: "publicKey", filename: "id_rsa.pub" }
Once you have added the collection to your source repository, a new Project can be created.
Make sure to select the Execution Environment that you create that uses the keeper/keeper-secrets-manager-tower-ee
image.
In the example above, the source repository was Git with the appropriate details. Your company may use a different source control.
After it is saved, sync the playbooks to your Ansible Tower instance.
In your instance of Ansible Tower, select Templates in the Resources menu, then click Add.
For Projects select the project that was just created that contain the playbooks. For Execution Environment select the execution environment what contains the Keeper Secrets Manager Tower EE docker image. For Playbook select a playbook from your source repository.
For Credentials select the Vault credential that will be used to decrypt the secrets.yml
file in the Project's source repository. You can also select the credential to use for connection to your inventory servers.
Finish by clicking the Save button at the bottom of the page.
The last step is to launch a template to create a job.
The include_vars
task will import the KSM Base64 Configuration and decrypt it. The no_log: True
will hide the configuration from the log. If it is not included, the configuration will be logged and viewable by anyone who has access to Ansible Tower.
With the configuration now in the available variables, the keeper_copy
action can retrieve the public and private SSH key from the Keeper Vault and copy them into location on the remote machine.
Protect your AWS Access Keys with Keeper Secrets Manager
By default, the AWS CLI uses credentials stored in plaintext in ~/.aws/credentials
. With this credential process, you can now use the Keeper Vault to store your AWS credentials, removing the need to have them on disk.
Instead, AWS will use this executable to securely fetch your AWS credential from your Vault using the Keeper Secrets Manager (KSM).
Use a vaulted AWS Access Key to authenticate to the AWS CLI.
In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper account
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with an Access Key shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
This integration only accepts JSON format configurations
The AWS CLI v2 installed
The first step in the setup of the integration is to add you AWS Access Key ID
and your Secret Access Key
to a record in your Vault. There is no built-in record type for this kind of secret; however, you can create a custom record for this purpose alone.
In order to create new custom Record Types, the user must be in an Administrative role with the "Manage Record Types in Vault" permission activated.
Note: Field names are case-sensitive.
Once you have created your custom field, you can now use it to create a record for your AWS Access Key. This record should be stored in a shared folder that your KSM application has permission to access.
Once safely stored, you can delete the Access Key credentials from your AWS credential file.
The integration expects a KSM Application Configuration file at either .config/keeper/aws-credential-process.json
or aws-credential-process.json
relative to the user's home directory. It must have access to a Shared Folder containing the required AWS Access key.
For help in obtaining a KSM configuration in JSON format, follow these instructions.
After creating a new device get corresponding config.json
and copy it into user's home folder as aws-credential-process.json
Download the latest version of the keeper-aws-credential-process
executable from the GitHub releases page and store that in a convenient location.
Now in your AWS configuration file, which is usually located at ~/.aws/config
, add the following line to any profile you are using via the CLI.
# Add the UID for your AWS Access Key
#credential_process = /path/to/keeper-aws-credential-process --uid <Record UID>
credential_process = /opt/keeper-aws-credential-process-v0.1.1_linux_amd64 --uid <Record UID>
Make sure there's no residual aws cli configuration left on the machine which may be picked up automatically or on credential process misconfiguration.
Once configured as above, the AWS CLI will automatically fetch your authentication credential from the Keeper Vault. You can test that it works by using any CLI command in which you have an appropriate IAM role for, such as:
# List all s3 buckets
aws s3 ls
If the command completes without error, congratulations, you are now fully set up.
This Credential Process is open source and can be found on GitHub. If you need to report a bug or would like to request a feature to support more authentication use cases, please create a GitHub issue.
Sync secrets from the Keeper Vault with AWS Secrets Manager
The Keeper Secrets Manager CLI tool sync
command allows you to push secrets from the Keeper Vault to a target AWS Secrets Manager account, overwriting the existing values in the target location. This allows the Keeper Vault to be the single source of truth for any services or scripts in AWS that utilize AWS Secrets Manager.
Use secrets from the Keeper Vault as the source of truth for AWS Secrets Manager
Seamlessly start using secrets from the Keeper Vault with your existing AWS scripts and services
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper subscription
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An AWS account with AWS Secrets Manager, and the ability to create IAM security credentials
To configure the KSM CLI tool, a profile needs to be created with the Keeper Secrets Manager One Time Access Token.
The simplest way to do this is to initialize the default profile with the following command:
ksm profile init <TOKEN>
For information on creating multiple profiles and other options, see the profile documentation
To use the KSM sync to AWS, AWS Secrets Manager requires standard IAM security credentials with SecretsManagerReadWrite
enabled for the entire vault or on individual keys to sync.
arn:aws:iam::aws:policy/SecretsManagerReadWrite
See the Amazon instructions for creating Access Keys:
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
The KSM CLI needs the credentials for the AWS account to set secrets. These credentials are stored in a Keeper record which the CLI tool can access using Keeper Secrets Manager.
Record fields with the following labels are required on the credentials record:
"AWS Access Key ID" "AWS Secret Access Key" "AWS Region Name"
A custom record type can be created with the required fields, which makes it easy and clean to create a record.
To create a custom record type, go to the "Custom Record Types" tab in the Keeper Vault and hit "Create Type". Create a new record type with hidden fields that have the correct field label, then click "Publish" to create the new record type.
Then simply create a new record of the AWS Credentials type and enter the details into the corresponding fields.
Make sure this new record is moved to a Shared Folder that is associated with your Secrets Manager application.
To create a credentials record without creating a new record type, the required fields can be added as custom fields to a standard record.
Create a new record of any type, then add Custom Fields of the 'Hidden Field' type for each required AWS field. Click "Edit Label" to change the labels to the corresponding field name.
Then fill in each custom field and hit "Save" to save the record.
The KSM CLI sync
command identifies which values to set using mappings that are defined on the command call. For each mapping passed to the command, a value with the given name will be populated with the given value from the Keeper Vault.
These mappings follow this format:
--map "VALUE KEY" "KEEPER NOTATION"
VALUE KEY
is the key name that the value will be assigned in AWS Secrets Manager
KEEPER NOTATION
is a Keeper notation query of a value from a keeper record to set to the key
Keeper notation is a query notation used by Keeper Secrets Manager to identify specific record values. The notation follows the general format of: UID/
[field|custom_field]/fieldname
for example: ae3d[...]d22e/field/password
See the Keeper Notation documentation for more information
Full Mapping Example:
--map "MySQL_PWD" "jd3[...]i-fd/field/password"
Multiple mappings can be added to a single sync
command
--map "MySQL_PWD" "jd3[...]i-fd/field/password" --map "MySQL_Login" "jd3[...]i-fd/field/login"
Ensure that the records referenced by the Keeper Notation queries are in a shared folder that is shared with your Secrets Manager application
KSM sync is now ready to run
To run the sync, use the KSM CLI sync
command with the credentials record and value mapping.
Put together the KSM sync command with the AWS type. The format looks like the following:
ksm sync --type aws --credentials [UID] --map [...] --map [...]
The sync command supports running a dry-run which will identify all changes that will be made to your AWS Secrets Manager values without actually pushing the values or making changes. Use this to make sure your mapping queries are constructed properly.
ksm sync --type aws --credentials [UID] --map [...] --map [...] --dry-run
When ready, run the sync command without the dry-run option. This will push values from your Keeper Vault to AWS Secrets Manager
ksm sync --type aws --credentials [UID] -m [...] -m [...]
Protect Secrets Manager connection details with AWS KMS
Keeper Secrets Manager integrates with AWS KMS in order to provide encryption for Keeper Secrets Manager configuration files. With this integration, you can protect connection details on your machine while taking advantage of Keeper's zero-knowledge encryption of all your secret credentials.
Encrypt and Decrypt your Keeper Secrets Manager configuration files with AWS KMS
Protect against unauthorized access to your Secrets Manager connections
Requires only minor changes to code for immediate protection. Works with all Keeper Secrets Manager SDK functionality
Supports the Java Secrets Manager SDK
Supports Java 11 and above
Supports the JavaScript Secrets Manager SDK
Requires aws-sdk/client-kms package
Supports the Python Secrets Manager SDK
Requires boto3 package
Supports the .Net Secrets Manager SDK
Requires AWSSDK.KeyManagementService
Supports the GoLang Secrets Manager SDK
Requires aws-sdk-v2
Setting up project using Gradle or Maven
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("com.keepersecurity.secrets-manager:aws:1.0.0")
implementation("com.keepersecurity.secrets-manager:core:17.0.0")
implementation ("software.amazon.awssdk:kms:2.20.28")
implementation ("software.amazon.awssdk:auth:2.20.28")
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
implementation("com.fasterxml.jackson.core:jackson-core:2.18.2")
implementation("com.google.code.gson:gson:2.12.1")
implementation("org.slf4j:slf4j-api:1.7.32"){
exclude("org.slf4j:slf4j-log4j12")
}
implementation("ch.qos.logback:logback-classic:1.2.6")
implementation("ch.qos.logback:logback-core:1.2.6")
implementation("org.bouncycastle:bc-fips:1.0.2.4")
}
Maven
<!-- KMS-core -->
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>aws</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>core</artifactId>
<version>17.0.0</version>
</dependency>
<!-- aws-kms -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>kms</artifactId>
<version>2.20.28</version>
</dependency>
<!-- aws-auth -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>auth</artifactId>
<version>2.20.28</version>
</dependency>
<!--gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.12.1</version>
</dependency>
<!--jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!--jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!-- slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
<scope>runtime</scope>
</dependency>
<!-- logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
<scope>compile</scope>
</dependency>
<!-- logback-core -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.6</version>
<scope>compile</scope>
</dependency>
<!-- bc-fips -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>1.0.2.4</version>
</dependency>
The Secrets Manager AWS Key Management Service Integration can be installed using npm
npm install @keeper-security/secrets-manager-aws
The Secrets Manager HSM modules are located in the Keeper Secrets Manager storage module which can be installed using pip
pip3 install keeper-secrets-manager-storage
boto3 is a prerequisite for the AWS KSM integration. Install it to your machine using pip.
pip install boto3
The Secrets Manager AWS Key Management Service Integration can be installed using
dotnet add package Keeper.SecretsManager.AWSKeyManagement
The Secrets Manager AWS Key Management Service Integration can be installed using
go get github.com/keeper-security/secrets-manager-go/integrations/aws
By default the boto3 library will utilize the default connection session setup with the AWS CLI with the aws configure
command. If you would like to specify the connection details, the two configuration files located at ~/.aws/config
and ~/.aws/credentials
can be manually edited.
Alternatively, configuration variables can be provided explicitly as an access key using the AwsSessionConfig
data class and providing aws_access_key_id
, aws_secret_access_key
and aws_session_token
variables.
Once AWS connection has been configured, You can fetch the Key to encrypt / decrypt KSM configuration using integration and you need to tell the Secrets Manager SDK to utilize the KMS as storage. Using Specified Connection credentials
To do this, use AwsKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, AwsSessionConfig, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import com.keepersecurity.secretmanager.aws.kms.AwsKeyValueStorage;
import com.keepersecurity.secretmanager.aws.kms.AwsSessionConfig;
import com.keepersecurity.secretsManager.core.InMemoryStorage;
import com.keepersecurity.secretsManager.core.SecretsManager;
import com.keepersecurity.secretsManager.core.SecretsManagerOptions;
import static com.keepersecurity.secretsManager.core.SecretsManager.initializeStorage;
import software.amazon.awssdk.regions.Region;
import java.security.Security;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
class Test {
public static void main(String args[]){
String keyId = "<Key ID>";
String awsAccessKeyId = "<AWS Access ID>";
String awsSecretAccessKey = "<AWS Secret>";
String oneTimeToken = "[One Time Token]";
Region region = Region.<cloud-region>;
String profile = null OR "DEFAULT"; //set profile (ex. DEFUALT/UAT/PROD) if ~/.aws/config is set
String configFileLocation = "client_config_test.json";
try{
//set AWS configuration, It can be null if profile is set for aws credentials
AwsSessionConfig sessionConfig = new AwsSessionConfig(awsAccessKeyId, awsSecretAccessKey);
//Get Storage
AwsKeyValueStorage awskvstorage = new AwsKeyValueStorage(keyId, configFileLocation, profile, null, region);
initializeStorage(awskvstorage, oneTimeToken);
SecretsManagerOptions options = new SecretsManagerOptions(awskvstorage);
//getSecrets(OPTIONS);
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
To do this, use AWSKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, AWS Session credentials - AWSSessionConfig
, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
import { AWSKeyValueStorage, AWSSessionConfig, LoggerLogLevelOptions } from "@keeper-security/secrets-manager-aws";
import { initializeStorage, getSecrets } from "@keeper-security/secrets-manager-core";
const getKeeperRecordsAWS = async () => {
const accessKeyId = "<YOUR AWS ACCESS KEY>>";
const secretAccessKey = "<YOUR AWS SECRET_ACCESS_KEY>";
const regionName = "<YOUR AWS REGION>";
const logLevel = LoggerLogLevelOptions.Debug;
const configPath = "client-config-path.json";
const awsSessionConfig = new AWSSessionConfig(accessKeyId, secretAccessKey, regionName);
const keyId = 'arn:aws:kms:ap-south-1:<accountName>:key/<keyId>';
const storage = await new AWSKeyValueStorage(keyId, configPath, awsSessionConfig, logLevel).init();
const oneTimeToken = "<one time token>";
await initializeStorage(storage, oneTimeToken);
const { records } = await getSecrets({ storage: storage });
const firstRecord = records[0]
const firstRecordPassword = firstRecord.data.fields.find(x => x.type === 'password')
console.log(firstRecordPassword.value[0])
};
getKeeperRecordsAWS();
To do this, use AwsKmsKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, AwsSessionConfig, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
from keeper_secrets_manager_core import SecretsManager
from keeper_secrets_manager_hsm.storage_aws_kms import AwsKmsKeyValueStorage
aws_session_cfg = AwsSessionConfig(
aws_access_key_id="AK[...]FIF",
aws_secret_access_key="/[...]/g3",
region_name="us-east-2")
config = AwsKmsKeyValueStorage(
key_id='e9[...]567',
config_file_location='client-config.json',
aws_session_config=aws_session_cfg)
secrets_manager = SecretsManager(config=config, verify_ssl_certs=True)
all_records = secrets_manager.get_secrets()
To do this, use AWSKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, AwsSessionConfig, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
using System;
using System.Linq;
using System.Threading.Tasks;
using SecretsManager;
using AWSKeyManagement;
public class Program
{
private static async Task getOneIndividualSecret()
{
var accessKeyId = "<ACCESS_KEY_ID>";
var secretAccessKey = "<SECRET_ACCESS_KEY>";
var regionName = "<AWS_REGION_STRING";
var keyId = "<KEY_ID_1>";
var path = "<KEEPER_CONFIG_FILE_PATH>";
var dotnet_access_token = "<ONE_TIME_TOKEN>";
var awsSessionConfig = new AWSSessionConfig(accessKeyId, secretAccessKey, regionName);
var aws_storage = new AWSKeyValueStorage(keyId, path, awsSessionConfig);
SecretsManagerClient.InitializeStorage(aws_storage, dotnet_access_token);
var options = new SecretsManagerOptions(aws_storage);
var records_1 = await SecretsManagerClient.GetSecrets(options);
records_1.Records.ToList().ForEach(record => Console.WriteLine(record.RecordUid + " - " + record.Data.title));
}
static async Task Main()
{
await getOneIndividualSecret();
}
}
To do this, use AWSKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, AwsSessionConfig, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
package main
import (
"encoding/json"
"fmt"
"github.com/keeper-security/secrets-manager-go/core"
awskv "github.com/keeper-security/secrets-manager-go/integrations/aws"
)
func main() {
clientID := "<Some Client ID>"
clientSecret := "<Some Client Secret>"
region := "<Cloud Region>"
keyARN := "arn:<partition>:kms:<region>:<account-id>:key/<key-id>"
oneTimeToken := "one time token"
ksmConfigFileName := ""
// Initialize the AWS Key Vault Storage
cfg := awskv.NewAWSKeyValueStorage(ksmConfigFileName, keyARN, &awskv.AWSConfig{
ClientID: clientID,
ClientSecret: clientSecret,
Region: region,
})
clientOptions := &core.ClientOptions{
Token: oneTimeToken,
Config: cfg,
}
fmt.Printf("Client ID in config: %v\n", cfg.Get(core.KEY_CLIENT_ID))
secrets_manager := core.NewSecretsManager(clientOptions)
// Fetch secrets from Keeper Security Vault
record_uids := []string{}
records, err := secrets_manager.GetSecrets(record_uids)
if err != nil {
// do something
fmt.Printf("Error while fetching secrets: %v", err)
}
for _, record := range records {
// do something with record
fmt.Println(record.Title())
}
}
Using Default Connection
To do this, use AwsKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import com.keepersecurity.secretmanager.aws.kms.AwsKeyValueStorage;
import com.keepersecurity.secretmanager.aws.kms.AwsSessionConfig;
import com.keepersecurity.secretsManager.core.InMemoryStorage;
import com.keepersecurity.secretsManager.core.SecretsManager;
import com.keepersecurity.secretsManager.core.SecretsManagerOptions;
import static com.keepersecurity.secretsManager.core.SecretsManager.initializeStorage;
import software.amazon.awssdk.regions.Region;
import java.security.Security;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
class Test {
public static void main(String args[]){
String keyId = "<Key ID>";
String awsAccessKeyId = "<AWS Access ID>";
String awsSecretAccessKey = "<AWS Secret>";
String oneTimeToken = "[One Time Token]";
Region region = Region.<cloud-region>;
String profile = null OR "DEFAULT"; //set profile (ex. DEFUALT/UAT/PROD) if ~/.aws/config is set
String configFileLocation = "client_config_test.json";
try{
//set AWS configuration, It can be null if profile is set for aws credentials
AwsSessionConfig sessionConfig = new AwsSessionConfig(awsAccessKeyId, awsSecretAccessKey);
//Get Storage
AwsKeyValueStorage awskvstorage = new AwsKeyValueStorage(keyId, configFileLocation, profile, sessionConfig, region);
initializeStorage(awskvstorage, oneTimeToken);
SecretsManagerOptions options = new SecretsManagerOptions(awskvstorage);
//getSecrets(OPTIONS);
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
To do this, use AWSKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID , as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
import { AWSKeyValueStorage } from "@keeper-security/secrets-manager-aws";
import { initializeStorage, getSecrets } from "@keeper-security/secrets-manager-core";
const getKeeperRecordsAWS = async () => {
const configPath = "client-config-path.json";
const keyId = 'arn:aws:kms:ap-south-1:<accountName>:key/<keyId>';
const storage = await new AWSKeyValueStorage(keyId, configPath).init();
const oneTimeToken = "<one time token>";
await initializeStorage(storage, oneTimeToken);
const { records } = await getSecrets({ storage: storage });
const firstRecord = records[0]
const firstRecordPassword = firstRecord.data.fields.find(x => x.type === 'password')
console.log(firstRecordPassword.value[0])
};
getKeeperRecordsAWS();
To do this, use AwsKmsKeyvalueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
from keeper_secrets_manager_core import SecretsManager
from keeper_secrets_manager_hsm.storage_aws_kms import AwsKmsKeyValueStorage
key_id = 'c5[...]576'
config = AwsKmsKeyValueStorage(key_id, 'client-config.json') # default session
secrets_manager = SecretsManager(config=config, verify_ssl_certs=True)
all_records = secrets_manager.get_secrets()
To do this, use AWSKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
using System;
using System.Linq;
using System.Threading.Tasks;
using SecretsManager;
using AWSKeyManagement;
public class Program
{
private static async Task getOneIndividualSecret()
{
var keyId = "<KEY_ID_1>";
var path = "<KEEPER_CONFIG_FILE_PATH>";
var dotnet_access_token = "<ONE_TIME_TOKEN>";
var aws_storage = new AWSKeyValueStorage(keyId, path);
SecretsManagerClient.InitializeStorage(aws_storage, dotnet_access_token);
var options = new SecretsManagerOptions(aws_storage);
var records_1 = await SecretsManagerClient.GetSecrets(options);
records_1.Records.ToList().ForEach(record => Console.WriteLine(record.RecordUid + " - " + record.Data.title));
}
static async Task Main()
{
await getOneIndividualSecret();
}
}
To do this, use AWSKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an AWS Key ID, as well as the name of the Secrets Manager configuration file which will be encrypted by AWS KMS.
package main
import (
"fmt"
"github.com/keeper-security/secrets-manager-go/core"
awskv "github.com/keeper-security/secrets-manager-go/integrations/aws"
)
func main() {
keyARN := "arn:<partition>:kms:<region>:<account-id>:key/<key-id>"
oneTimeToken := "one time token"
ksmConfigFileName := "<config file name>"
// Initialize the AWS Key Vault Storage
cfg := awskv.NewAWSKeyValueStorage(ksmConfigFileName, keyARN, nil)
clientOptions := &core.ClientOptions{
Token: oneTimeToken,
Config: cfg,
}
fmt.Printf("Client ID in config: %v\n", cfg.Get(core.KEY_CLIENT_ID))
secrets_manager := core.NewSecretsManager(clientOptions)
// Fetch secrets from Keeper Security Vault
record_uids := []string{}
records, err := secrets_manager.GetSecrets(record_uids)
if err != nil {
// do something
fmt.Printf("Error while fetching secrets: %v", err)
}
for _, record := range records {
// do something with record
fmt.Println(record.Title())
}
}
Once setup, the Secrets Manager AWS KMS integration supports all Secrets Manager SDK functionality. Your code will need to be able to access the AWS KMS APIs in order to manage the decryption of the configuration file when run.
We can change key that is used for encrypting the configuration, examples below show the code needed to use it
String newkeyId = "<New-Key-ID>";
AwsKeyValueStorage awskvstorage = new AwsKeyValueStorage(keyId, configFileLocation, profile, sessionConfig, region);
awskvstorage.changeKey(newkeyId)
const storage = await new AWSKeyValueStorage(keyId,config_path).init()
await initializeStorage(storage, oneTimeToken);
// do all process needed if any or change directly
await storage.changeKey(keyId2);
from keeper_secrets_manager_core import SecretsManager
from keeper_secrets_manager_hsm.storage_aws_kms import AwsKmsKeyValueStorage
aws_session_cfg = AwsSessionConfig(
aws_access_key_id="AK[...]FIF",
aws_secret_access_key="/[...]/g3",
region_name="<region>")
new_key_id = "<new_key_id>"
config = AwsKmsKeyValueStorage(
key_id='e9[...]567',
config_file_location='client-config.json',
aws_session_config=aws_session_cfg)
secrets_manager = SecretsManager(config=config, verify_ssl_certs=True)
all_records = secrets_manager.change_key(new_key_id)
using Microsoft.Extensions.Logging;
var awsSessionConfig2 = new AWSSessionConfig();
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger<AWSKeyValueStorage>();
var aws_storage = new AWSKeyValueStorage(keyId, path, awsSessionConfig2,logger);
updatedKeyARN := "arn:<partition>:kms:<region>:<account-id>:key/<key-id>"
isChanged, err := cfg.ChangeKey(updatedKeyARN, nil)
if err != nil {
fmt.Printf("Error while changing key: %v", err)
}
We can decrypt the config if current implementation is to be migrated onto a different cloud or if you want your raw credentials back. The function accepts a boolean which when set to true will save the decrypted configuration to file and if left false, will just return decrypted configuration.
AwsKeyValueStorage awskvstorage = new AwsKeyValueStorage(keyId, configFileLocation, profile, sessionConfig, region);
awskvstorage.decryptConfig(true) // Set true as a parameter to extract plaintext and save config as a plaintext.
//OR
awskvstorage.decryptConfig(false); // Set false as a parameter to extract only plaintext.
const storage = await new AWSKeyValueStorage(keyId,config_path).init();
await storage.decryptConfig();
from keeper_secrets_manager_core import SecretsManager
from keeper_secrets_manager_hsm.storage_aws_kms import AwsKmsKeyValueStorage
aws_session_cfg = AwsSessionConfig(
aws_access_key_id="AK[...]FIF",
aws_secret_access_key="/[...]/g3",
region_name="<region>")
config = AwsKmsKeyValueStorage(
key_id='e9[...]567',
config_file_location='client-config.json',
aws_session_config=aws_session_cfg)
secrets_manager = SecretsManager(config=config, verify_ssl_certs=True)
all_records = secrets_manager.decrypt_config(True)
var conf = await aws_storage.DecryptConfigAsync(false);
Console.WriteLine(conf);
cfg := awskv.NewAWSKeyValueStorage(ksmConfigFileName, keyARN, &awskv.AWSConfig{
ClientID: clientID,
ClientSecret: clientSecret,
Region: region,
})
decryptedConfig, err := cfg.DecryptConfig(true)
You're ready to use the KSM integration 👍
Keeper Secrets Manager integration into Azure DevOps for dynamic secrets retrieval
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
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 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The Azure DevOps integration accepts JSON and Base64 format configurations
Download from the Visual Studio Marketplace here or search for "Keeper Secrets Manager"
Enable the extension for your Azure organization by selecting an organization and clicking "Download".
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 and have the following syntax KeeperNotation > destination
where the destination location is defined by its prefix var:
, out:
or file:
see the examples below.
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.
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.
Search the Tasks menu for "Keeper Secrets Manager" to open the task form.
To fill in the task form and create a Keeper Secrets Manager Task, you will need:
A Keeper Secrets Manager Configuration
The Azure DevOps Extension accepts JSON and base64 configurations.
One or more Secret queries (See query syntax below)
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 to learn more about Azure Key Vault.
Submit the form to add a task to your configuration automatically.
To add a task manually to the pipeline configuration, follow this syntax:
- task: <Task Name>
inputs:
keepersecretconfig: <Secrets Manager Configuration>
secrets: |
<Secrets Queries>
- 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
Queries for secrets in the Keeper Vault use the following syntax:
Syntax
[UID]/field/[FIELD NAME] > [VARIABLE NAME]
Example
6ya_fdc6XTsZ7i7x9Jcodg/field/password > my_password
Syntax
[UID]/custom_field/[FIELD NAME] > [VARIABLE NAME]
Example
6ya_fdc6XTsZ7i7x9Jcodg/custom_field/notes > MyNotes
Syntax
[UID]/field/oneTimeCode > [VARIABLE NAME]
Example
6ya_fdc6XTsZ7i7x9Jcodg/field/oneTimeCode > MyOneTimeCode
Syntax
[UID]/file/[SECRET FILE NAME] > file:[OUTPUT FILE NAME]
Example
6ya_fdc6XTsZ7i7x9Jcodg/file/cert.pem > file:secret-cert.pem
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)
This example pipeline sets secrets from the Keeper Vault to variables and echoes them. Note that echoed passwords are masked.
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
This example gets passwords and files from Keeper, and utilizes those passwords and files in another job.
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)"
Sync secrets from the Keeper Vault with Azure Key Vault
The Keeper Secrets Manager CLI tool sync
command allows you to push secrets from the Keeper Vault to a target Azure Key Vault account, overwriting the existing values in the target location. This allows the Keeper Vault to be the single source of truth for any services or scripts in Azure which utilize the Key Vault.
Use secrets from the Keeper Vault as the source of truth for Azure Key Vault
Seamlessly start using secrets from the Keeper Vault with your existing Azure scripts and services
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper account
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An Azure account with Key Vault, and the ability to create security principals
To configure the KSM CLI tool, a profile needs to be created with the Keeper Secrets Manager One Time Access Token.
The simplest way to do this is to initialize the default profile with the following command:
ksm profile init <TOKEN>
For information on creating multiple profiles and other options, see the profile documentation
To use KSM sync with Azure, the Azure account needs to be configured to accept the connection. The Azure account with Key vault needs to enable a service principal with authorization to perform key operations in the Key Vault.
Follow the Microsoft guide for setting up a service principal: https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals
The KSM CLI needs the credentials for the Azure account to set secrets. These credentials are stored in a Keeper record which the CLI tool can access using Keeper Secrets Manager.
Record fields with the following labels are required on the credentials record:
"Azure Tenant ID" "Azure Client ID" "Azure Client Secret" "Azure Key Vault Name"
A custom record type can be created with the required fields, which makes it easy and clean to create a record.
To create a custom record type, go to the "Custom Record Types" tab in the Keeper Vault and hit "Create Type". Create a new record type with hidden fields that have the correct field label, then click "Publish" to create the new record type.
Then simply create a new record of the Azure Credentials type and enter the details into the corresponding fields.
Make sure this new record is in a shared folder that is shared to your Secrets Manager application.
To create a credentials record without creating a new record type, the required fields can be added as custom fields to a standard record.
Create a new record of any type, then add Custom Fields of the 'Hidden Field' type for each required Azure field. Click "Edit Label" to change the labels to the corresponding field name.
Then fill in each custom field and hit "Save" to save the record.
The KSM CLI sync
command identifies which values to set using mappings that are defined on the command call. For each mapping passed to the command, a value with the given name will be populated with the given value from the Keeper Vault.
These mappings follow this format:
--map "VALUE KEY" "KEEPER NOTATION"
VALUE KEY
is the key name that the value will be assigned in Azure Key Vault
KEEPER NOTATION
is a Keeper notation query of a value from a keeper record to set to the key
Keeper notation is a query notation used by Keeper Secrets Manager to identify specific record values. The notation follows the general format of: UID/
[field|custom_field]/fieldname
for example: ae3d[...]d22e/field/password
See the Keeper Notation documentation for more information
Full Mapping Example:
--map "MySQL_PWD" "jd3[...]i-fd/field/password"
Multiple mappings can be added to a single sync
command
--map "MySQL_PWD" "jd3[...]i-fd/field/password" --map "MySQL_Login" "jd3[...]i-fd/field/login"
Ensure that the records referenced by the Keeper Notation queries are in a shared folder that is shared with your Secrets Manager application
KSM sync is now ready to run
To run the sync, use the KSM CLI sync
command with the credentials record and value mapping
Put together the KSM sync command with the Azure type. The format looks like the following:
ksm sync --type azure --credentials [UID] --map [...] --map [...]
The sync command supports running a dry-run which will identify all changes that will be made to your Azure Key Vault values without actually pushing the values or making changes. Use this to make sure your mapping queries are constructed properly.
ksm sync --type azure --credentials [UID] --map [...] --map [...] --dry-run
When ready, run the sync command without the dry-run option. This will push values from your Keeper Vault to Azure Key Vault
ksm sync --type azure --credentials [UID] -m [...] -m [...]
Protect Secrets Manager connection details with Azure Key Vault Keys
Keeper Secrets Manager integrates with Azure Key Vault in order to provide encryption for Keeper Secrets Manager configuration files. With this integration, you can protect connection details on your machine while taking advantage of Keeper's zero-knowledge encryption of all your secret credentials.
Encrypt and Decrypt your Keeper Secrets Manager configuration files with Azure Key Vault.
Protect against unauthorized access to your Secrets Manager connections.
Requires only minor changes to code for immediate protection. Works with all Keeper Secrets Manager SDK functionality.
supports RSA Asymmetric keys from Azure.
Support the Java/Kotlin Secrets Manager SDK.
Requires Azure packages: azure-identity
and azure-keyvault-keys
.
Works with just RSA key types with WrapKey
and UnWrapKey
permissions.
Supports the JavaScript Secrets Manager SDK
Requires Azure packages @azure/identity
, @azure/keyvault-keys
Works with just RSA key types with WrapKey
and UnWrapKey
permissions.
Supports the Python Secrets Manager SDK
Requires package azure-identity azure-keyvault-keys
Works with just RSA key types with WrapKey
and UnWrapKey
permissions.
Supports the .Net Secrets Manager SDK
Supports dotnet version net9.0
Requires Azure packages: Azure.Identity
and Azure.Security.KeyVault.Keys
Works with just RSA key types with WrapKey
and UnWrapKey
permissions.
Supports the GoLang Secrets Manager SDK
Requires Azure packages: azcore
, azidentity
and azkeys
.
Works with just RSA key types with WrapKey
and UnWrapKey
permissions.
Setting up project using Gradle or Maven
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("com.keepersecurity.secrets-manager:azurekv:1.0.0")
implementation("com.keepersecurity.secrets-manager:core:17.0.0")
implementation("com.azure:azure-identity:1.15.0")
implementation("com.azure:azure-security-keyvault-keys:4.9.2")
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
implementation("com.fasterxml.jackson.core:jackson-core:2.18.2")
implementation("com.google.code.gson:gson:2.12.1")
implementation("org.slf4j:slf4j-api:1.7.32"){
exclude("org.slf4j:slf4j-log4j12")
}
implementation("ch.qos.logback:logback-classic:1.2.6")
implementation("ch.qos.logback:logback-core:1.2.6")
implementation("org.bouncycastle:bc-fips:1.0.2.4")
}
Maven
<!-- KMS-core -->
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>azurekv</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>core</artifactId>
<version>17.0.0</version>
</dependency>
<!-- Azure-identity -->
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>1.15.0</version>
<scope>compile</scope>
</dependency>
<!-- Azure-keyvault -->
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-keys</artifactId>
<version>4.9.2</version>
</dependency>
<!--gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.12.1</version>
</dependency>
<!--jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!--jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!-- slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
<scope>runtime</scope>
</dependency>
<!-- logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
<scope>compile</scope>
</dependency>
<!-- logback-core -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.6</version>
<scope>compile</scope>
</dependency>
<!-- bc-fips -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>1.0.2.4</version>
</dependency>
The Secrets Manager Azure Key Vault module can be installed using npm
npm install @keeper-security/secrets-manager-azure
The Secrets Manager Storage Azure module can be installed using pip
pip3 install keeper-secrets-manager-storage
The Secrets Manager KSM modules are located in the Keeper Secrets Manager storage module which can be installed using dotnet
dotnet add package Keeper.SecretsManager.AzureKeyVault
The Secrets Manager azure KSM module Integration can be installed using
go get github.com/keeper-security/secrets-manager-go/integrations/azure
Ensure that you have an Azure Key Vault instance available, The following param needed to connect azure key vault
AZURE_TENANT_ID: The Microsoft Entra tenant (directory) ID.
AZURE_CLIENT_ID: The client (application) ID of an App Registration in the tenant.
AZURE_CLIENT_SECRET: A client secret that was generated for the App Registration.
You will need an Azure App directory App to use the Azure Key Vault integration.
Once azure connection has been configured, You can fetch the Key to encrypt / decrypt KSM configurations using azure key and you need to tell the Secrets Manager SDK to utilize the key vault as storage.
Once setup, the Secrets Manager Azure Key Vault integration supports all Secrets Manager SDK functionality. Your code will need to be able to access the Azure Keys in order to manage the encryption and decryption of the KSM configuration file. Using Specified Connection credentials
To do this, create AzureKeyValueStorage
instance and use this in SecretManagerOptions
constructor.
The AzureKeyValueStorage
will require the name of the Secrets Manager configuration file with azure_key_id
, azure_keyvault_URL
and configuration.
import java.security.Security;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import static com.keepersecurity.secretsManager.core.SecretsManager.initializeStorage;
import com.keepersecurity.secretmanager.azurekv.AzureKeyValueStorage;
import com.keepersecurity.secretmanager.azurekv.AzureSessionConfig;
import com.keepersecurity.secretsManager.core.SecretsManagerOptions;
class Test {
public static void main(String args[]){
String oneTimeToken = "[One_Time_Token]";
String keyId = "https://<vault-name>.vault.azure.net/keys/<keyname>/<keyversion>";
String configFileLocation="<KSM-client-config.json>";
String azTenantId = "<azure-tenant-id>";
String azClientId = "<azure-client-id>";
String azClientSecret = "<azure-client-secret>";
String keyVaultUrl = "https://<vault-name>.vault.azure.net/";
Security.addProvider(new BouncyCastleFipsProvider());
try{
//set azure KV configuration,
AzureSessionConfig azConfig= new AzureSessionConfig(azTenantId, azClientId, azClientSecret, keyVaultUrl);
//Get Storage
AzureKeyValueStorage azkvstorage = AzureKeyValueStorage.getInternalStorage(keyId, configFileLocation, azConfig);
initializeStorage(azkvstorage, oneTimeToken);
SecretsManagerOptions options = new SecretsManagerOptions(azkvstorage);
//getSecrets(options)
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
To do this, use AzureKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an Azure Key ID
, as well as the name of the Secrets Manager configuration file which will be encrypted by Azure Key Vault.
import { getSecrets, initializeStorage, localConfigStorage } from '@keeper-security/secrets-manager-core';
import {AzureKeyValueStorage, AzureSessionConfig} from "@keeper/secrets-manager-azure";
const getKeeperRecords = async () => {
const tenant_id="<tenant_id>"
const client_id="<client_id>"
const client_secret="<client-secret>"
const azureSessionConfig = new AzureSessionConfig(tenant_id, client_id, client_secret)
let config_path = "<path to ksm-client-config.json>"
const logLevel = LoggerLogLevelOptions.info;
// oneTimeToken is used only once to initialize the storage
// after the first run, subsequent calls will use ksm-config.txt
const oneTimeToken = "[One Time Token]";
const keyId = 'https://<vault_name>.vault.azure.net/keys/<key_name>/<version>'
const storage = await new AzureKeyValueStorage(keyId,config_path,azureSessionConfig,logLevel).init();
await initializeStorage(storage, oneTimeToken);
const {records} = await getSecrets({storage: storage});
console.log(records)
}
getKeeperRecords()
To do this, use AzureKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor as config along with a token.
The storage will require a Azure Key ID, as well as the location of the Secrets Manager configuration file which will be encrypted by Azure-KSM Integration and Azure session configuration as shown below.
from keeper_secrets_manager_storage.storage_azure_keyvault import AzureSessionConfig,AzureKeyValueStorage
from keeper_secrets_manager_core import SecretsManager
tenant_id = "<Tenant_ID>"
client_id = "<CLIENT_ID>"
client_secret = "<CLIENT_SECRET>"
azure_session_config = AzureSessionConfig(tenant_id, client_id, client_secret)
config_path = "<path_to_client_config_python.json>"
token="<One Time Token>"
key_id = "<key_id>"
azure_key_value_storage = AzureKeyValueStorage(key_id=keyId,config_file_location=config_path ,az_session_config=azure_session_config)
secrets_manager = SecretsManager(token = token,config=azure_key_value_storage)
records = secrets_manager.get_secrets()
for record in records:
print(record)
To do this, use AzureKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an Azure Key ID
, as well as the name of the Secrets Manager configuration file which will be encrypted by Azure Key Vault. Optionally AzureSessionConfig
can be provided. If credentials are not provided the default credentials are used.
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OracleKeyManagement;
using SecretsManager;
public class Program
{
private static async Task getOneIndividualSecret()
{
var tenant_id = "<TENANT_ID>";
var client_secret = "<CLIENT_SECRET>";
var client_id = "<CLIENT_ID>";
var keyId = "<KEY_ID>";
var path = "ksmConfigDotnet.json";
var dotnet_access_token = "<ACCESS_TOKEN>";
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger<AzureKeyValueStorage>();
var azure_session_config = new AzureSessionConfig(tenant_id, client_id, client_secret);
AzureKeyValueStorage azure_storage = new AzureKeyValueStorage(keyId, path, azure_session_config, logger);
SecretsManagerClient.InitializeStorage(azure_storage, dotnet_access_token);
var options = new SecretsManagerOptions(azure_storage);
var records_list = await SecretsManagerClient.GetSecrets(options);
records_list.Records.ToList().ForEach(record => Console.WriteLine(record.RecordUid + " - " + record.Data.title));
}
static async Task Main()
{
await getOneIndividualSecret();
}
}
To do this, use NewAzureKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The NewAzureKeyVaultStorage
requires the following parameters to encrypt the KSM configuration using Azure Key Vault:
ksmConfigFileName
: The file name of KSM configuration.
keyURL
: Azure Key URL
package main
import (
"encoding/json"
"fmt"
"github.com/keeper-security/secrets-manager-go/core"
azurekv "github.com/keeper-security/secrets-manager-go/integrations/azure"
)
func main() {
ksmConfigFile := ""
oneTimeToken := "oneTimeToken"
keyURL := "<Key URL>" }
//Initialize the Azure Key Vault Storage
cfg := azurekv.NewAzureKeyValueStorage(ksmConfigFileName, keyURL, &azurekv.AzureConfig{
TenantID: "<Azure Tenant ID>",
ClientID: "<Azure Client ID>",
ClientSecret: "<Azure Client Secret>",
})
// create a new secrets manager client
secrets_manager := core.NewSecretsManager(
&core.ClientOptions{
Config: cfg,
Token: oneTimeToken,
},
)
// Fetch all the secrets from the vault
secrets, err := secrets_manager.GetSecrets([]string{})
if err != nil {
// do something
fmt.Printf("Error: %s\n", err)
} else {
for _, secret := range secrets {
fmt.Printf("Recieved secret: %s\n", secret.Title())
}
}
}
We can change key that is used for encrypting the KSM configuration, examples below show the code needed to use it
//The method changeKey(newKeyID) will be used to encrypt the KSM config file with new azure key.
....
String newKeyID = "https://<vault-name>.vault.azure.net/keys/<keyname>/<keyversion>";
AzureKeyValueStorage azkvstorage = AzureKeyValueStorage.getInternalStorage(keyId, configFileLocation, azConfig);
boolean isChanged = azkvstorage.changeKey(newKeyID); // Change the key for encryption/decryption
....
// To change the Azure Key Vault key used for encryption, you can call the `changeKey` method on the `OciKeyValueStorage` instance.
.....
const keyId = 'https://<vault_name>.vault.azure.net/keys/<key_name>/<version>'
const keyId2 = "https://<vault_name>.vault.azure.net/keys/<key_name>/<version>"
const storage = await new AzureKeyValueStorage(keyId,config_path,azureSessionConfig).init();
await storage.changeKey(keyId2);
.....
azure_key_value_storage = AzureKeyValueStorage(key_id=keyId,config_file_location=config_path ,az_session_config=azure_session_config)
new_key_id = "<new key id>"
isChanged = azure_key_value_storage.change_key(new_key_id = new_key_id)
print("Key is changed " + isChanged)
// To change the Azure key used for encryption, you can call the `ChangeKeyAsync` method on the `AzureKeyValueStorage` instance.
using Microsoft.Extensions.Logging;
....
var keyId2 = "<KEY_ID_2>";
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger<AzureKeyValueStorage>();
AzureKeyValueStorage azure_storage = new AzureKeyValueStorage(keyId, path, azure_session_config, logger);
azure_storage.ChangeKeyAsync(keyId2).Wait();
....
....
updatedConfig := &azurekv.AzureConfig{
TenantID: "<Updated Tenant ID>",
ClientID: "<Updated Client ID>",
ClientSecret: "<Updated Client Secret>",
}
updatedKeyURL := "<Updated Key URL>"
// Changes the key
// If you don't want to change Config, pass nil as a paramter
isChanged, err := cfg.ChangeKey(updatedKeyURL, updatedConfig)
if err != nil {
fmt.Printf("Error while changing key: %v", err)
} else {
fmt.Printf("Key changed: %v\n", isChanged)
}
.....
We can decrypt the config if current implementation is to be migrated onto a different cloud or if you want your raw credentials back. The function accepts a boolean which when set to true will save the decrypted configuration to file and if it is false, will just return decrypted configuration. This function accepts a boolean, when set to true will save the decrypted configuration to file and when set to false will return decrypted configuration.
....
AzureKeyValueStorage azkvstorage = AzureKeyValueStorage.getInternalStorage(keyId, configFileLocation, azConfig);
azkvstorage.decryptConfig(false); // Set false as a parameter to extract only plaintext.
//OR
azkvstorage.decryptConfig(true); // Set true as a parameter to extract plaintext and save config as a plaintext.
....
//To decrypt the config file and save it again in plaintext, you can call the `DecryptConfigAsync` method on the `AzureKeyValueStorage` instance.
....
const storage = await new AzureKeyValueStorage(keyId,config_path,azureSessionConfig).init();
const decryptedConfig = storage.DecryptConfigAsync(true).wait(); // return decrypted and Saves to file
//OR
const decryptedConfig = await storage.decryptConfig(false); // returns the decrypted config
....
storage = AzureKeyValueStorage(key_id=keyId,config_file_location=config_path ,az_session_config=azure_session_config)
storage.decrypt_config() #saved plain config to file
# or
storage.decrypt_config(False)# returns config as return value, file will stay encrypted
//To decrypt the config file and save it again in plaintext, you can call the `DecryptConfigAsync` method on the `AzureKeyValueStorage` instance.
....
var keyId2 = "<KEY_ID_2>";
AzureKeyValueStorage azure_storage = new AzureKeyValueStorage(keyId, path, azure_session_config, logger);
await azure_storage.DecryptConfigAsync(true); // return decrypted and Saves to file
//OR
await azure_storage.DecryptConfigAsync(false); // returns the decrypted config
....
.....
configs := make(map[core.ConfigKey]interface{})
plainText, err := cfg.DecryptConfig(true)
if err != nil {
// do something
fmt.Printf("Error while decrypting config: %v", err)
} else {
if err := json.Unmarshal([]byte(plainText), &configs); err != nil {
fmt.Printf("Error while unmarshalling: %v", err)
}
fmt.Printf("Decrypted data: %v\n", configs["clientId"])
}
.....
You're ready to use the KSM integration 👍
Keeper Secrets Manager integration into Bitbucket for dynamic secrets retrieval
Retrieve secrets from the Keeper Vault within BitBucket Pipelines
Set secret credentials as build arguments or environment variables in BitBucket Pipeline scripts
Copy secure files from the Keeper Vault
This page documents the Secrets Manager BitBucket integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The BitBucket integration accepts JSON and Base64 format configurations
Using Keeper Commander, add a new client to an application and initialize the configuration to a Base64 string. This will be the long text hash that appears after the "Initialized Config:" label.
My Vault> sm client add --app MyApp --config-init b64
Successfully generated Client Device
====================================
Initialized Config: eyJob3N0bmFtZSI6ICJr....OUk1ZTV1V2toRucXRsaWxqUT0ifQ==
IP Lock: Enabled
Token Expires On: 2021-10-19 15:31:31
App Access Expires on: Never
That value can be added to your BitBucket Repository variables, under Repository settings menu, as a secure secret with the name KSM_CONFIG. This will allo the configuration to be available to the Keeper Secrets Manager pipe as a variable.
image: atlassian/default-image:2
pipelines:
default:
- step:
name: 'Build My Stuff'
script:
- pipe: keepersecurity/keeper-secrets-manager-pipe:<tag>
variables:
KSM_CONFIG: "${KSM_CONFIG}"
SECRETS: |
1adh_WZxtbbHWqf6IALMVg/field/login > MY_LOGIN
V8lFbio0Bs0LuvaSD5DDHA/file/IMG_0036.png > file:my.png
SCRIPT_TEXT: |
#!/usr/bin/env bash
echo "My Login = \${MY_LOGIN}"
ls my.png
SHOW_OUTPUT: "True"
SECRETS_FILE: "secret.env"
SECRETS_FILE_TYPE: "export"
- source secret.env
The name of the pipe integration is the following.
script:
- pipe: keepersecurity/keeper-secrets-manager-pipe:<tag>
KSM_CONFIG
- The Keeer Secrets Mananger pipe requires configuration information. This can be stored in the Repository variables and pulled into a variable using "${KSM_CONFIG}"
SECRETS
- The secrets are a new line separted list of Keeper Notation and destinations. The notation and desitnation are separated by the '>' character.
SCRIPT_FILE
- The script file is an application, or shell script, that you wish to run inside of the pipe. The script will be able to access the secrets.
SCRIPT_TEXT
- The script text allows you to hardcode a script inside of the bitbucket-pipeline.yml. It will be used if a SCRIPT_FILE
does not exist. If used, you will need to escape any shell related special characters.
SECRETS_FILE
- If set, secrets that were to be place into environmental varaibles will also be placed into a file. The format of the file depends on the SECRET_FILE_TYPE
.
SECRETS_FILE_TYPE
- If a SECRET_FILE is used, this variable will determine it's format. Valid formats are 'json', 'export', 'setenv', and 'set'. The default is 'json'
SHOW_OUTPUT
- A boolean flag to show the output from the SCRIPT_FILE
or SCRIPT_TEXT
. The REDACT variable will determine if you will be able to see your secrets in the ouput. By default, this flag is True.
SAVE_OUTPUT_FILE
- If set, the output from the SCRIPT_FILE
or SCRIPT_TEXT
will be saved to a file.
REDACT
- If True, any secret displayed from the SCRIPT_FILE
or SCRIPT_TEXT
will be replaced with '****'. By default, this flag is True. This does not redact output saved to a file.
REMOVE_FILES
- If True, when the pipe exits it will delete any files it created. Those files will not be available outside of the pipe unless the value is set to False. By default, this is True.
CLEANUP_FILE
- The name of a shell script that will remove any files created inside of the pipe. While the build workspace is removed when the build finishes, this shell file can be run to make sure the files are deleted. If not set, no clean up file will be created.
DEBUG
- Enable debug message inside of the pipe. By default, this is False.
The SECRETS variable in the YAML contains a list of Keeper Notation and where the value should be stored. Secrets can be stored as an environmental variable or in a file.
The default destination for a variable is a environmental variable. The prefix env: can be added to the front of the environmental variable name, but is not required.
The example below will take the login secret and place them into environmental variables. Both lines do the same, one without the env: prefix and one with.
script:
- pipe: keepersecuirty/keeper-secrets-manager-pipe:<tag>
variables:
KSM_CONFIG: "${KSM_CONFIG}"
SECRETS: |
1adh_WZxtbbHWqf6IALMVg/field/login > MY_LOGIN
1adh_WZxtbbHWqf6IALMVg/field/login > env:SAME_LOGIN
In the example, 1adh_WZxtbbHWqf6IALMVg
is a record UID.
If the secret is binary data it is highly recommended not to store the secret in an environmental variable due to encoding issues. Use the file: destination instead.
script:
- pipe: keepersecurity/keeper-secrets-manager-pipe:<tag>
variables:
KSM_CONFIG: "${KSM_CONFIG}"
SECRETS: |
1adh_WZxtbbHWqf6IALMVg/file/server.xml > file:server.xml
1adh_WZxtbbHWqf6IALMVg/file/domain.crt > file:config/path/domain.crt
If the variable REMOVE_FILES
is True, the file will be removed when the pipe exits. Set this variable to False if you wish to use the files outside of the pipe.
This example will create a Tomcat server Docker image that contains a custom server.xml config and keystore containing the SSL certs. The server.xml and keystore are stored in the Keeper Vault.
The first step is to create a repo in BitBucket, then add a Dockerfile. This Dockerfile will add two files created by the Keeper Secrets Manager pipe to an official Tomcat Docker image.
FROM tomcat:10-jdk16
ADD /server.xml /usr/local/tomcat/conf/server.xml
ADD /localhost-rsa.jks /usr/local/tomcat/conf/localhost-rsa.jks
# Expose port 8443 for SSL
EXPOSE 8443
Next a configuration is needed for the Keeper Secrets Manager pipe. This can be created using Keeper Commander and initializing the config as Base64.
My Vault> sm client add --app MyApp --config-init b64
Successfully generated Client Device
====================================
Initialized Config: eyJob3N0bmFtZSI6ICJr....OUk1ZTV1V2toRucXRsaWxqUT0ifQ==
IP Lock: Enabled
Token Expires On: 2021-10-19 15:31:31
App Access Expires on: Never
The Initialized Config: Base64 string needs to be cut-n-pasted into your Repository variables. In this example the name of the variable is KSM_CONFIG. A private Docker Hub username and password are also added to the Repository variables.
Next a bitbucket-pipelines.yml
file needs to be added to the repository.
image: atlassian/default-image:2
pipelines:
default:
- step:
name: 'Build Custom Tomcat Server'
script:
- pipe: keepersecuirty/keeper-secrets-manager-pipe:<tag>
variables:
KSM_CONFIG: "${KSM_CONFIG}"
SECRETS: |
3GGclNXOoU0DwZwdn6iZmg/file/server.xml > file:server.xml
3GGclNXOoU0DwZwdn6iZmg/file/localhost-rsa.jks > file:localhost-rsa.jks
REMOVE_FILES: "False"
CLEANUP_FILE: "ksm_cleanup.sh"
- VERSION="1.$BITBUCKET_BUILD_NUMBER"
- IMAGE="$DOCKERHUB_USERNAME/$BITBUCKET_REPO_SLUG"
- docker login --username "$DOCKERHUB_USERNAME" --password "${DOCKERHUB_PASSWORD}"
- docker image build -t ${IMAGE}:${VERSION} .
- docker image tag ${IMAGE}:${VERSION} ${IMAGE}:latest
- docker image push ${IMAGE}
- git tag -a "${VERSION}" -m "Tagging for release ${VERSION}"
- git push origin ${VERSION}
- ./ksm_cleanup.sh
services:
- docker
The above is used to build a Docker image and push it to your Docker Hub account. The first step will use the Keeper Secrets Manager pipe to retrieve the two files and place them into the work directory.
The REMOVE_FILES
variable is set to False since we don't want to delete them after the pipe has finished.
The CLEANUP_FILE
variable is set to ksm_cleanup.sh which will create a script that will remove the two files when we are done.
When we build the Dockerfile, it will add the two files into the correct locations inside the image. When done it will push the image to the Docker Hub account.
The last part is running the ksm_cleanup.sh script that was set by the CLEANUP_FILE
variable. This will make sure the two files we created are deleted. BitBucket Pipeline does delete the work space when it is done, however this guarantees the files are deleted.
This example will retrieve secrets that are used as variables for another pipe. The other pipe is the AWS S3 Deploy pipe which will copy a local directory into a S3 bucket.
In the Keeper Vault, a record was created that contains our AWS credentials and information about the S3 bucket.
The first step is to create a repo in BitBucket, and then store the Keeper Secrets Manager pipe configuration in the Repository variables. This can be created using Keeper Commander and initializing the config as Base64.
My Vault> sm client add --app MyApp --config-init b64
Successfully generated Client Device
====================================
Initialized Config: eyJob3N0bmFtZSI6ICJr....OUk1ZTV1V2toRucXRsaWxqUT0ifQ==
IP Lock: Enabled
Token Expires On: 2021-10-19 15:31:31
App Access Expires on: Never
The Initialized Config: Base64 string needs to be cut-n-pasted into your Repository variables. In this example the name of the variable is KSM_CONFIG.
Next a bitbucket-pipelines.yml
file needs to be added to the repository.
image: atlassian/default-image:2
pipelines:
default:
- step:
name: 'Copy Image To S3'
script:
- pipe: keepersecurity/keeper-secrets-manager-pipe:<tag>
variables:
KSM_CONFIG: "${KSM_CONFIG}"
SECRETS: |
IumwT1QYRr8TTCtY8rqzhw/custom_field/AWS_ACCESS_KEY_ID > AWS_ACCESS_KEY_ID
IumwT1QYRr8TTCtY8rqzhw/custom_field/AWS_SECRET_ACCESS_KEY > AWS_SECRET_ACCESS_KEY
IumwT1QYRr8TTCtY8rqzhw/custom_field/AWS_DEFAULT_REGION > AWS_DEFAULT_REGION
IumwT1QYRr8TTCtY8rqzhw/custom_field/S3_BUCKET > S3_BUCKET
V8lFbio0Bs0LuvaSD5DDHA/file/IMG_0036.png > file:to_s3/my_image.png
SECRETS_FILE: "secrets.env"
SECRETS_FILE_TYPE: "export"
- source ./secrets.env
- pipe: atlassian/aws-s3-deploy:1.1.0
variables:
AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}"
AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}"
AWS_DEFAULT_REGION: "${AWS_DEFAULT_REGION}"
S3_BUCKET: "${S3_BUCKET}"
LOCAL_PATH: "to_s3"
The bitbucket-pipelines.yml
contains the Keeper Secrets Manager pipe which will retrieve our AWS credential from a record and place them into environment variables. It will also get a PNG image and write it into a directory called to_s3. The pipe will create a secrets file called secrets.env.
The SECRETS_FILE_TYPE
is export which will allow the contents to be sourced and the secret values placed into environment.
Next the secrets file is sourced. This allows other pipes, and applications, access to the secrets as environmental variables.
The last step is using the aws-s3-deploy pipe to copy the image to the S3 bucket. The variables for the aws-s3-deploy pipe are set using the environmental variables provided by the Keeper Secrets Manager pipe's secret file.
Using environmental variable substitution with containerized environments
Pass secret credentials from the Keeper Vault to Docker images
Build Docker Images with secret credentials from the Keeper Vault using build arguments
Copy files from the Keeper vault into Docker containers
This page documents the Secrets Manager Docker Image b Actions integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
The Keeper Secrets Manager (KSM) CLI Tool
See instructions on setting up the KSM CLI here
The Secrets Manager CLI can be used to pull secrets from a Docker image at runtime, or it can be used by building it into the docker image. Several use cases are described in this document.
Secrets from the Keeper Vault can be built into a Docker container using Docker BuildKit. As of Docker 18.09 or later, image building supports the ability to pass secrets in via a mounted file system. As a simple example demonstrating this capability, we will be creating a user account in the destination image with a username and password from Keeper Secrets Manager.
Step 1: Set Environmental Variables with Keeper notation for the secrets that are needed. For more notation examples click here.
export MY_UID="SOAsfj_lIg0VenDr83gjDw"
export MY_USER="keeper://${MY_UID}/field/login"
export MY_PASS="keeper://${MY_UID}/field/password"
Step 2: Using the ksm exec
command, the Docker build is created with the 2 secrets (login and password). The --secret
parameters will pull values from the environmental variables that have been substituted with Keeper secrets.
DOCKER_BUILDKIT=1 ksm exec -- \
docker build \
--secret id=my_user,env=MY_USER \
--secret id=my_password,env=MY_PASS \
-t my_image .
Step 3: In the dockerfile, we will create a linux user account using useradd
and then set the password with chpasswd
. The Docker file is below:
FROM my_base_image
RUN --mount=type=secret,id=my_user,dst=/my_secrets/my_user \
--mount=type=secret,id=my_password,dst=/my_secrets/my_password \
useradd "$(cat /my_secrets/my_user)" && \
echo "$(cat /my_secrets/my_user)":"$(cat /my_secrets/my_password)" | chpasswd
In this example, each secret is mounted as a file. The 'dst' value specifies where you want to temporarily store the secret. Once the RUN command is finished, the temporary file will be removed and unmounted. You can either pass the file name as an argument or in this case we are using cat $(/path/to/secret)
to read the file contents into a variable.
Similar to example 1, you can pass in secrets via the --build-arg
. This example will also demonstrate the ability of using secrets in a Docker build process.
Step 1: Set Environmental Variables with Keeper notation for the secrets that are needed. For more notation examples click here.
export MY_UID="SOAsfj_lIg0VenDr83gjDw"
export MY_USER="keeper://${MY_UID}/field/login"
export MY_PASS="keeper://${MY_UID}/field/password"
Step 2: Using the ksm exec
command, the Docker build is created with the 2 secrets (login and password). The flag --inline
processes the replacement of secrets. For example:
ksm exec --inline -- \
docker build \
--build-arg "BUILD_MY_USER=${MY_USER}" \
--build-arg "BUILD_MY_PASSWORD=${MY_PASSWORD}" \
-t my_image .
Step 3: In the dockerfile, we will create a linux user account using useradd
and then set the password with chpasswd
. The Docker file is below:
FROM my_base_image
ARG BUILD_MY_USER
ARG BUILD_MY_PASSWORD
RUN useradd "$(printenv --null BUILD_MY_USER)" && \
echo "$(printenv --null BUILD_MY_USER)":"$(printenv --null BUILD_MY_PASSWORD)" | chpasswd
To prevent secrets being sent to stdout from the printenv
command, use the --null
option to remove the line feed.
In this example, we will use docker-compose to build an image. Docker-compose cannot populate build args from environment variables. To replace notation with secret values, the build args need to be set via the command line. Since the notation will be on the command line, the --inline replacement flag needs to be set.
Step 1: Create a simple docker-compose.yaml
file:
---
version: "3"
services:
my_app:
build:
content: "."
Step 2: Using the ksm exec
command, the Docker build is created with the 2 secrets (login and password). The flag --inline
processes the replacement of secrets. For example:
ksm exec --inline -- \
docker-compose build \
--build-arg "BUILD_MY_USER=${MY_USER}" \
--build-arg "BUILD_MY_PASSWORD=${MY_PASSWORD}" \
-t my_image .
Step 3: In the dockerfile, we will create a linux user account using useradd
and then set the password with chpasswd
. The Docker file is below:
FROM my_base_image
ARG BUILD_MY_USER
ARG BUILD_MY_PASSWORD
RUN useradd "$(printenv --null BUILD_MY_USER)" && \
echo "$(printenv --null BUILD_MY_USER)":"$(printenv --null BUILD_MY_PASSWORD)" | chpasswd
To prevent secrets being sent to stdout from the printenv
command, use the --null
option to remove the line feed.
In this real world example, we copy an SSL certificate and passphrase from the Keeper Vault to a Tomcat container.
By default, the official Tomcat docker contains a default server configuration that does not have SSL enabled. We are going build a custom image that installs our server.xml, copies over the keystore file, and enables SSL. The server.xml file also contains the secret passphrase for the keystore file.
Step 1: Create a Keeper Secret Record
In the Keeper Vault, create a secret record that contains 2 file attachments: server.xml
and localhost-rsa.jks
as seen below:
Make note of the Record UID in the information dialog which will be used in the dockerfile. Click the Record UID to copy to your clipboard.
Step 2: Create the dockerfile
The below dockerfile example copies the server.xml and keystore files from the vault into the Tomcat folder.
FROM tomcat:10-jdk16
ARG BUILD_KSM_INI_CONFIG
ARG BUILD_KSM_SERVER_UID
# The names of our files in our secret record
ARG BUILD_SERVER_CONFIG="server.xml"
ARG BUILD_KEYSTORE="localhost-rsa.jks"
# Temporarily install Python3
RUN apt-get update -y && \
apt-get install -y \
python3 \
python3-pip \
python3-venv
# Install modules in a known place so we can remove them later.
ENV VIRTUAL_ENV /venv
RUN python3 -m pip install --upgrade pip && \
python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# Upgrade pip since the distro's python might be old enough that it doesn't like to install newer modules.
RUN pip3 install --upgrade pip
RUN pip3 install keeper_secrets_manager_cli
RUN echo ${BUILD_KSM_INI_CONFIG}
# Import the KSM Client Device configuration, decode it, and store it a place where ksm can find it.
RUN ksm profile import $(printenv --null BUILD_KSM_INI_CONFIG)
# Download the server.xml and keystore into the Tomcat conf directory
RUN ksm secret download -u ${BUILD_KSM_SERVER_UID} --name ${BUILD_SERVER_CONFIG} --file-output /usr/local/tomcat/conf/server.xml
RUN ksm secret download -u ${BUILD_KSM_SERVER_UID} --name ${BUILD_KEYSTORE} --file-output /usr/local/tomcat/conf/localhost-rsa.jks
# We no longer need ksm. Remove it, python, and Debian apt to make a smaller Docker image.
RUN rm -rf /venv keeper.ini
RUN apt-get purge -y \
python3 \
python3-pip \
python3-venv && \
apt-get clean autoclean && \
apt-get autoremove -y && \
rm -rf /var/lib/{apt,dpkg,cache,log}/
# Expose port 8443 for SSL
EXPOSE 8443
Note that in this use case, ksm
is no longer needed after the build, so it is deleted.
Step 3: Create a shell script to execute the docker build
To execute the docker build the below script will pass in the Secrets Manager device configuration and Record UID that contains the secret files.
#!/bin/sh
# Export the KSM profile as a string
export CF=$(ksm profile export _default)
# Execute the docker build, passing in the Record UID
# that contains the secret files
docker build \
--build-arg "BUILD_KSM_INI_CONFIG=${CF}" \
--build-arg "BUILD_KSM_SERVER_UID=LdRkidFLPF7vDaogwJ7etQ" \
-t ksm_tomcat .
When the docker image is built, it will be fully configured with SSL, keystore file and passphrase that are managed by the Keeper Vault. 😃😃😃
Keeper Secrets Manager supports direct integration with Docker Compose using the KSM Writer Docker image.
Learn more about the KSM Writer Docker image here.
If you have some great examples to contribute to this page, please ping us on Slack or email sm@keepersecurity.com.
Retrieve secrets from Keeper Secrets Manager at Docker runtime
Dynamically retrieve secrets from the Keeper Vault when Docker containers execute
This page documents the Secrets Manager Docker Runtime integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
The Keeper Secrets Manager (KSM) CLI Tool
See instructions on setting up the KSM CLI here
Keeper Secrets Manager integrates with the Docker Runtime so that you can dynamically retrieve a secret from the vault when the container executes.
The ksm
command is used to set environment variables when the container is started instead of hard-coding them into a deployment script. A real world example of this implementation is demonstrated below.
The official MySQL docker allows a user to set the MySQL root password and create a network accessible user via environment variables. The MySQL instance is then provisioned when a container is run.
The official MySQL dockerfile is below:
FROM debian:buster-slim
...
... INSTALL MySQL 8.0 SERVER
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
In the standard implementation, the ENTRYPOINT does the provisioning of the container and will use environmental variables that are passed in to set up MYSQL. The environmental variables referenced are the following:
MYSQL_ROOT_PASSWORD
MYSQL_USER
MYSQL_PASSWORD
MYSQL_DATABASE
The below steps will show how to initialize the MySQL database with secrets that are stored in the Keeper Vault.
Step 1: Create 2 Vault Records with Secrets
Create two records in the Vault that are managed by the Secrets Manager application. One record contains the root password. The other record contains the regular user, password and database values.
Make sure to copy the Record UID that appears in the vault records. These are used in Step 3 below when referencing the vault secrets.
Step 2: Create dockerfile that builds on the default MySQL dockerfile
We'll create a dockerfile that installs Keeper Secrets Manager CLI (ksm
) and then wraps the ENTRYPOINT with ksm exec
In the below dockerfile, the 4 environment variables are replaced using Keeper Notation. We are also passing in the Secrets Manager profile that points to the vault where the secrets are stored.
FROM mysql:debian
ARG BUILD_KSM_INI_CONFIG
ARG BUILD_ROOT_UID
ARG BUILD_USER_UID
RUN apt-get update && \
apt-get install -y python3 python3-pip python3-venv && \
apt-get clean
# Avoid system installed modules that might interfer.
ENV VIRTUAL_ENV /venv
RUN python3 -m pip install --upgrade pip && \
python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# Upgrade pip since the distro's Python might be old enough that it doesn't like to install newer modules.
RUN pip3 install --upgrade pip
# Install Keeper Secrets Manager CLI
RUN pip3 install keeper-secrets-manager-cli
# Import our configuration, decode it, and store it a place where ksm can find it.
RUN ksm profile import $(printenv --null BUILD_KSM_INI_CONFIG)
ENV MYSQL_ROOT_PASSWORD keeper://${BUILD_ROOT_UID}/field/password
ENV MYSQL_USER keeper://${BUILD_USER_UID}/field/login
ENV MYSQL_PASSWORD keeper://${BUILD_USER_UID}/field/password
ENV MYSQL_DATABASE keeper://${BUILD_USER_UID}/custom_field/database
ENTRYPOINT ["ksm", "exec", "--", "docker-entrypoint.sh"]
Step 3: Create a shell script to execute the docker build
To execute the docker build, the below script will pass in the Secrets Manager device configuration, root user Record UID and network user Record UID from the vault that contains the secrets.
#!/bin/sh
export CF=$(ksm profile export)
docker build \
--build-arg "BUILD_KSM_INI_CONFIG=${CF}" \
--build-arg "BUILD_ROOT_UID=DvpMcO4xV5nZF6jqLGF1fQ" \
--build-arg "BUILD_USER_UID=VNxZvvNAZ8j2mL4WIjEzjg" \
-t mysql_custom \
.
The KSM CLI Docker includes a volume mount to both GLIBC (most Linux distributions) and MUSL (Alpine Linux) CLI binaries. The volume is /cli
. This directory can be mounted into another container using the volumes_from
in docker-compose or -v
from command line docker. The ksm executables exists in directory based on the version of C library your Linux distribution is using.
/cli/glibc/ksm
- For standard GLIBC distributions like Ubuntu, Debian, Fedora, and CentOS.
/cli/musl/ksm
- For Alpine Linux.
For example, the following is simple framework showing how to access the CLI binary.
---
version: "2"
services:
init:
image: keeper/keeper-secrets-manager-cli:latest
main:
image: ubuntu:latest
volumes_from:
- init:ro
command: [ '/cli/glibc/ksm', 'exec', 'printenv', 'MY_LOGIN' ]
environment:
KSM_CONFIG: ewog ... M09IemdQMnc9Igp9
MY_LOGIN: keeper://bf18xLR3aVut5eYy7oIZZZ/field/login
LC_ALL: C.UTF-8
LANG: C.UTF-8
depends_on:
init:
condition: service_completed_successfully
The init
service will load the CLI docker. The container will start, display a CLI splash screen, and then will exit. Even though the container has stopped, the /cli
volume is still accessible from other containers.
The main
service will mount the CLI docker's volume under the directory /cli
using volumes_from
. The command
is overridden to run the GLIBC version of the KSM CLI. The command
is using the exec
function of the CLI. That will replace environment variables environment variable, that use the Keeper Notation, with a secret value. The exec
command, of the CLI, is running the printenv
application. That will print the environment variable, MY_LOGIN, that has been set to Keeper Notation, and has had its value replaced with a secret by the exec
command.
$ example : docker-compose up
[+] Running 2/0
⠿ Container example-init-1 Created 0.0s
⠿ Container example-main-1 Recreated 0.1s
Attaching to example-init-1, example-main-1
example-init-1 |
example-init-1 | ██╗ ██╗███████╗███╗ ███╗ ██████╗██╗ ██╗
example-init-1 | ██║ ██╔╝██╔════╝████╗ ████║ ██╔════╝██║ ██║
example-init-1 | █████╔╝ ███████╗██╔████╔██║ ██║ ██║ ██║
example-init-1 | ██╔═██╗ ╚════██║██║╚██╔╝██║ ██║ ██║ ██║
example-init-1 | ██║ ██╗███████║██║ ╚═╝ ██║ ╚██████╗███████╗██║
example-init-1 | ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝
example-init-1 |
example-init-1 | Current Version: 1.0.13
example-init-1 |
example-init-1 | Running in shell mode. Type 'quit' to exit.
example-init-1 |
example-init-1 exited with code 0
example-main-1 | john.smith@localhost
example-main-1 exited with code 0
Similar to the examples above, the KSM CLI docker can be used to override the entrypoint and command for another vendor's Docker image without creating a custom Docker image.
This example, combines the first two examples.
For this example, it will be assumed the Docker image is being severed by the Docker Hub repository and the images' Dockerfile is stored on GitHub.
The first step is to determine what operating system distribution the vendor's Docker image is built upon. Often this can be determined by the tag name. For example, if the name has "alpine" in the image tag name, you'll know it's the Alpine Linux distribution.
If the image tag name does not indicate the distribution, then on the Docker Hub web page for the image, click on the tag name in the "Supported tags" section. This will display the content of the Dockerfile. The FROM statement will indicate the distribution the vendor has built their image upon. If it is not apparent from the FROM statement, you man check the Dockerfile of the FROM image due to inheritance.
MySQL 8.0.31 doesn't indicate the operating system distribution in the tag name. On the MySQL Docker Hub page, the 8.0.31 tag links to their GitHub repo. From the Dockerfile we can see the distribution is Oracle Linux.
The purpose of checking the distribution is to determine what version of the libc library is being used. Most distributions use GLIBC but some, mainly Alpine Linux, uses MUSL. This is needed to select the correct binary from the KSM CLI Docker image. If you select the wrong one, you will get an error like exec /cli/musl/ksm: no such file or directory
or exec /cli/glibc/ksm: no such file or directory
. For our example, Oracle Linux is a GLIBC distribution.
The next step is to determine the vendor's Docker image ENTRYPOINT and CMD. The Dockerfile will list the ENTRYPOINT and/or CMD.
From the MySQL Dockerfile, the ENTRYPOINT is ["docker-entrypoint.sh"]
and the CMD is ["mysqld"]
. This means the ENTRYPOINT will be prepended to the CMD, so when the container is started docker-entrypoint.sh mysqld
will be executed.
docker-compose.yml
The docker-compose uses two services.
The init service loads the keeper/keeper-secrets-manager-cli
Docker image volumes. This image image will start and exit, however the volumes will still be accessible after it exits.
The main service will run after the init service. This is done by using the docker-composes depends_on
directive. This service contains environment variables, with notation, that will be replaced by the KSM CLI exec
command and also includes the Base64 encoded configuration needed by the KSM CLI. The MYSQL_ environmental variables are used by the MySQL Docker image to provision the database.
The main services also will mount the volumes from the init service using the volumes_from
. The KSM CLI Docker image defined that volumes are exported, and where they are mounted in the main service container. The binaries are mounted in /cli
, followed by the libc version, and the ksm
binary name.
version: '3.0'
services:
init:
image: keeper/keeper-secrets-manager-cli:latest
main:
image: mysql:8.0
environment:
KSM_CONFIG: "ewog .... RQ3pQMnc9Igp9"
MYSQL_USER: "keeper://KOJLz4Wzbqfi9xUO-VMViA/field/login"
MYSQL_PASSWORD: "keeper://KOJLz4Wzbqfi9xUO-VMViA/field/password"
MYSQL_ROOT_PASSWORD: "keeper://KOJLz4Wzbqfi9xUO-VMViA/custom_field/Root Password"
MYSQL_DATABASE: "keeper://KOJLz4Wzbqfi9xUO-VMViA/custom_field/Database"
depends_on:
init:
condition: service_completed_successfully
entrypoint: ["/cli/glibc/ksm", "exec", "docker-entrypoint.sh"]
command: ["mysqld"]
ports:
- "3306:3306"
volumes_from:
- init:ro
Since the MySQL image uses the Oracle distribution, a GLIBC distribution, the main service will use the /cli/glibc/ksm
binary.
The main service will override the ENTRYPOINT and CMD of the MySQL image. This is done using entrypoint and command. The entrypoint will use the KSM CLI exec
command to run the original ENTRYPOINT docker-entrypoint.sh
. The command is the same, however it needs to be set in the docker-compose.yml
else the service will just exit.
Based on the Docker image you are using, you may need override either ENTRYPOINT or CMD, or both.
When the services are brought up. The init service will run first and then exit with a code 0, which means it exited successfully execute. Then the main services will start up, execute the KSM CLI exec
command and run docker-entrypoint.sh
with mysqld
. At this point the environmental variable have been replaced with secrets, MySQL has been provisioned, and mysqld
is running.
$ my_mysql : docker-compose up
[+] Running 3/3
⠿ Network my_mysql_default Created 0.0s
⠿ Container my_mysql-init-1 Created 0.1s
⠿ Container my_mysql-main-1 Created 0.0s
Attaching to my_mysql-init-1, my_mysql-main-1
my_mysql-init-1 |
my_mysql-init-1 | ██╗ ██╗███████╗███╗ ███╗ ██████╗██╗ ██╗
my_mysql-init-1 | ██║ ██╔╝██╔════╝████╗ ████║ ██╔════╝██║ ██║
my_mysql-init-1 | █████╔╝ ███████╗██╔████╔██║ ██║ ██║ ██║
my_mysql-init-1 | ██╔═██╗ ╚════██║██║╚██╔╝██║ ██║ ██║ ██║
my_mysql-init-1 | ██║ ██╗███████║██║ ╚═╝ ██║ ╚██████╗███████╗██║
my_mysql-init-1 | ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝
my_mysql-init-1 |
my_mysql-init-1 | Current Version: 1.0.14
my_mysql-init-1 |
my_mysql-init-1 | Running in shell mode. Type 'quit' to exit.
my_mysql-init-1 |
my_mysql-init-1 exited with code 0
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]: Initializing database files
my_mysql-main-1 | 2022-10-31T21:35:26.830527Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
my_mysql-main-1 | 2022-10-31T21:35:26.830594Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.31) initializing of server in progress as process 83
...
my_mysql-main-1 | 2022-10-31T21:35:35.611063Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
my_mysql-main-1 | 2022-10-31T21:35:35.611015Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
If you have some great examples to contribute to this page, please ping us on Slack or email sm@keepersecurity.com.
A general purpose docker image to retrieve secrets.
The Docker Writer Image for KSM is an image that can download secret files and also generate a file containing secrets.
The image can be pulled with the following command:
$ docker pull keeper/keeper-secrets-manager-writer
When run, its parameters are passed in via environmental variables.
$ docker run \
-v $PWD:/wd --workdir /wd \
-e "KSM_CONFIG=BASE64 CONFIG" \
-e "SECRETS=JfXpSQ2nZG6lkdl1rxB0dg/file/example.crt > file:example.crt"
keeper/keeper-secrets-manager-writer
The parameters are handled by passing environment variables into the container.
KSM_CONFIG
A base64 encode configuration file.
SECRETS
A line-feed separated list of Keeper notation and destinations.
SECRETS_FILE
A filename to write the non-file destination secrets.
SECRETS_FILE_TYPE
The format of the secrets file. Valid format are export, setenv, set, and JSON. JSON is the default.
CLEANUP_FILE
If set, all files created will be added to the shell file to be removed when executed. This file can be executed to remove the files created.
The SECRETS
are a list of Keeper Notation and destinations. The values are separated by line feeds. For example:
fXpSQ2nZG6lkdl1rxB0dg/file/example.crt > file:example.crt
cl9a9k0DWP-Iy227rBo5gQ/field/login > MY_LOGIN
gpsBL343CVYMFgOKZ-L2hQ/custom_field/Ip Address > IP_ADDR
Each line is "Keeper Notation > destination". The destination can be either an environmental variable/JSON key or a file path and name. If a file, the path is prefixed with the text file:
. It is recommended not to place binary data into an environmental variable due to unknown string encoding.
The secrets file contains the values of the environmental variable SECRETS
. The format of the file is based on the value of SECRETS_FILE_TYPE
. The type can be the following values:
json - Values stored in a JSON format.
export - Values stored as export commands commonly used with a BASH shell.
setenv - Values stored as setenv commands commonly used with C shell.
set - Values stored as set commands commonly used with C shell.
The types related to a shell can be sourced to place the secrets into the environment.
The Docker Writer Image for KSM can be used for many applications. Here are some examples.
The writer image is best used in an Init Container.
initContainers:
- name: my_app
image: keeper/keeper-secrets-manager-writer:latest
env:
- name: SECRETS
value: |
qCAw9dMQgr3Hs7EdfFpfkA/field/password > my_password
qCAw9dMQgr3Hs7EdfFpfkA/file/exmaple.crt > file:/etc/keys/example.crt
qCAw9dMQgr3Hs7EdfFpfkA/file/exmaple.key > file:/etc/keys/example.key
In this container, the writer image is used to save a file and create a secrets file that the main container can access. This can be done by mounting a volume, writing the files, and then having the main container mount the same value. The pod's emptyDir is a good choice.
By using the depends_on
options in the main service, the Docker Writer Image for KSM can be used in the initialization service. In the example below, the Docker Writer pulls secrets from the vault and shares them on a volume mount to the main image.
---
version: "2"
services:
init:
image: keeper/keeper-secrets-manager-writer:latest
environment:
KSM_CONFIG: R2VwWTVDS ... dmVyUHVibGljS2V5SWQiOiAiMTAiCn0=
SECRETS: |
qCAw9dMQgr3Hs7EdfFpfkA/field/password > file:/etc/keys/global.pass
qCAw9dMQgr3Hs7EdfFpfkA/file/myserver.crt > file:/etc/keys/myserver.crt
qCAw9dMQgr3Hs7EdfFpfkA/file/myserver.key > file:/etc/keys/myserver.key
volumes:
- keys-volume:/etc/keys
main:
image: nginx
restart: always
volumes:
- ./config:/etc/nginx/conf.d
- keys-volume:/etc/keys
ports:
- "80:80"
- "443:443"
environment:
- NGINX_HOST=example.com
depends_on:
init:
condition: service_completed_successfully
volumes:
keys-volume:
Normally services start in parallel, however by using the depends_on
option the service startup can be controlled. In the above, the main service depends on the init service.
The init service will start, retrieve and save the files into the keys-volume, then exit. By using the condition service_completed_successfully
, when the init service successfully exits, it will start the main service. The main service will also mount the keys-volume
and use the stored keys.
The writer image can be executed in the command line by using docker run
.
docker run \
-v $PWD:/wd --workdir /wd \
-e "KSM_CONIFG=BASE64 CONFIG" \
-e "SECRETS=JfXpSQ2nZG6lkdl1rxB0dg/file/example.crt > file:example.crt"
keeper/keeper-secrets-manager-writer
If SECRETS
has multiple secrets, the line-feed character (\n) is hard to represent. The solution is to surround the --env,-e
value with $". For example
-e $'SECRETS=V8lFbio0Bs0LuvaSD5DDHA/file/IMG_0036.png > file:my.png\nIumwT1QYRr8TTCtY8rqzhw/custom_field/S3_BUCKET > s3'
Between file:my.png and the next record UID, there is a '\n'. If you don't wrap the entire value with $'' the my.png file name will include the escape line feed and the next record UID.
Protect Secrets Manager connection details locally with Entrust HSM
Keeper Secrets Manager integrates with Entrust HSM in order to provide encryption for Keeper Secrets Manager configuration files. With this integration, you can protect connection details on your machine while taking advantage of Keeper's zero-knowledge encryption of all you secret credentials.
Encrypt and Decrypt your KSM configuration files with Entrust HSM
Protect against unauthorized access to your Secrets Manager connections
Requires only minor change to code for immediate protection. Works with all KSM Python SDK functionality
Supports the Python Secrets Manager SDK
The Python module needs to be built as a nShield native application
Using Python (v3.8.5) and nfpython modules from SDK ISO image from Entrust nShield software (Security World 12.80 or later)
Virtualenv is recommended
This step is optional, but recommended for development
Create a virtualenv environment to work in
/opt/nfast/python3/bin/python3 -m venv --copies venv
Activate the virtualenv environment before starting development
. venv/bin/activate
Create a virtualenv environment to work in
c:\Program Files\nCipher\nfast\python3\python --copies -m venv venv
Activate the virtualenv environment before starting development
venv\Scripts\activate.ps1
The Secrets Manager HSM modules are located in the Keeper Secrets Manager storage module which can be installed using pip
pip3 install keeper-secrets-manager-storage
The nfpython package also needs to be installed in order to utilize the Entrust HSM. This package is installed as part of the nShield package with your Entrust installation.
In Linux:
pip install /opt/nfast/python3/additional-packages/nfpython*.whl
In Windows:
pip install c:\Program Files\nCipher\nfast\python3\additional-packages\nfpython*.whl
Use the HsmNfastKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The HsmNfastKeyValueStorage
requires the method and identity ("simple" and "ksmkey" respectively in this example).
from keeper_secrets_manager_core import SecretsManager
from keeper_secrets_manager_hsm.storage_hsm_nfast import HsmNfastKeyValueStorage
config=HsmNfastKeyValueStorage('simple', 'ksmkey', 'client-config.json')
secrets_manager = SecretsManager(config=config, verify_ssl_certs=True)
all_records = secrets_manager.get_secrets()
You're all set and ready to use Secrets Manager with Entrust NShield HSM
Once setup, the Secrets Manager Entrust integration supports all Secrets Manager SDK functionality. Your code will need to be able to access the nShield HSM in order to manage the decryption of the configuration file when run.
In order to test encryption with the Entrust nShield HSM, use the following command:
Replace "ksmkey" in these examples with the identity in your HSM.
in Linux:
opt/nfast/bin/generatekey -b simple protect=module type=AES size=256 ident=ksmkey
in Windows:
c:\Program Files\nShield\nfast\bin\generatekey -b simple protect=module type=AES size=256 ident=ksmkey
Sign your git commits using an SSH key stored in your Keeper Vault
Signing your git commits is important. It verifies authorship, ensures the integrity of committed content, prevents identity spoofing, and establishes non-repudiation. Using a cryptographic signature with your private key demonstrates a commitment to the authenticity and security of your contributions, building trust among collaborators and protecting the repository from potential tampering and malicious code.
This integration allows developers to sign git commits with an SSH key protected in your Keeper Vault (via Keeper Secrets Manager).
Signs git commits using an SSH key stored in Keeper Vault.
Removes the need for SSH keys on disk for secure DevOps workflows.
Works on Windows, MacOS, and Linux.
Source code at https://github.com/Keeper-Security/git-ssh-sign
In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper account
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with SSH key(s) shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
This integration only accepts JSON format configurations
Git installed with a minimum version of 2.34.0
Login to the Keeper Web Vault or Desktop App
Create a shared folder (e.g. "Git SSH Keys")
Add a SSH Key record to the shared folder
Generate
In order to fetch the SSH key from your vault, this integration uses the zero-knowledge Keeper Secrets Manager.
It expects to find the Secrets Manager configuration file at .config/keeper/ssh-sign.json
in the user's home directory for all systems. If this configuration is not found, it will check ssh-sign.json
as a backup. The Secrets Manager application must have access to the shared folder in which your SSH key is stored.
For help in setting up your application and obtaining your configuration file, you can find detailed instructions here.
After successfully configuring Secrets Manager, you can now configure git to sign your commits automatically. This can be done locally or globally, depending on your needs.
Four pieces of information are required in your config:
Tell git you want to sign all commits.
Tell git you want to use SSH signing over the default GPG signing.
Tell git the location of this integration's executable file. (download here)
Tell git the UID of the SSH key to be used to sign.
We can do this for the local Git repository with the following commands (add the --global
flag to set these globally):
git config commit.gpgsign true
git config gpg.format ssh
git config gpg.ssh.program <path to this binary>
git config user.signingkey <SSH Key UID>
Your git config will now include these attributes:
[commit]
gpgsign = true
[gpg]
format = ssh
[user]
signingKey = <SSH Key UID>
[gpg "ssh"]
program = path/to/ssh-sign
For GitHub to verify the signature used to sign the commit, you will need to upload your SSH key's public key to your GitHub account. GitHub will then use this public key to verify the signature and display the verified
tag in the UI.
For full details on adding your public key to your account, see GitHub's official documentation.
Important: Be sure to set the type of key to "signing key".
For GitLab to verify the signature used to sign the commit, you will need to upload your SSH key's public key to your GitLab account. GitLab will then use this public key to verify the signature and display the verified
tag in the UI.
For full details on adding your public key to your account, see Gitlab's official documentation.
Important: Be sure to set the type of key to "signing key" or "Authentication and signing".
Git is now configured to automatically sign all commits, regardless of whether you use the terminal or an IDE interface to interact with git. It also removes the need to use the -S
flag for commit signing.
You can confirm your commit has been signed with git show --pretty=raw
in the terminal.
Once you have signed a commit and pushed it to GitHub or GitLab, you should see the verified tag next to your commit in the Git history automatically. No further work is needed.
If your repos are stored in your own datacenter, you can verify commits locally on the command line. In order to so this, you will need to create an allowed_signers
file which is a record of authorized signing keys.
Typically, this file is saved either globally at .ssh/allowed_signers
or in the local repo at .git/allowed_signers
. The path to this file needs then to be added to your .gitconfig
or .git/config
file.
git config gpg.ssh.allowedSignersFile path/to/file
Each line of your allowed_signers
file should be a principal of an authorized signing key. The line should start with the email address associated with the public key, separated by a space. For example:
test@example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQvSrBv28KLAjYO7pD91prhlenrm3hZ4B7DdcB/4/H+
The format of the allowed signers file is documented in full here.
While it is correct syntax to have more than one email address associate with a single public key, it is not recommended or currently supported.
To verify your git
history use:
# Verify all commits in the repo
git log --show-signature
# Verify the last commit in the repo
git log --show-signature -1
The source code for this integration is open source and available on GitHub. Issues can be submitted here.
Keeper also provides the ability to authenticate and sign Git commits using the Keeper SSH Agent.
Learn more about the Keeper SSH Agent and specifically Integration with Git
Keeper Secrets Manager integration into GitHub Actions for dynamic secrets retrieval
Retrieve secrets from the Keeper Vault within the Github Actions runner
Set secret credentials as build arguments or environment variables in Github Actions scripts
Copy secure files from the Keeper Vault
The below overview video covers basic setup and ends with a basic Github Actions integration.
This page documents the Secrets Manager GitHub Actions integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The GitHub Actions integration accepts JSON and Base64 format configurations
This action securely retrieves secrets from Keeper and places them to the desired destination of the GitHub Actions runner such as an environment variable, output parameters of the step or to the file.
Below example shows all available functionality of this plugin
on:
push:
branches: [ master ]
jobs:
buildexecutable:
runs-on: ubuntu-latest
name: Build with Keeper secrets
steps:
- name: Retrieve secrets from Keeper
id: ksecrets
uses: Keeper-Security/ksm-action@master
with:
keeper-secret-config: ${{ secrets.KSM_CONFIG }}
secrets: |-
# Reference records by UID
uid123/field/password > PASSWORD
uid234/field/password > env:PASSWORD
uid234/field/login > LOGIN
uid234/custom_field/Cust1 > env:CUST1
uid321/file/Certificate.crt > file:/tmp/Certificate.crt
# Reference records by title - see Keeper Notation for full detail
Server1/field/password > PASSWORD1
Server2/field/password > PASSWORD2
# View secret stored into 'PASSWORD' environment variable
- name: Print password
run: |
echo "Password is ${{ env.PASSWORD }}"
echo "Login is ${{ steps.ksecrets.outputs.LOGIN }}"
You will need to provide two inputs to utilize the Github Actions plugin:
A Keeper Secrets Manager configuration
Github Actions supports JSON type configuration
Keeper Notation queries for secrets
keeper-secret-config
Secrets configuration. See documentation for more information about creating a configuration.
JSON type configuration is supported.
Example:
keeper-secret-config: ${{ secrets.KSM_CONFIG }}
We recommend storing the configuration in a Github Actions secret and accessing it as a variable, as shown in the example above.
secrets
Queries using Keeper Notation to access fields in Keeper records.
The secrets
input is the list of secrets that you need to get from Keeper and put into either an environment variable, GitHub Action output or a file.
Example:
secrets: |-
# Reference records by UID
uid123/field/password > APP_PASSWORD
uid234/field/password > env:DB_PASSWORD
uid321/file/Certificate.crt > file:/tmp/Certificate.crt
# Reference records by title - see Keeper Notation for full detail
App1/field/password > PASSWORD1
DB2/field/password > PASSWORD2
The first part is the id of the secret using the Keeper Notation format.
The second part defines the destination of the secret in the GitHub runner.
field
or custom_field
Notation query result is placed into step's output
Notation query result is placed into environment variable
Not allowed
file
file is downloaded and placed into destination
file is downloaded and placed into destination
file is downloaded and placed into destination
This action uses GitHub Action's built-in masking, so all variables will automatically be masked if printed to the console or to logs. This only obscures secrets from output logs. If someone has the ability to edit your workflows, then they are able to read and therefore write secrets to somewhere else just like normal GitHub Secrets.
Find the Keeper Secrets Manager Github Actions plugin source code in the GitHub repository
Keeper Secrets Manager integration into GitLab for dynamic secrets retrieval
Retrieve secrets from the Keeper Vault within the GitLab Pipeline
Set secret credentials as build arguments or environment variables
Copy secure files from the Keeper Vault
This page documents the Secrets Manager GitLab integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The GitLab integration accepts JSON and Base64 format configurations
A GitLab account with Pipeline creation access
Python3 installed to the GitLab Pipeline job
This action securely retrieves secrets from Keeper and places them to the desired destination of the GitLab Pipeline such as an environment variable or file.
A keeper Secrets Manager configuration is required to utilize the GitLab integration.
1) Create a Keeper Secrets Manager Configuration. See the documentation for details. The GitLab integration supports Base64 and JSON configurations.
2) To save the configuration in GitLab, navigate to GitLab Settings -> CI/CD -> Variables
3) Create a new variable. Key can be set to any name for the variable (use KSM_CONFIG to have the SDKs automatically recognize the configuration). Set Value as the Secrets Manager configuration in Base64 or JSON format.
After creating the variable, you should see it in your GitLab variables as shown below.
Keeper Secrets Manager GitLab Integration setup is complete
In order to use Keeper Secrets Manager with GitLab, first we need to install it from the PyPi registry. This can be achieved by adding following line to the before_script
area:
before_script:
- python3 -m pip install keeper-secrets-manager-cli
If you did not set the Secrets Manager Configuration variable to the name KSM_CONFIG
you need to set it here in the before_script
area
- export KSM_CONFIG=$<SECRETS MANAGER CONFIG VARIABLE>
Inside the GitLab job, retrieve a secrets from the Keeper Vault using the following format:
$(ksm secret notation <KEEPER NOTATION>)
This utilizes the KSM CLI tool to get secrets using Keeper Notation.
After getting a secret, you can set it as an environment variable or file.
Use - export <VARIABLE NAME>=$(ksm secret notation <KEEPER NOTATION>)
to set a secret to an environment variable
Example:
The following job sets a password secret as an environment variable named MY_PWD
and a custom 'isbncode' record field to the environment variable named MY _ISBNCODE
job1:
stage: build
script:
- export MY_PWD=$(ksm secret notation keeper://XXX/field/password)
- export MY_ISBNCODE=$(ksm secret notation keeper://XXX/custom_field/isbncode)
Replace XXX
with a record UID in the above example.
Use - ksm secret download -u <UID> --name <SECRET FILENAME> --file-output "<OUTPUT FILENAME>"
to get a file from the Keeper Vault and save it as a file to your GitLab Pipeline job.
Example:
The following job gets a file named "mykey.pub" that is attached to a Keeper record and saves its contents into file name "mykey.pub" in the local "tmp" folder
job1:
stage: build
script:
- ksm secret download -u XXX --name "mykey.pub" --file-output "/tmp/mykey.pub"
Replace XXX
with a record UID in the above example.
The example below shows all available functionality of this integration
image: python:latest
before_script:
- python3 -m pip install keeper-secrets-manager-cli
job1:
stage: build
script:
- export MY_PWD=$(ksm secret notation keeper://XXX/field/password)
- export MY_ISBNCODE=$(ksm secret notation keeper://XXX/custom_field/isbncode)
- ksm secret download -u XXX--name "mykey.pub" --file-output "/tmp/mykey.pub"
- file /tmp/mykey.pub
Replace XXX
in the example above with a record UID.
Sync secrets from the Keeper Vault with GCP Secret Manager
The Keeper Secrets Manager CLI tool sync
command allows you to push secrets from the Keeper Vault to a target GCP Secret Manager project, overwriting the existing values in the target location. This allows the Keeper Vault to be the single source of truth for any services or scripts in GCP that utilize GCP Secret Manager.
Use secrets from the Keeper Vault as the source of truth for GCP Secret Manager
Seamlessly start using secrets from the Keeper Vault with your existing GCP scripts and services
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper subscription
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
A GCP account with GCP Secret Manager, and optionally the ability to create IAM service account credentials
To configure the KSM CLI tool, a profile needs to be created with the Keeper Secrets Manager One Time Access Token.
The simplest way to do this is to initialize the default profile with the following command:
ksm profile init <TOKEN>
For information on creating multiple profiles and other options, see the profile documentation
To use the KSM sync to GCP, GCP Secrets Manager requires standard IAM security credentials with Secret Manager Admin
role enabled for the project or on the service account principal to sync.
Secret Manager Access control with IAM:
https://cloud.google.com/secret-manager/docs/access-control
GCP instructions for creating Service Account Credentials (optional):
https://developers.google.com/workspace/guides/create-credentials#service-account
The KSM CLI needs the credentials for the GCP service account to set secrets. These credentials are stored in a Keeper record which the CLI tool can access using Keeper Secrets Manager.
Record fields with the following labels are required on the credentials record:
"Google Cloud Project ID"
"Google Application Credentials"
- optional
A custom record type can be created with the required fields, which makes it easy and clean to create a record.
To create a custom record type, go to the "Custom Record Types" tab in the Keeper Vault and hit "Create Type". Create a new record type with hidden fields that have the correct field label, then click "Publish" to create the new record type.
Then simply create a new record of the GCP Credentials type and enter the details into the corresponding fields.
Make sure this new record is moved to a Shared Folder that is associated with your Secrets Manager application.
To create a credentials record without creating a new record type, the required fields can be added as custom fields to a standard record.
Create a new record of any type, then add Custom Fields of the 'Hidden Field' type for each required GCP field. Click "Edit Label" to change the labels for the corresponding field name.
Then fill in each custom field and hit "Save" to save the record.
The KSM CLI sync
command identifies which values to set using mappings that are defined on the command call. For each mapping passed to the command, a value with the given name will be populated with the given value from the Keeper Vault.
These mappings follow this format:
--map "VALUE KEY" "KEEPER NOTATION"
VALUE KEY
is the key name that the value will be assigned in GCP Secret Manager
KEEPER NOTATION
is a Keeper notation query of a value from a keeper record to set to the key
Keeper notation is a query notation used by Keeper Secrets Manager to identify specific record values. The notation follows the general format of: UID/
[field|custom_field]/fieldname
for example: ae3d[...]d22e/field/password
See the Keeper Notation documentation for more information
Full Mapping Example:
--map "MySQL_PWD" "jd3[...]i-fd/field/password"
Multiple mappings can be added to a single sync
command
--map "MySQL_PWD" "jd3[...]i-fd/field/password" --map "MySQL_Login" "jd3[...]i-fd/field/login"
Ensure that the records referenced by the Keeper Notation queries are in a shared folder that is shared with your Secrets Manager application
KSM sync is now ready to run
To run the sync, use the KSM CLI sync
command with the credentials record and value mapping.
Put together the KSM sync command with the GCP type. The format looks like the following:
ksm sync --type gcp --credentials [UID] --map [...] --map [...]
The sync command supports running a dry-run which will identify all changes that will be made to your GCP Secret Manager values without actually pushing the values or making changes. Use this to make sure your mapping queries are constructed properly.
ksm sync --type gcp --credentials [UID] --map [...] --map [...] --dry-run
When ready, run the sync command without the dry-run option. This will push values from your Keeper Vault to GCP Secret Manager
ksm sync --type gcp --credentials [UID] -m [...] -m [...]
Protect Secrets Manager connection details with Google Cloud Key Management
Keeper Secrets Manager integrates with Google Cloud Key Management in order to provide encryption for Keeper Secrets Manager configuration files. With this integration, you can protect connection details on your machine while taking advantage of Keeper's zero-knowledge encryption of all your secret credentials.
Encrypt and Decrypt your Keeper Secrets Manager configuration files with Google Cloud Key Management.
Protect against unauthorized access to your Secrets Manager connections.
Requires only minor changes to code for immediate protection. Works with all Keeper Secrets Manager SDK functionality.
To configure, Google Cloud Key Management with Keeeper Security you need service account keys ended with .json
.
Key structure that is supported by this integration is `projects/<project_name>/locations/<location_name>/keyRings/<key_ring_name>/cryptoKeys/<key_name>/cryptoKeyVersions/<key_version>`
Support the Java/Kotlin Secrets Manager SDK.
Required GCP package google-cloud-kms
Google Cloud Key Management needs ENCRYPT
and DECRYPT
permissions.
Supports the JavaScript Secrets Manager SDK
Requires the @google-cloud/kms
package from GCP SDK.
GCP CKM Key needs ENCRYPT
and DECRYPT
permissions.
Supports the Python Secrets Manager SDK
Requires google-cloud-kms
package
GCP CKM Key needs ENCRYPT
and DECRYPT
permissions.
Supports the .Net Secrets Manager SDK
Requires Google.Apis.CloudKMS.v1
GCP CKM Key needs ENCRYPT
and DECRYPT
permissions.
Supports the GoLang Secrets Manager SDK
GCP CKM Key needs ENCRYPT
and DECRYPT
permissions.
Setting up project using Gradle or Maven
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("com.keepersecurity.secrets-manager:core:17.0.0")
implementation("com.keepersecurity.secrets-manager:gcp:1.0.0")
implementation ("com.google.cloud:google-cloud-kms:2.62.0")
implementation ("com.google.auth:google-auth-library-oauth2-http:1.33.1")
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
implementation("com.fasterxml.jackson.core:jackson-core:2.18.2")
implementation("com.google.code.gson:gson:2.12.1")
implementation("org.slf4j:slf4j-api:1.7.32"){
exclude("org.slf4j:slf4j-log4j12")
}
implementation("ch.qos.logback:logback-classic:1.2.6")
implementation("ch.qos.logback:logback-core:1.2.6")
implementation("org.bouncycastle:bc-fips:1.0.2.4")
}
Maven
<!-- KMS-core -->
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>core</artifactId>
<version>[17.0.0,)</version>
</dependency>
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>gcp</artifactId>
<version>1.0.0</version>
</dependency>
<!-- gcp-kms -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-kms</artifactId>
<version>2.62.0</version>
</dependency>
<!-- gcp auth -->
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>1.33.1</version>
</dependency>
<!--gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.12.1</version>
</dependency>
<!--jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!--jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!-- slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
<scope>runtime</scope>
</dependency>
<!-- logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
<scope>compile</scope>
</dependency>
<!-- logback-core -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.6</version>
<scope>compile</scope>
</dependency>
<!-- bc-fips -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>1.0.2.4</version>
</dependency>
The Secrets Manager Google Cloud Key Management module can be installed using npm
npm install @keeper-security/secrets-manager-gcp
The Secrets Manager Google Cloud Key Management module can be installed using pip
pip3 install keeper-secrets-manager-storage-gcp-kms
The Secrets Manager Google Cloud Key Management module can be installed using dotnet nuget package manager.
dotnet add package Keeper.SecretsManager.GCPKeyManagement
The Secrets Manager Google Cloud Key Management module Integration can be installed using
go get github.com/keeper-security/secrets-manager-go/integrations/gcp
To enable secure authentication with Google Cloud Platform (GCP), generate a Service Account key in JSON format. This credential file will serve as the authentication mechanism for interacting with GCP services programmatically.
Once GCP connection has been configured, You can fetch the Key to encrypt / decrypt KSM configuration using integration and you need to tell the Secrets Manager SDK to utilize the KMS as storage.
Once setup, the Secrets Manager GCP Key Vault integration supports all Secrets Manager SDK functionality. Your code will need to be able to access the GCP CKM Keys in order to manage the encryption and decryption of the KSM configuration file. Using Specified Connection credentials
To do this, create GcpKeyValueStorage
instance and use this in SecretManagerOptions
constructor.
The GcpKeyValueStorage
will require the name of the Secrets Manager configuration file , gcp credential file and key details of Cloud Key Management.
import java.security.Security;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import static com.keepersecurity.secretsManager.core.SecretsManager.initializeStorage;
import com.keepersecurity.secretsmanager.gcp.GcpKeyValueStorage;
import com.keepersecurity.secretsmanager.gcp.GcpSessionConfig;
import com.keepersecurity.secretsManager.core.SecretsManagerOptions;
public class Test {
public static void main(String args[]){
String oneTimeToken = "One_Time_Token";
String projectId = "projectId";
String location = "cloud_region";
String keyRing = "key_ring_name";
String keyId = "key_id";
String keyVersion = "key_version";
String configFileLocation = "client_config_test.json";
String credentialFileLocation = "<path_with_name_of_gcp_cred_file.json>";
Security.addProvider(new BouncyCastleFipsProvider());
try{
GcpSessionConfig sessionConfig = new GcpSessionConfig(projectId, location, keyRing, keyId, keyVersion, credentialFileLocation);
GcpKeyValueStorage storage = new GcpKeyValueStorage(configFileLocation, sessionConfig);
initializeStorage(storage, oneTimeToken);
SecretsManagerOptions options = new SecretsManagerOptions(storage);
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
To do this, use GCPKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an keyConfig
, gcpsessionConfig
(generated by GCPKSMClient
) , and the name of the Secrets Manager configuration file
which will be encrypted by GCP Cloud Key Management.
import {GCPKeyValueStorage,GCPKeyConfig,GCPKSMClient,LoggerLogLevelOptions} from "@keeper-security/secrets-manager-gcp";
const getKeeperRecordsGCP = async () => {
const gcpCredFile = "<path_with_name_of_gcp_cred_file.json>"
const keyConfig2 = new GCPKeyConfig("<key_version_resource_url_1>");
const keyConfig = new GCPKeyConfig("key_version_resource_url_2");
const gcpSessionConfig = new GCPKSMClient().createClientFromCredentialsFile(gcpCredFile)
let config_path = "<path to client-config.json>"
let logLevel = LoggerLogLevelOptions.debug;
const oneTimeToken = "<one_time_token>";
const storage = await new GCPKeyValueStorage(config_path, keyConfig, gcpSessionConfig, logLevel).init();
await initializeStorage(storage, oneTimeToken);
const {records} = await getSecrets({storage: storage});
console.log(records)
const firstRecord = records[0];
const firstRecordPassword = firstRecord.data.fields.find((x: { type: string; }) => x.type === 'bankAccount');
console.log(firstRecordPassword.value[0]);
}
console.log("start")
getKeeperRecordsGCP()
To do this, use GCPKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require gcp_key_config
(generated by GCPConfig
), gcp_session_config
object (generated by GCPKMSClientConfig
) and the name of the Secrets Manager configuration file
which will be encrypted by GCP Cloud Key Management.
from keeper_secrets_manager_storage_gcp_kms import GCPKeyConfig, GCPKeyValueStorage, GCPKMSClientConfig
from keeper_secrets_manager_core import SecretsManager
# Example key: projects/<project>/locations/<location>/keyRings/<keyring>/cryptoKeys/<key_name>/cryptoKeyVersions/<version>
gcp_key_config_1 = GCPKeyConfig("<key_resource_uri_1>")
gcp_key_config_2 = GCPKeyConfig("<key_resource_uri_2>")
gcp_cred_file_location_with_name = "<path_with_name_of_gcp_cred_file.json>"
gcp_session_config = GCPKMSClientConfig().create_client_from_credentials_file(gcp_cred_file_location_with_name)
config_path = "ksm_config.json"
one_time_token = "<one_time_token>"
storage = GCPKeyValueStorage(config_path, gcp_key_config_1, gcp_session_config)
secrets_manager = SecretsManager(token=one_time_token, config=storage)
all_records = secrets_manager.get_secrets()
first_record = all_records[0]
print(first_record)
To do this, use GCPKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an keyConfig
(generated by GCPKeyConfig
), gcpSessionConfig
object (generated by GCPKMSClient
), and the name of the Secrets Manager configuration file
which will be encrypted by GCP Cloud Key Management.
using System;
using System.Linq;
using System.Threading.Tasks;
using SecretsManager;
using GCPKeyManagement;
using Microsoft.Extensions.Logging;
public class Program {
private static async Task getOneIndividualSecret() {
Console.WriteLine("execution started");
string key1ResourceName = "<KEY1ResourceURL>";
string key2ResourceName = "<Key2ResourceURL>";
string gcpConfigFilePath = "<GCP config file path with name>";
var keyConfig = new GCPKeyConfig(key1ResourceName);
var gcpSessionConfig = new GCPKMSClient().CreateClientFromCredentialsFile(gcpConfigFilePath);
var ksmConfigPath = "ksm_config.json";
var dotnet_access_token = "[One_Time_Token]";
var loggerFactory = LoggerFactory.Create(builder => {
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger < GCPKeyValueStorage > ();
var gcp_storage = new GCPKeyValueStorage(keyConfig, gcpSessionConfig, ksmConfigPath, logger);
SecretsManagerClient.InitializeStorage(gcp_storage, dotnet_access_token);
}
static async Task Main() {
await getOneIndividualSecret();
}
}
To do this, use NewGCPKeyVaultStorage
as your Secrets Manager storage in the NewSecretsManager
The NewGCPKeyVaultStorage
requires the following parameters to encrypt the KSM configuration using GCP Cloud Key Management:
ksmConfigFileName
: The file name of KSM configuration.
keyResourceName
: ProvidekeyResourceName
of Google Cloud Key Management
credentialFileWithPath
: Provide file path with name of GCP credential file.
package main
import (
"encoding/json"
"fmt"
"github.com/keeper-security/secrets-manager-go/core"
gcpkv "github.com/keeper-security/secrets-manager-go/integrations/gcp"
)
func main() {
credentialFileWithPath := "<Location of credential file ending with .json>"
keyResourceName := "<Key_Resource_Name>"
ksmConfigFileName := "ksmConfig.json"
oneTimeToken := "<One_Time_Access_Token>"
cfg := gcpkv.NewGCPKeyVaultStorage(ksmConfigFileName, keyResourceName, credentialFileWithPath)
client_options := &core.ClientOptions{
Token: oneTimeToken,
Config: cfg,
}
fmt.Printf("Client ID Value: %s", cfg.Get(core.KEY_CLIENT_ID))
secrets_manager := core.NewSecretsManager(client_options)
secrets, err := secrets_manager.GetSecrets([]string{})
if err != nil {
// do something
fmt.Printf("Error while fetching secrets: %v\n", err)
}
for _, record := range secrets {
fmt.Printf("Records: %v\n", record)
}
}
We can change key that is used for encrypting the KSM configuration, examples below show the code needed to use it
//The method changeKey(keyID) will be used to encrypt the KSM config file with new Key and version.
GcpKeyValueStorage storage = new GcpKeyValueStorage(configFileLocation, sessionConfig);
String newKeyID = "<new Key ID>";
boolean isChanged = storage.changeKey(keyId);
System.out.println("Key Changed: "+isChanged); // Change the key for encryption/decryption
// To change the GCP CKM key used for encryption, you can call the `changeKey` method on the `OciKeyValueStorage` instance.
const storage = await new GCPKeyValueStorage(configPath,keyConfig,gcpSessionConfig).init();
await storage.changeKey(keyConfig2);
storage = GCPKeyValueStorage(config_path, gcp_key_config_1, gcp_session_config)
is_changed = storage.change_key(gcp_key_config_2)
print("Key is changed:", is_changed)
// To change the Google CKM key used for encryption, you can call the `ChangeKeyAsync` method on the `GCPKeyValueStorage` instance.
// using Microsoft.Extensions.Logging;
var gcp_storage = new GCPKeyValueStorage(keyConfig2, gcpSessionConfig, path,logger);
bool isChanged = gcp_storage.ChangeKeyAsync(keyConfig1).Wait();
Console.WriteLine(isChanged)
// If you want to change the key not gcpp config, then pass nil in place of oracle config.
cfg := gcpkv.NewGCPKeyVaultStorage(ksmConfigFileName, keyResourceName, credentialFileWithPath)
updatedResourceName := "<Updated Key Resource Name>"
isChanged, err := cfg.ChangeKey(updatedResourceName, "")
if err != nil {
// do something
}
fmt.Printf("Key changed: %v\n", isChanged)
We can decrypt the config if current implementation is to be migrated onto a different cloud or if you want your raw credentials back. The function accepts a boolean which when set to true will save the decrypted configuration to file and if it is false, will just return decrypted configuration.
GcpKeyValueStorage storage = new GcpKeyValueStorage(configFileLocation, sessionConfig);
storage.decryptConfig(false); // Set false as a parameter to extract only plaintext.
//OR
storage.decryptConfig(true); // Set true as a parameter to extract plaintext and save config as a plaintext.
const storage = await new GCPKeyValueStorage(configPath,keyConfig,gcpSessionConfig).init();
await storage.decryptConfig(true); // Set true as a parameter to extract plaintext and save config as a plaintext.
// OR
await storage.decryptConfig(false); // Set false as a parameter to extract only plaintext.
storage = GCPKeyValueStorage(config_path, gcp_key_config_1, gcp_session_config)
# Extract only plaintext
plaintext = storage.decrypt_config(False)
print(plaintext)
# OR extract plaintext and save config as plaintext
plaintext = storage.decrypt_config(True)
print(plaintext)
# To decrypt the config file and save it again in plaintext, you can call the `DecryptConfigAsync` method on the `OracleKeyValueStorage` instance.
var gcp_storage = new GCPKeyValueStorage(keyConfig2, gcpSessionConfig, path,logger);
var conf = await gcp_storage.DecryptConfigAsync(false); # Set false as a parameter to extract only plaintext.
Console.WriteLine(conf);
# OR
var conf = await gcp_storage.DecryptConfigAsync(true); # Set true as a parameter to extract plaintext and save config as a plaintext.
Console.WriteLine(conf);
cfg := gcpkv.NewGCPKeyVaultStorage(ksmConfigFileName, keyResourceName, credentialFileWithPath)
plainText, err := cfg.DecryptConfig(false)
if err != nil {
// do something
fmt.Printf("Error while decrypting config: %v", err)
}
plainText, err := cfg.DecryptConfig(true) // Set true as a parameter to extract plaintext and save config as a plaintext.
if err != nil {
// do something
fmt.Printf("Error while decrypting config: %v", err)
}
You're ready to use the KSM integration 👍
Use Keeper Secrets Manager with HashiCorp Vault as a Data Source
The Keeper Secrets Manager HashiCorp Vault integration allows you to use secrets from the Keeper Vault as a data store for HashiCorp Vault.
Use Secrets from the Keeper Vault with HashiCorp Vault scripts and commands
Read secret information using HashiCorp Vault
Update secret information from HashiCorp Vault
This page documents the Secrets Manager HashiCorp Vault integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper subscription
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The HashiCorp Vault integration accepts our Base64 format configurations
HashiCorp Vault command line, and a Vault server running
See the HashiCorp Vault documentation for how to install
Download the latest integration release from the KSM GitHub page:
Look for a vault-plugin release in the list of releases that matched your platform.
Unzip the plugin and place it into your HashiCorp Vault plugins directory. In this example the folder is located at C:\vault\plugins
(Windows) or /etc/vault/vault_plugins
(MacOS/ Linux)
For testing the plugin or to allow quick development, development mode can be used to quickly get the HashiCorp Vault CLI up and running.
HashiCorp Vault CLI development mode utilizes volatile in-memory storage. Any actions taken on secrets in the Keeper Vault are immediate, but the plugin will need to be re-enabled each time the HashiCorp Vault is started in dev mode.
When ready to move to production, the plugin will need to be registered using a SHA256 hash of the plugin.
vault plugin register -command=vault-plugin-secrets-ksm.exe -sha256=<SHA256> secret vault-plugin-secrets-ksm
vault secrets enable -path=ksm vault-plugin-secrets-ksm
You will need a hash of the plugin file to enable it with production HashiCorp Vault servers. This hash can be generated for the Secrets Manager plugin.
Windows 7 and later comes with a built-in tool called CertUtil that can be used to generate the SHA256 hash. This example will show how to generate a SHA hash using CertUtil, but any tool that can generate a file hash in SHA256 will work.
CertUtil -hashfile C:\vault\plugins\vault-plugin-secrets-ksm.exe SHA256
vault plugin register -sha256=<SHA256> secret vault-plugin-secrets-ksm
vault secrets enable -path=ksm vault-plugin-secrets-ksm
You will need a hash of the plugin file to enable it with production HashiCorp Vault servers. This hash can be generated for the Secrets Manager plugin.
Using the built-in shasum function this can be generated like this:
shasum -a 256 /etc/vault/vault_plugins/vault-plugin-secrets-ksm
Depending on your OS, you may use the sha256sum
command instead
sha256sum /etc/vault/vault_plugins/vault-plugin-secrets-ksm
Now that the HashiCorp Vault plugin is installed, a secure connection to the Keeper Vault needs to be established so that secret credentials can be accessed. To create this connection, a Secrets Manager configuration needs to be created and assigned to the plugin.
A Secrets Manager configuration can be created using Keeper Commander or the Secrets Manager CLI. See the Configuration Documentation for more information on creating a configuration.
Once a configuration has been generated, set it to a variable to be used by the Vault Plugin.
vault write ksm/config ksm_config=<BASE64_CONFIG...>
vault list ksm/records
The records will be shown in the following format:
Keys
----
UID RECORDTYPE: RECORDTITLE
Example:
C:\Vault> vault list ksm/records
Keys
----
Hf6of4uo_2aD7IMjn4VPuA login: My Record
Lv3B9ObAjxdpdBl0IJ3oow folder: 4 record(s)
Oq3fFu14hZY00d7sp3EYNA MyCustomType: My New Record (Custom record type)
YDx58Q94dE1k9B367ZVz1w databaseCredentials: MySQL Credentials
qe3EWYn840uR0bOMyZ2b0Q login: Dropbox Login
vault read ksm/record uid=<UID>
Example:
C:\Vault> vault read ksm/record uid=Hf6r5Zuo_2aD7IMjn4VPuA
Key Value
--- -----
fields [map[type:login value:[username@email.com]] map[type:password value:[Pd08fi@1]]]
notes Example Login Record
title Sample KSM Record
type login
vault read ksm/record/totp uid=<UID>
Example:
C:\Vault> vault read ksm/record/totp uid=32t82-oRu-79yplIAZ6jmA
Key Value
--- ---
TOTP [map[token:392528 ttl:22 url:otpauth://totp/Generator:?secret=JBSWY3DPEZAK3PXP&issuer=Generator&algorithm=SHA1&digits=6&period=30]]
UID 32t82-oRu-79yplIAZ6jmA
To update an existing secret, use the following command, passing in JSON data that represents the updated secret's information. The corresponding record in the Keeper Vault will be updated to match the JSON data passed.
vault write -format=json ksm/record uid=<UID> data=@update.json
In this example, the updated data is passed in from a file, this is recommended for cleaner and more simple CLI commands. The JSON data can be passed in on the command line, but quotes will need to be escaped.
Example data file:
{
"fields": [
{
"type": "login",
"value": [
"username@email.com"
]
},
{
"type": "password",
"value": [
"kjh4j3245DCD!d"
]
}
],
"notes": "\tThis record was updated with the Vault KSM plugin",
"title": "Sample Updated Record",
"type": "login"
}
Similar to updating a secret, create a new secret by passing JSON data to the following command:
vault write -format=json ksm/record/create folder_uid=<UID> data=@data.json
In this example, the updated data is passed in from a file, this is recommended for cleaner and more simple CLI commands. The JSON data can be passed in on the command line, but quotes will need to be escaped.
Example data file:
{
"fields": [
{
"type": "login",
"value": [
"username@email.com"
]
},
{
"type": "oneTimeCode",
"value": [
"otpauth://totp/Generator:?secret=JBSWY3JP9HPK3PXP\u0026issuer=Generator\u0026algorithm=SHA1\u0026digits=6\u0026period=30"
]
}
],
"notes": "\tExample Record wth TOTP",
"title": "Sample TOTP SECRET",
"type": "login"
}
vault delete ksm/record uid=Oq3fFu14hZY00d7sp3EYNA
Using Keepers Secrets Manager to store your Heroku application sensitive secrets.
Securely store secret credentials in the Keeper Vault and use them in Heroku without exposure
Copy files from the Keeper vault into your Heroku Apps
Utilize other Secrets Manager SDK features (such as record creation and TOTP codes) from Heroku
Heroku offers the ability to store configuration variables for your application. The problem is it stores the values in a viewable format. Keeper Secrets Manager allows you to store your sensitive secrets offsite in a zero knowledge environment.
The Keeper Secrets Manager SDK can be used with Heroku
See the example project below to get an idea of the capabilities of Keeper Secrets Manager with Heroku
This example uses the Keeper Secrets Manager SDK to retrieve a webhook token to send messages to a channel in Slack from a Heroku web application.
The first step is getting a webhook token from your instance of Slack. Login into the Slack website and go to Your Apps.
Create a new app by clicking the Create New App button and selecting From scratch from the dialog box. At this point enter an App Name and select the workspace you want to develop your app in.
Next click the Incoming Webhooks button.
Turn On the Incoming Webhooks. This will show the Webhook URLs for Your Workspace section. Click the Add New Webhook to Workspace button.
Then select a channel in your workspace.
Now at the bottom of the Incoming Webhooks page, there will be a Webhook URL. For this example, Copy the url. This will be placed in Keeper Vault record.
In the Keeper Vault create a Login record to hold the Slack Webhook URL in the Shared Folder. The Shared Folder can be added used by an Application. Reference the Quick Start Guide for more details.
Copy the Webhook URL into the Website Address field of the Login record and save. Once saved click on the information icon, , of the record to see the Record UID. You can copy a Record UID URL into the clipboard which will contain the actual Record UID. You only need that part of the URL.
For this example, a Heroku account and Python 3 are requiered. The next step is to install the Heroku CLI following their instructions.
With the Heroku CLI installed an application can be created.
$ heroku create
Creating app... done, ⬢ random-name-30564
https://random-name-30564.herokuapp.com/ | https://git.heroku.com/random-name-30564.git
That will create a blank Git repository that will be used for the application. The Git repository can then be cloned. There will be a warning about it being empty. After that change into the repository directory.
$ git clone https://git.heroku.com/random-name-30564.git
Cloning into 'random-name-30564'...
warning: You appear to have cloned an empty repository.
$ cd random-name-30564
With the repository cloned, the config variables can be set. There are two config variables that need to be set. The first is RECORD_UID which the Record UID of the record that contains the Webhook URL. The second is KSM_CONFIG which contains the Base64 encoded Secrets Manager configuration.
$ heroku config:set RECORD_UID=XXXXXX
Setting RECORD_UID and restarting ⬢ random-name-30564... done, v11
RECORD_UID: XXXXXX
$ heroku config:set KSM_CONFIG=ewogI ..... Igp9
Setting KSM_CONFIG and restarting ⬢ random-name-30564... done, v11
KSM_CONFIG: ewogI ..... Igp9
With the configuration variables in place, the application can be added. The first step is to defined the requirements for the Python 3 application. The requirements.txt file contains Flask used for the website, slack_sdk used to communicate with Slack, and keeper-secrets-manager-core to communicate with Secrets Manager.
$ cat << EOF > requirements.txt
Flask
slack_sdk
keeper-secrets-manager-core
EOF
In your preferred editor save the contents of the following to app.py.
import os
from flask import Flask, request
from slack_sdk.webhook import WebhookClient
from keeper_secrets_manager_core import SecretsManager
app = Flask(__name__)
secret_manager = SecretsManager()
record_id = os.environ.get("RECORD_UID")
webhook = WebhookClient(secret_manager.get_notation("{}/field/url".format(record_id)))
@app.route('/')
def hello():
message = request.args.get("message")
if message is not None and message != "":
response = webhook.send(text=message)
html = """
<html>
<head><title>Send a Slack Message</title></head>
<body>
<form method="GET">
Message:
<input type="text" name="message" />
<input type="submit" />
</form>
</body>
</html>
"""
return html
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)
This is a simple Flask web application that will display a form input box and a submit button. Any text entered into the input box will be sent to your Slack channel.
The last part is to give Heroku information on how to start your application using the Procfile file.
$ cat << EOF > Procfile
web: python app.py
EOF
Now the application is ready to be run. Add the file it your the Git repository and push the main branch. This will build and launch the application.
$ git add requirements.txt app.py Procfile
$ git commit -m "Initial Commit"
[main 0f31f23] Initial Commit
3 file changed, 0 insertion(+), 0 deletion(-)
...
$ git push origin main
...
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/python
remote: -----> Python app detected
remote: -----> No Python version was specified. Using the same version as the last build: python-3.9.9
remote: To use a different version, see: https://devcenter.heroku.com/articles/python-runtimes
remote: -----> No change in requirements detected, installing from cache
remote: -----> Using cached install of python-3.9.9
remote: -----> Installing pip 21.3.1, setuptools 57.5.0 and wheel 0.37.0
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 62.4M
remote: -----> Launching...
remote: Released v13
remote: https://random-name-30564.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/random-name-30564.git
89b16a2..fda1835 main -> main
At this point you can visit the web site by either going to the URL, i.e. https://random-name-30564.herokuapp.com/
, or by using the following command line.
$ heroku open
This will display a simple web site. Enter a message and click submit.
The message should appear in the channel for the created Webhook.
Keeper Secrets Manager integration into Jenkins for dynamic secrets retrieval
Retrieve secrets from the Keeper Vault with Jenkins
Use Keeper Secrets Manager with Jenkins Freestyle or Jenkins Pipeline projects
Get files from the Keeper vault
This page documents the Secrets Manager Jenkins integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper account
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
The plugin uses SecureRandom which can be slow on certain systems due too low entropy.
On Linux, executing cat /proc/sys/kernel/random/entropy_avail
will show the available entropy. If below 200, you'll need to software like rng-tools
to generate entropy.
The Jenkins plugin for Keeper Secrets Manager allows you retrieve secrets from the Keeper Vault and place the values into environmental variables or files within the builder and workflow pipelines.
The Keeper Secrets Plugin can be installed from Jenkins' the list of available plugins. Within Jenkins navigate to Manage Jenkins->Manage Plugins->Available. Search for "Keeper Secrets Manager" using the search bar to find the plugin. Check the Install checkbox and an Install button. You can choose to restart Jenkins immediately, or later to complete installation. When Jenkins restarts, you will be able to use the plugin.
If you had installed a beta version of the Keeper Secrets Manager plugin you will need to remove it first. On the tab Manage Jenkins->Manage Plugins->Installedclick the Uninstall button. It will not show up on the Available tab if already installed.
Find the Keeper Secrets Manager Jenkins Plugin source code in the GitHub repository
If you haven't done so already, follow the Quick Start Guide and create a Secrets Manager application and Client Device specifically for Jenkins usage.
Using Keeper Commander, generate a Client Device for Jenkins. Make note of the One Time Access Token.
My Vault> secrets-manager client add --app MyApplication
------------------------------------------------------------------
One Time Access Token: XX:XXXXXXXXXXXXX
------------------------------------------------------------------
By default, the Client Device is locked to the first IP address that uses the One Time Access Token. If your Jenkins server has potentially multiple external IP addresses, you may want to add the--unlock-ip
parameter when generating the One Time Access Token.
For more information on creating Secrets Manager Applications and Clients, see the Secrets Manager Commands documentation.
The first step in using the plugin is creating a Jenkins credential from a One Time Access Token.
Within Jenkins, navigate to Manage Jenkins > Manage Credentials > (scope) > Add Credentials, then select Keeper Secrets Manager in the Kind dropdown. You will be presented with a form that looks like the following:
Set a Description for the credential to make it easier to find in other areas of Jenkins.
Paste the One Time Access Token into the form field and save.
When you save the credential, the Jenkins server will connect to the Keeper Secrets Manager service and initialize the One Time Access Token. It will then populate the required encryption keys and client identifiers inside Jenkins for subsequent requests. At this point the One Time Access Token field will be cleared out.
If there was a problem initializing the One Time Access Token, the error message will be placed in the field. The Jenkins credential cannot be used until there is no errors. You are able to create a new One Time Access Token and replace the information that already existing for a credential. Just use Commander to create another token, cut-n-paste it into the Token field, and save.
You will not be able to see the Client Id, Private and App Keys. You can replace them from an existing config by clicking the Replace Keys... button.
Clicking the Replace button will allow you to cut-n-paste values from an existing configuration into Jenkins. You can then validate the id and keys by clicking the the Validate Credential button.
For a Freestyle project the environmental variable injection is performed via a Build step.
In the Add build step dropdown, select Keeper Secrets Manager.
In the Credential dropdown select the Keeper Secrets Manager credential that was created in the prior steps.
Using Keeper Notation syntax, the environmental variable is magically replaced with the matching value from the record in the Keeper vault. You can reference any field within the Keeper vault secret such as login, password, custom field or filename.
Then select the destination for the secret. A secret can be placed into an environmental variable or a file within the build's workspace.
You can add multiple environmental variable to the Build step by clicking on "Add Secret" and populating the environmental variable and notation fields.
Keeper Notation Syntax
Use the Keeper notation format to select which record field to use as your secret. Keeper notation has the following format:
keeper://<Record UID>/field/<field name>
Where "Record UID" is the UID of the record which contains the secret credential as a field and "field name" is the field that credential is stored as, such as "password"
Here's an example: keeper://3FXqmP5nFKwju0H8pl0DmQ/field/password
Using Your Secrets
The populated environment variables will available to the following build steps. You can even add another Keeper Secrets Manager step and select secret from a different account or application.
You can use and view the environment variables in a Execute Shell step. For example:
#!/bin/bash
my_app --login "${MY_LOGIN}"
echo "My Login = ${MY_LOGIN}"
In the above the environmental variable MY_LOGIN will be passed a parameter to the application my_app, however the echo statement will result in the text "****" the console. Text based secrets are actively redacted in the console.
The Keeper Secret Manager plugin can be used inside a Jenkinsfile using a step that has the label withKsm
. Below is an example.
pipeline {
agent any
stages {
stage('Hello') {
steps {
withKsm(application: [
[
credentialsId: '5142ceb84e9b4a2a9179cc5b6fe2798b',
secrets: [
[destination: 'env', envVar: 'MY_LOGIN', filePath: '',
notation: '1adh_WZxtbbHWqf6IALMVg/field/login'],
[destination: 'env', envVar: 'MY_SEC_PHONE_NUM', filePath: '',
notation: 'Atu8tVgMxpB-iO4xT-Vu3Q/custom_field/phone[1][number]'],
[destination: 'file', envVar: '', filePath: 'img.png',
notation: 'V8lFbio0Bs0LuvaSD5DDHA/file/IMG_0036.png']
]
]
]) {
sh'''
# Will be redacted in console
echo "MY_LOGIN = ${MY_LOGIN}"
echo "MY_SEC_PHONE_NUM = ${MY_SEC_PHONE_NUM}"
./my/build/script --login "${MY_LOGIN}" --phone "${MY_SEC_PHONE_NUM}"
file img.png
'''
}
}
}
}
}
The Keeper Secrets Manager snippet can be created using the Pipeline Syntax snipper editor inside of Jenkins. Select withKsm from the Sample Step dropdown, then add a Keeper Secrets Manager Application, which will allow you to select the credentials and add secrets.
When you are finished setting up your application, credentials, and secrets, you can click the Generate Pipeline Script to generate the withKsm block. This snippet can then be added to your Jenkinsfile.
Keeper Secrets Manager integration into Keeper Connection Manager for dynamic secrets retrieval
Retrieve secrets from Keeper when launching Remote RDP, SSH, MySQL and other connections
Protect secret configuration settings in the Keeper Vault
Provide privileged sessions without exposing credentials to the end-user
This page documents the Secrets Manager <> Keeper Connection Manager integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper account
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The Connection Manager integration accepts the Base64 format configuration
This integration securely retrieves secrets from Keeper for use in establishing remote connections via RDP, SSH, VNC, MySQL, K8s and other protocols.
Step by Step documentation for activating Keeper Secrets Manager with Keeper Connection Manager can be found at the link below:
Synchronize Secrets from Keeper Secrets Manager with the K8s External Secrets Operator
Kubernetes External Secrets Operator injects secrets into Kubernetes by synchronizing them from various external APIs. This guide primarily focuses on the setup process for External Secrets, facilitating the synchronization of secrets from your Keeper Vault into Kubernetes.
The External Operator documentation can be found at this link.
Seamless synchronization of secrets from Keeper Vault into Kubernetes via External Secrets.
Real-time access to secrets from Keeper Vault across all pods.
Before proceeding with the setup, ensure you have the following:
Keeper Secrets Manager (KSM) access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper account
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
Make sure you add the proper permissions to your device in order to be able to read and write secrets
An initialized Keeper Secrets Manager Configuration
To install External Secrets with Helm, run the following commands:
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets \
external-secrets/external-secrets \
-n external-secrets \
--create-namespace
After creating a Secrets Manager Configuration for your device, you will have a Base64 JSON string that contains connection tokens, encryption keys, identifiers and domain information used to authenticate and decrypt data from the Keeper Secrets Manager APIs.
The Base64 JSON config string will be set by External Secrets to authenticate against Keeper Security and defined in a regular Kubernetes Secret.
Invoking the following command will create a Kubernetes Secret which is used to authenticate to Keeper Secrets Manager:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: ksm-config-secret # name of the k8s Secret where KSM config is stored
type: Opaque
data:
ksm_config: "[REPLACE WITH YOUR BASE64 JSON string]"
EOF
Note: Lines 2-8 in the above code snippet can be stored in a YAML file and applied with the command kubectl apply
. For example, you can store lines 2-8 in secrets.yaml
and execute the following:
kubectl apply -f secret.yaml
After creating a Kubernetes Secret with ksm_config
defined to your Base64 JSON string, you can now create your SecretStore.
Invoking the following command will create your SecretStore:
kubectl apply -f - <<EOF
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: my-external-secrets-secretstore # name of the SecretStore where retrieved secrets will be stored once fetched from Keeper Secrets Manager (KSM)
spec:
provider:
keepersecurity: # name of the SecretStore provider, in this case KeeperSecurity
authRef:
name: ksm-config-secret # name of the k8s Secret where KSM config is stored
key: ksm_config # key in the k8s Secret where KSM config is stored
folderID: "[SHARED FOLDER UID]" # UID of the shared folder in KeeperSecurity where the records
# are stored. Make sure the folder is shared into the KSM Application
EOF
Note: Lines 2-13 in the above code snippet can be stored in a YAML file and applied with the command kubectl apply
. For example, you can store lines 2-13 in secretstore.yaml
and execute the following:
kubectl apply -f secretstore.yaml
Next, you need to create your ExternalSecret.
The following code snippet will create your External Secret and store the values of the login & password field for the specified record into the Kubernetes Secret. These fields are defined in the target.template.data
section and refreshed every 30 seconds. For a full list of supported fields, visit this page.
kubectl apply -f - <<EOF
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: ksm-external-secret
spec:
refreshInterval: 12h # rate how often SecretManager pulls KeeperSecurity.
# In this case every 12 hours, for the example.
# We recommend this value to be 12h or more.
secretStoreRef: # reference to the SecretStore defined above to authenticate against Keeper Security
kind: SecretStore # tells External Secrets the type of the secret store, should be same as the one defined above
name: my-external-secrets-secretstore
dataFrom: # tells External Secrets which record to use to fetch from Keeper Secrets Manager (KSM)
- extract:
key: "[RECORD UID]" # UID of the record in Keeper where the secrets are going to be fetched from
target: # tells External Secrets the target location where to store the secrets once fetched from Keeper Security
name: my-external-secrets-values # name of the k8s Secret to be created
creationPolicy: Owner # tells External Secrets to create the k8s Secret if it doesn't exist
template:
engineVersion: v2
data:
username: "{{ .login }}" # tells External Secrets to store the value of
# the login field in Keeper Security into the k8s Secret under the key username
password: "{{ .password }}" # tells External Secrets to store the value of
# the password field in Keeper Security into the k8s Secret under the key password
name: "{{ (fromJson .name).first }} {{ (fromJson .name).middle }} {{ (fromJson .name).last }}" # decode json string into vars
EOF
Note: Lines 2-27 in the above code snippet can be stored in a YAML file and applied with the command kubectl apply
. For example, you can store lines 2-27 in externalsecret.yaml
and execute the following:
kubectl apply -f externalsecret.yaml
How a Record is equated to an ExternalSecret:
remoteRef.key
is equated to a Record's ID
remoteRef.property
is equated to one of the following options:
Fields: Record's field's Type
CustomFields: Record's field's Label
Files: Record's file's Name
If empty, defaults to the complete Record in JSON format
remoteRef.version
is currently not supported.
dataFrom
:
find.path
is currently not supported.
find.name.regexp
is equated to one of the following options:
Fields: Record's field's Type
CustomFields: Record's field's Label
Files: Record's file's Name
find.tags
are not supported at this time.
There are some limitations using this provider.
Keeper Secret Manager does not work with legacy non-typed records
Using tags find.tags
is not supported by KSM
Using path find.path
is not supported at the moment
Push Secret will only work with a custom KeeperSecurity Record type ExternalSecrets
selector
:
secret.name
: name of the kubernetes secret to be pushed
data.match
:
secretKey
: key on the selected secret to be pushed
remoteRef.remoteKey
: Secret and key to be created on the remote provider
Format: SecretName/SecretKey
To create a Keeper Security record from Kubernetes a Kind=PushSecret
is needed.
kubectl apply -f - <<EOF
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
name: example
spec:
secretStoreRefs:
- name: keeper
kind: SecretStore
refreshInterval: "1h"
deletionPolicy: Delete
selector:
secret:
name: secret-name # k8s secret to be pushed
data:
- match:
secretKey: secret-key # k8s key within the secret to be pushed
remoteRef:
remoteKey: remote-secret-name/remote-secret-key # This will create a record called "remote-secret-name" with a key "remote-secret-key"
EOF
Note: Lines 2-19 in the above code snippet can be stored in a YAML file and applied with the command kubectl apply
. For example, you can store lines 2-19 in pushsecret.yaml
and execute the following:
kubectl apply -f pushsecret.yaml
Make sure there's only one record with the title remote-secret-name
in the KSM Application in use.
Only possible to push one key per secret at the moment
If the record with the selected name exists but the key does not exists the record can not be updated.
After setting up your Kubernetes Secret, SecretStore, and ExternalSecret, you can extract secrets with the command kubectl get secrets
In the above code snippets, the name of the secret is my-external-secrets-values and we store the following record values:
data:
username: "{{ .login }}"
password: "{{ .password }}"
To get the login and password values, invoke the following command:
$ kubectl get secret my-external-secrets-values -o jsonpath="{.data}"
{"password":"a2lsbCB5b3U=","username":"SSB3aWxs"}
The above response is encoded, to decode, invoke the following:
$ kubectl get secret my-external-secrets-values -o jsonpath="{.data.password}" | base64 --decode
pAs$w0rd
In conclusion, this guide has detailed a step-by-step process for integrating the Keeper Secrets Manager with Kubernetes via the Kubernetes External Secrets Operator. By following these steps, you'll be able to seamlessly synchronize your secrets stored in Keeper Vault into your Kubernetes environment. This not only provides a secure method to manage your secrets but also facilitates real-time access across all your pods.
The processes outlined, including setting up the External Secrets operator, creating a Kubernetes Secret, SecretStore, and ExternalSecret, are key to this integration. Upon successful setup, the provided commands allow you to verify the integration and retrieve stored secrets effortlessly.
The integration of Keeper Secrets Manager with Kubernetes enhances the security infrastructure of your applications running in the Kubernetes environment. It provides a solid foundation for managing your secrets, thereby improving overall operational efficiency and security posture.
Remember to replace all placeholders in the command snippets with your specific information, and don't hesitate to refer back to this guide anytime you need to set up or manage your External Secrets in Kubernetes.
Keeper Secrets Manager integration into Kubernetes for dynamic secrets retrieval
We recommend using the Kubernetes External Secrets Operator integration for most use cases. This document describes an alternate method of integration which does not utilize the External Secrets Operator.
Retrieve secrets from the Keeper Vault within the Kubernetes
Access secrets from the Keeper Vault in real-time across all pods
Copy secure file attachments from the Keeper Vault to the local filesystem
This page documents the Secrets Manager Kubernetes integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
Keeper Secrets Manager can be integrated into your K8s cluster for accessing Keeper secrets in real-time across all pods.
Using Commander, create a Secrets Manager device configuration for Kubernetes. Note that this configuration is not IP locked and it is pre-initialized.
Create the configuration in Commander using this command:
secrets-manager client add --app <APP NAME> --unlock-ip --config-init k8s
Example:
My Vault> sm client add --app MyAdd --unlock-ip --config-init k8s
Successfully generated Client Device
====================================
Initialized Config:
apiVersion: v1
data:
config: ewog2N...ICIxMCIKfQ==
metadata:
name: ksm-config
namespace: default
type: Opaque
IP Lock: Disabled
Token Expires On: 2021-10-13 12:45:45
App Access Expires on: Never
In the example above, copy lines 8 through 14 and place them into a file called secret.yaml. Then, If you are using a machine with kubectl
installed and you have access to your cluster, add the KSM SDK config to your Kubernetes secrets.
$ kubectl apply -f secret.yaml
Alternatively, you can create a configuration by generating a One Time Access Token with Commander (or the Vault UI) and then using the Keeper Secret Manager CLI to create a configuration as demonstrated below (replace XX:XXX) with the One Time Access Token.
$ ksm init k8s XX:XXX
apiVersion: v1
data:
config: ewog2N[...]ICIxMCIKfQ==
kind: Secret
metadata:
name: ksm-config
namespace: default
type: Opaque
If you are using a machine with kubectl
installed and you have access to your cluster, the parameter --apply
can be set to automatically add the KSM SDK config to your Kubernetes secrets.
The output of redeeming the token can be piped to a file and then applied via kubectl. For example:
$ ksm init k8s XX:XXX > secret.yaml
$ kubectl apply -f secret.yaml
secret/ksm-config created
The KSM config can be pulled into your K8s containers using secrets.
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: my_container:XXXXX
env:
- name: KSM_CONFIG
valueFrom:
secretKeyRef:
name: ksm-config
key: config
restartPolicy: Never
At runtime, the Keeper Developer SDKs running in the K8s cluster will use the environment variable KSM_CONFIG to retrieve the device configuration and communicate with the Keeper Vault.
Below is a simple example that will generate a deployment and service that displays database secrets via a web application. This example uses the Keeper Python Developer SDK for the web application. The SDK will get its configuration from a Kubernetes secret and then retrieve PostgreSQL database record information from the Keeper vault.
From the Keeper Vault, a "Database" record type is created using the following information.
Now let's create our web application. The web page can be created using any of the Developer SDKs. For this example, it will being using the Python SDK. A simple Flask application with one endpoint will display the HTML that contains the Vault record secrets. The secrets are retrieved using the Keeper Notation syntax.
from flask import Flask
from keeper_secrets_manager_core import SecretsManager
import os
app = Flask(__name__)
@app.route("/")
def hello_world():
sm = SecretsManager()
return """
<h1>Database</h1>
<ul>
<li>Type: {}</li>
<li>Host: {}</li>
<li>Port: {}</li>
<li>Login: {}</li>
<li>Password: {}</li>
</ul>
""".format(
sm.get_notation(os.environ.get("DB_TYPE")),
sm.get_notation(os.environ.get("DB_HOST")),
sm.get_notation(os.environ.get("DB_PORT")),
sm.get_notation(os.environ.get("DB_LOGIN")),
sm.get_notation(os.environ.get("DB_PASS")))
The next part is creating a Dockerfile. The Dockerfile below is based off of the Python Debian images from Docker Hub.
FROM python:3.10.0-slim-bullseye
RUN apt-get update \
&& apt-get install -y gcc make libffi-dev curl libssl-dev \
&& apt-get clean
RUN pip3 install --upgrade pip wheel
# cryptology requires Rust to build
RUN curl https://sh.rustup.rs -sSf > /tmp/rust.sh \
&& chmod a+x /tmp/rust.sh \
&& /tmp/rust.sh -y
ENV PATH $PATH:/root/.cargo/bin
RUN pip3 install \
flask \
keeper-secrets-manager-core
RUN groupadd -g 5000 demo
RUN useradd -g demo demo
# Copy our application into the image
COPY demo.py /demo.py
USER demo
ENV FLASK_APP demo
EXPOSE 5000
CMD ["flask", "run"]
Next we will build a Docker image named ksm_demo.
$ docker build -t ksm_demo .
Assuming there is access to the Kubernetes cluster, the config can be generated from the One Time Access Token and automatically applied.
$ ksm init k8s --apply XX:XXXXXXXXXXX
secret/ksm-config created
Created secret for KSM config.
You can see the secret entry when you enter kubectl get secret
.
$ kubectl get secret ksm-config
NAME TYPE DATA AGE
ksm-config Opaque 1 55s
You can then make a deployment and service for the ksm_demo Docker image. This example is going to name the file ksm_demo.yaml.
Defining which secrets you need, and the config for the SDK, happen in the env section in the list of containers. In this section the KSM_CONFIG environmental variable is defined to get it's value from the ksm-config Kubernetes secret, specifically the config key of the secret.
The other environmental variables are just list of name/values. The value is Keeper Notation which the web application will send to the notation retrieval method of the SDK.
The second record in the ksm_demo.yaml file is the Service definition. This can be changed to whatever works with your Kubernetes cluster. In our example, it uses an external IP address. It's safe to use one of your Kubernetes nodes IP address, 10.0.1.18 for the example.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ksm-demo-deployment
labels:
app: ksm-demo
spec:
replicas: 1
selector:
matchLabels:
app: ksm-demo
template:
metadata:
labels:
app: ksm-demo
spec:
nodeSelector:
kubernetes.io/hostname: work
dnsPolicy: "None"
dnsConfig:
nameservers:
- 10.0.1.207
- 1.1.1.1
containers:
- name: ksm-demo
image: ksm_demo:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
protocol: TCP
env:
- name: KSM_CONFIG
valueFrom:
secretKeyRef:
name: ksm-config
key: config
- name: DB_TYPE
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/Type"
- name: DB_HOST
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/host[hostName]"
- name: DB_PORT
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/host[port]"
- name: DB_LOGIN
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/login"
- name: DB_PASS
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/password"
---
apiVersion: v1
kind: Service
metadata:
name: ksm-demo-service
spec:
ports:
- name: http
port: 5000
targetPort: 5000
protocol: TCP
selector:
app: ksm-demo
externalIPs:
- 10.0.1.18
At this point the deployment and service are ready to be applied.
$ kubectl apply -f ksm_demo.yaml
deployment/ksm-demo-deployment created
service/ksm-demo-service created
Wait until your deployment is ready. Either monitor it via the command line or Kubernetes Dashboard.
$ kubectl get deployment ksm-demo-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
ksm-demo-deployment 1/1 1 1 46m
$ kubectl get svc ksm-demo-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ksm-demo-service ClusterIP 10.107.91.89 10.0.1.18 5000/TCP 56m
Finally, use a web browser and go to the external IP address, port 5000, and you will see the Keeper vault record database secrets.
In this example a pod will be created that contains the stock NGINX docker image and SSL certificates retrieved from the Keeper Vault.
A Login record is created in the vault to hold the SSL certificate, private key, and certificate password.
A one time token is generated and added to the Kubernetes ConfigMap.
$ ksm init k8s XX:XXX > secret.yaml
$ kubectl apply -f secret.yaml
secret/ksm-config created
The example website is simply an index HTML page. The HTML can be stored in the ConfigMap and mounted in to the document root directory.
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-html-config
namespace: default
labels:
app: nginx
data:
index.html: |
<html>
<head>
<title>Nginx Test Page</title>
</head>
<body>
<h1>Hello From Keeper Secrets Manager!</h1>
</body>
</html>
The default.conf
will be overwritten by our example. The certificate, key, and password will be placed in to the /etc/keys
directory. For non-interactive startup, NGINX requires the certificate password be placed in a file and ssl_password_file
to be included in the server configuration.
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: default
labels:
app: nginx
data:
default.conf: |
server {
listen 80 default;
server_name localhost;
location / {
root /var/www/nginx-default;
index index.html index.htm;
}
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/keys/example.com.crt;
ssl_certificate_key /etc/keys/example.com.key;
ssl_password_file /etc/keys/global.pass;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /var/www/nginx-default;
index index.html index.htm;
}
}
The deployment for this example looks like the following:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
initContainers:
- name: ksm
image: keeper/keeper-secrets-manager-writer:latest
env:
- name: KSM_CONFIG
valueFrom:
secretKeyRef:
name: ksm-config
key: config
- name: SECRETS
value: |
5x0v0VFwYj2VvuhamrJhzQ/field/password > file:/etc/keys/global.pass
5x0v0VFwYj2VvuhamrJhzQ/file/example.com.crt > file:/etc/keys/example.com.crt
5x0v0VFwYj2VvuhamrJhzQ/file/example.com.key > file:/etc/keys/example.com.key
volumeMounts:
- mountPath: "/etc/keys"
name: keys-volume
containers:
- name: nginx
image: nginx:1.21.4-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
- containerPort: 443
protocol: TCP
volumeMounts:
- mountPath: "/etc/keys"
name: keys-volume
- mountPath: "/etc/nginx/conf.d/default.conf"
name: nginx-config-file
subPath: default.conf
- mountPath: "/var/www/nginx-default/index.html"
name: nginx-html-file
subPath: index.html
volumes:
- name: keys-volume
emptyDir: {}
- name: nginx-config-file
configMap:
name: nginx-config
- name: nginx-html-file
configMap:
name: nginx-html-config
imagePullSecrets:
- name: my-docker-hub-secrets
The docker image keeper/keeper-secrets-manager-writer
is used for an initialization container. The container will retrieve the secrets and write them to disk so they can be used by NGINX. The secrets are written to the pod's emptyDir volume, mounted to /etc/keys. This directory will be removed when the pod is deleted.
The main container will also mount the pod's emptyDir volume to /etc/keys. And will also mount the default.conf
into /etc/nginx/conf.d and the index.html
file into the document root for the server.
The last part is to create a service to access NGINX as shown below.
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app: nginx
externalIPs:
- XXX.XXX.XXX.XX
The service can be tested by going to the external IP via https (ie https://XXX.XXX.XXX.XXX). Notice the lock in the address bar indicates the certificate is valid.
External Secrets is a Kubernetes operator that synchronizes secrets from External APIs and injects them into Kubernetes. For more information on how to setup External Secrets to synchronize secrets from your Keeper Vault into Kubernetes, visit the following:
Kubernetes External Secrets OperatorAt this point, you can now integrate Keeper Secrets Manager into your K8s deployments using any of the Secrets Manager SDKs.
Store and Retrieve Secrets from the Linux Keyring
Keyring is a Linux security feature that stores sensitive information, such as passwords and secrets, and allows applications to securely access it.
Keeper provides a utility, the Linux Keyring Utility, that interacts with the native Linux APIs to store and retrieve secrets from the Keyring using the Secret Service API. This utility can be used by any integration, plugin, or code base to store and retrieve credentials, secrets, and passwords in any Linux Keyring simply and natively.
The code base for the Linux Keyring Utility can be found here:
The binary needed to use the above utility can be found here:
To use the Linux Keyring Utility, you can either
deploy the pre-built binary from the releases page
or import it into your code base.
Both use cases are covered below.
The Linux Keyring Utility gets and sets secrets in a Linux Keyring using the D-Bus Secret Service.
It has been tested with GNOME Keyring and KDE Wallet Manager. It should work with any implementation of the D-Bus Secrets Service.
There are two packages, dbus_secrets
and secret_collection
. The secret_collection
object uses the functions in dbus_secrets
. It unifies the D-Bus Connection, Session and Collection Service objects to offer a simple get/set/delete interface that the CLI uses.
The Go Language API has offers Get()
, Set()
and Delete()
methods. The first two accept and return string
data.
package main
import (
"os"
sc "github.com/Keeper-Security/linux-keyring-utility/pkg/secret_collection"
)
func doit() {
if collection, err := sc.DefaultCollection(); err == nil {
if err := collection.Unlock(); err == nil {
if secret, err := collection.Get("myapp", "mysecret"); err == nil {
print(string(secret))
os.Exit(0)
}
}
}
os.Exit(1)
}
The .DefaultCollection()
returns whatever collection the default alias refers to. It will generate an error if the default alias is not set. It usually points to the login keyring. Most Linux Keyring interfaces allow the user to set it.
The .NamedCollection(string)
method provides access to collections by name.
Set takes the data as a parameter and only returns an error or nil
on success. It does not restrict the content or length of the secret data.
if err := collection.Set("myapp", "mysecret", "mysecretdata"); err == nil {
// success
}
The Linux binary supports three subcommands:
get
set
del
Get
and del
require one parameter; name, which is the secret Label in D-Bus API terms.
Del
accepts one or more secret labels and deletes all of them. If it generates an error it will stop.
Set also requires the data as a single string in the second parameter. For example, set foo bar baz
will generate an error but set foo 'bar baz'
will work. If the string is -
then the string is read from standard input.
Get
and set
take a -b
or --base64
flag that handles base64 automatically. If used, Set
will encode the input before storing it and/or get will decode it before printing.
Note that calling get -b
on a secret that is not base64 encoded secret will generate an error.
# set has no output
lkru set root_cred '{
"username": "root"
"password": "rand0m."
}'
# get prints (to stdout) whatever was set
lku get root_cred
{
"username": "root"
"password": "rand0m."
}
lkru set -b root_cred2 '{"username": "gollum", "password": "MyPrecious"}'
lkru get root_cred2
eyJ1c2VybmFtZSI6ICJnb2xsdW0iLCAicGFzc3dvcmQiOiAiTXlQcmVjaW91cyJ9
lkru get -b root_cred2
{"username": "gollum", "password": "MyPrecious"}
cat ./good_cred.json | lkru set -b root_cred3 -
lkru get root_cred3
ewogICJ1c2VybmFtZSI6ICJhZGFtIiwKICAicGFzc3dvcmQiOiAicGFzc3dvcmQxMjMuIgp9
Error output goes to stderr
so adding 2>/dev/null
to the end of a command will suppress it.
The login collection does not exist because the keyring does not exist. KDE may create kdewallet instead of login like GNOME.
Unable to get secret 'test_cred': Unable to retrieve secret 'test_cred' for application 'lkru' from collection '/org/freedesktop/secrets/collection/login': Object does not exist at path “/org/freedesktop/secrets/collection/login”
A secret may not be returned even though a secret with the same label exists. If the secret was not created with lkru, it may not have the same attributes. Namely 'Agent', 'Application', and 'Id'.
Unable to get secret 'test_cred': Unable to retrieve secret 'test_cred' for application 'lkru' from collection '/org/freedesktop/secrets/aliases/default': org.freedesktop.Secret.Collection.SearchItems returned nothing
There may not be a D-Bus Session to host the Secret Service. This happens when the user is not logged into the GUI.
Unable to get the default keyring: Unable to open a D-Bus session: The name org.freedesktop.secrets was not provided by any .service files
The system may not host D-Bus. Several lightweight linux distributions ship without it by default.
Unable to get the default keyring: Unable to connect to the D-Bus Session Bus: exec: "dbus-launch": executable file not found in $PATH
Integrate Keeper Secrets Manager into AI agents using Docker
By enabling this feature, you authorize integration between Keeper and third-party AI tools or services. Keeper maintains its Zero-Trust architecture and does not access or process your vault records.
However, any data shared with third-party tools will be governed by those tools’ security, privacy, and compliance practices - not Keeper’s. You are solely responsible for configuring, managing, and auditing these integrations in accordance with your organization’s internal policies and applicable regulations.
To reduce exposure, access granted to AI Agents should be limited to only the minimum necessary folders in the Keeper Vault required to accomplish your specific use case.
Keeper Secrets Manager works with AI agents through the Model Context Protocol (MCP), enabling AI Agents to securely interact with specific vault folders. This integration provides a zero-trust architecture where AI agents are explicitly allowed to access designated information from the Keeper Vault.
The Model Context Protocol integration acts as a secure bridge between AI assistants and Keeper Secrets Manager. It allows AI tools to help you manage secrets while maintaining the highest security standards through human-in-the-loop confirmations for sensitive operations.
Zero Trust Architecture: AI agents are assigned specific folders in the vault Human-in-the-Loop: Confirmation prompts for sensitive operations Enterprise Ready: Comprehensive audit logging and compliance features Multi-Platform: Works on Linux, macOS, and Windows Docker Native: Easy deployment with container support
With KSM MCP integration, AI assistants can help you:
List secrets - Browse your accessible secrets Search secrets - Find secrets by title, URL, username, or other fields Retrieve secrets - Get specific secret values (with confirmation for unmasked data) Create secrets - Generate new secret entries Update secrets - Modify existing secret information Delete secrets - Remove secrets (with confirmation)
List attachments - View file attachments on secrets Upload files - Add file attachments to secrets Download files - Retrieve file attachments Delete files - Remove file attachments
Generate passwords - Create secure passwords with customizable parameters Get TOTP codes - Retrieve current time-based one-time passwords Execute KSM notation queries - Use Keeper's notation system for complex operations Health checks - Monitor server status and connectivity
From Keeper Secrets Manager, create an Application or use an existing application.
Discard the first Device token, and click on "Add Device" to generate a new Base64 configuration that will be provided to your AI agent.
From your AI Agent configuration screen, register the Keeper Secrets Manager MCP server.
The specific details vary between AI agent applications. In Claude Desktop, this can be set up by opening Settings > Developer and then clicking Edit Config. Add the "ksm" server to this file, making sure to include the Base 64 configuration string generated in step 2.
{
"mcpServers": {
"ksm": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "KSM_CONFIG_BASE64=<KSM_CONFIG_BASE64_HERE>",
"-e", "KSM_MCP_PROFILE=production",
"-e", "KSM_MCP_BATCH_MODE=true",
"-e", "KSM_MCP_LOG_LEVEL=error",
"-v", "ksm-mcp-data:/home/ksm/.keeper/ksm-mcp",
"keeper/keeper-mcp-server:latest"
]
}
}
}
Once this is set, you can begin interacting with the Keeper Secrets Manager MCP server.
Logs and event reporting are available inside the device logs screen and the Keeper Admin Console screens.
For additional setup details, see: https://github.com/Keeper-Security/keeper-mcp-golang-docker
Integrate Keeper Secrets Manager into AI agents using Node
By enabling this feature, you authorize integration between Keeper and third-party AI tools or services. Keeper maintains its Zero-Trust architecture and does not access or process your vault records.
However, any data shared with third-party tools will be governed by those tools’ security, privacy, and compliance practices - not Keeper’s. You are solely responsible for configuring, managing, and auditing these integrations in accordance with your organization’s internal policies and applicable regulations.
To reduce exposure, access granted to AI Agents should be limited to only the minimum necessary folders in the Keeper Vault required to accomplish your specific use case.
Keeper Secrets Manager works with AI agents through the Model Context Protocol (MCP), enabling AI Agents to securely interact with specific vault folders. This integration provides a zero-trust architecture where AI agents are explicitly allowed to access designated information from the Keeper Vault.
The Model Context Protocol integration acts as a secure bridge between AI assistants and Keeper Secrets Manager. It allows AI tools to help you manage secrets while maintaining the highest security standards through human-in-the-loop confirmations for sensitive operations.
Zero Trust Architecture: AI agents are assigned specific folders in the vault Human-in-the-Loop: Confirmation prompts for sensitive operations Enterprise Ready: Comprehensive audit logging and compliance features Multi-Platform: Works on Linux, macOS, and Windows
With KSM MCP integration, AI assistants can help you:
List secrets - Browse your accessible secrets Search secrets - Find secrets by title, URL, username, or other fields Retrieve secrets - Get specific secret values (with confirmation for unmasked data) Create secrets - Generate new secret entries Update secrets - Modify existing secret information Delete secrets - Remove secrets (with confirmation)
List attachments - View file attachments on secrets Upload files - Add file attachments to secrets Download files - Retrieve file attachments Delete files - Remove file attachments
Generate passwords - Create secure passwords with customizable parameters Get TOTP codes - Retrieve current time-based one-time passwords Execute KSM notation queries - Use Keeper's notation system for complex operations Health checks - Monitor server status and connectivity
From Keeper Secrets Manager, create an Application or use an existing application.
Discard the first Device token, and click on "Add Device" to generate a new Base64 configuration that will be provided to your AI agent.
You have two options for providing your Keeper configuration:
Place your downloaded configuration file in one of these locations:
~/.keeper/ksm-config.json
(recommended)
./ksm-config.json
(in the current directory)
If you have a one-time token instead:
export KSM_TOKEN="US:YOUR_ONE_TIME_TOKEN_HERE"
The server will use this token to generate and save a configuration file automatically.
Run the server directly to test:
npm start
You should see: Keeper MCP server is running
Add to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json
):
{
"mcpServers": {
"keeper": {
"command": "node",
"args": ["/path/to/keeper-mcp-node/dist/index.js"]
}
}
}
In Postman, go to the API Network tab
Create or select an MCP request
Configure the stdio connection:
Command: node
Arguments: /path/to/keeper-mcp-node/dist/index.js
The server communicates via stdio, so you can integrate it with any MCP-compatible client by running:
node /path/to/keeper-mcp-node/dist/index.js
ksm_list_secrets
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_list_secrets",
"arguments": {}
}
}
Response:
[
{
"uid": "XXXXXXXXXXXXXXXXXXXXXX",
"title": "My Secret",
"type": "login"
}
]
ksm_get_secret
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_get_secret",
"arguments": {
"identifier": "My Secret",
"unmask": false
}
}
}
ksm_search_secrets
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_search_secrets",
"arguments": {
"query": "database"
}
}
}
ksm_create_secret
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_create_secret",
"arguments": {
"title": "New Database Credentials",
"type": "login",
"fields": {
"login": "admin",
"password": "secure_password",
"url": "https://db.example.com"
},
"notes": "Production database",
"folderId": "FOLDER_UID"
}
}
}
ksm_update_secret
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_update_secret",
"arguments": {
"identifier": "My Secret",
"updates": {
"title": "Updated Title",
"fields": {
"password": "new_password"
}
}
}
}
}
ksm_delete_secret
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_delete_secret",
"arguments": {
"identifier": "My Secret"
}
}
}
ksm_get_field
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_get_field",
"arguments": {
"identifier": "My Secret",
"field": "password"
}
}
}
Common field names:
password
- The password field
login
- Username/email
url
- Website URL
Custom field labels
ksm_list_folders
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_list_folders",
"arguments": {}
}
}
ksm_create_folder
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_create_folder",
"arguments": {
"name": "Development Secrets",
"parentFolderId": "PARENT_FOLDER_UID"
}
}
}
ksm_delete_folder
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_delete_folder",
"arguments": {
"folderId": "FOLDER_UID",
"force": false
}
}
}
ksm_upload_file
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_upload_file",
"arguments": {
"identifier": "My Secret",
"filePath": "/path/to/certificate.pem",
"fileName": "server-cert.pem"
}
}
}
ksm_download_file
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_download_file",
"arguments": {
"identifier": "My Secret",
"fileId": "certificate.pem",
"outputPath": "/tmp/downloaded-cert.pem"
}
}
}
ksm_generate_password
Can optionally save to a new secret without exposing it to the AI
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_generate_password",
"arguments": {
"length": 24,
"includeUppercase": true,
"includeLowercase": true,
"includeNumbers": true,
"includeSpecial": true,
"saveToSecret": {
"title": "Generated API Key",
"login": "api-user",
"url": "https://api.example.com",
"notes": "Auto-generated API key"
}
}
}
}
ksm_get_totp_code
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_get_totp_code",
"arguments": {
"identifier": "My 2FA Secret"
}
}
}
ksm_get_server_version
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_get_server_version",
"arguments": {}
}
}
ksm_health_check
Request:
{
"method": "tools/call",
"params": {
"name": "ksm_health_check",
"arguments": {}
}
}
Ensure your configuration file is in one of the supported locations
Check that the file has proper JSON formatting
Verify file permissions (should be readable by your user)
Verify your configuration file contains all required fields
Check that your application has access to the shared folders/secrets
Ensure your device hasn't been revoked in Keeper
Verify you have internet connectivity
Check if your organization has IP restrictions enabled
Ensure your Keeper subscription includes Secrets Manager
For additional setup details, see: https://github.com/Keeper-Security/keeper-mcp-node/
Keeper Secrets Manager Step Template for accessing secrets in Octopus Deploy
Retrieve secrets from the Keeper Vault to use in Octopus Deploy Library
Inject credentials directly into Octopus Deploy projects
Get files from the Keeper Vault
This page documents the Secrets Manager Octopus Deploy integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The Octopus Deploy integration accepts Base 64 format configurations
The Keeper Octopus Deploy Step Template utilizes Keeper Secrets Manager to provide access to secret credentials saved in the Keeper Vault. The script allows for injecting secrets directly into Octopus Deploy projects securely using Keeper's zero-knowledge infrastructure.
To use the step template directly from Community Step Templates: Navigate: Library > Step Templates > Community Step Templates > Browse Library Search: "Keeper Secrets Manager - Retrieve Secrets" > Install > Save
To add as a Custom Step Template: Navigate: Library > Step Templates > Custom Step Templates > Import Paste the JSON obtained from community contributed templates library
Name: Keeper Secrets Manager - Retrieve Secrets Description: This step retrieves one or more secrets from a Keeper Vault and creates sensitive output variables for each value retrieved. These values can be used in other steps in your deployment or runbook process. You can retrieve secrets using Keeper Notation URIs, and you can choose a custom output variable name for each secret. Required:
A Keeper Secrets Manager application with permissions to retrieve secrets from the Keeper Vault.
The SecretManagement.Keeper.Extension
PowerShell module installed on the target or worker. If the module can't be found, the step will fail. The SecretManagement.Keeper
module(s) can be installed from the PowerShell gallery.
Keeper Secrets Manager Configuration (type: Sensitive)
Variable name: #{Keeper.SecretsManager.RetrieveSecrets.Config}
Keeper Secrets Manager configuration for KSM Application with permissions to retrieve secrets from the Keeper Vault. To generate KSM Configuration in Web Vault: Secrets Manager - KSM Application Name - Edit - Add Device, and switch to Method: Configuration file, preferably in Base64 format.
Vault Secrets to retrieve (type: Multi-line text box)
Variable name: #{Keeper.SecretsManager.RetrieveSecrets.VaultSecrets}
Use Secrets Manager Notation URIs to specify the Secrets to be returned from Keeper Vault, in the format SecretsManagerNotation URI | OutputVariableName
where:
OutputVariableName
is the optional Octopus output variable name to store the secret's value in. If this value isn't specified, an output name will be generated dynamically.
V8lFbio0Bs0LuvaSD5DDHA/field/login | MyLogin
V8lFbio0Bs0LuvaSD5DDHA/field/password | MyPass
V8lFbio0Bs0LuvaSD5DDHA/custom_field/phone[1][number] | MyOtherPhoneNum
V8lFbio0Bs0LuvaSD5DDHA/file/IMG_0036.png | MyImageBase64
Print output variable names (type: Checkbox)
Variable name: #{Keeper.SecretsManager.RetrieveSecrets.PrintVariableNames}
Write out the Octopus output variable names to the task log.
Default: False
Protect Secrets Manager connection details with Oracle Key Vault
Keeper Secrets Manager integrates with Oracle Key Vault in order to provide protection for Keeper Secrets Manager configuration files. With this integration, you can protect connection details on your machine while taking advantage of Keeper's zero-knowledge encryption of all your secret credentials.
Encrypt and Decrypt your Keeper Secrets Manager configuration files with Oracle Key Vault
Protect against unauthorized access to your Secrets Manager connections
Requires only minor changes to code for immediate protection. Works with all Keeper Secrets Manager SDK functionality
Support the Java/Kotlin Secrets Manager SDK.
Required Oracle packages: oci-java-sdk-keymanagement, oci-java-sdk-common and oci-java-sdk-common-httpclient-jersey.
OCI Key needs ENCRYPT
and DECRYPT
permissions.
Supports the JavaScript Secrets Manager SDK
Requires the oci-keymanagement package from OCI SDK.
OCI KMS Key needs ENCRYPT
and DECRYPT
permissions.
Supports the Python Secrets Manager SDK
Requires oci
package
User credentials to be used will need to have key vault permissions
Supports the .Net Secrets Manager SDK.
Requires OCI.DotNetSDK.Keymanagement.
Requires Encrypt
and Decrypt
permissions.
Supports the GoLang Secrets Manager SDK
Requires the oci-keymanagement package from OCI SDK.
OCI KMS Key needs ENCRYPT
and DECRYPT
permissions.
Setting up project using Gradle or Maven
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("com.keepersecurity.secrets-manager:oracle:1.0.0")
implementation("com.keepersecurity.secrets-manager:core:17.0.0")
implementation("com.oracle.oci.sdk:oci-java-sdk-keymanagement:3.60.0")
implementation("com.oracle.oci.sdk:oci-java-sdk-common-httpclient-jersey:3.60.0") // or the latest version
implementation("com.oracle.oci.sdk:oci-java-sdk-common:3.60.0")
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
implementation("com.fasterxml.jackson.core:jackson-core:2.18.2")
implementation("com.google.code.gson:gson:2.12.1")
implementation("org.slf4j:slf4j-simple:2.0.16")
implementation("org.bouncycastle:bc-fips:1.0.2.4")
}
Maven
<!-- KMS-core -->
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>oracle</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.keepersecurity.secrets-manager</groupId>
<artifactId>core</artifactId>
<version>17.0.0</version>
</dependency>
<!-- oci-kv -->
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-keymanagement</artifactId>
<version>3.60.0</version>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common-httpclient-jersey</artifactId>
<version>3.60.0</version>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>3.60.0</version>
</dependency>
<!--gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.12.1</version>
</dependency>
<!--jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!--jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.2</version>
</dependency>
<!-- slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
</dependency>
<!-- bc-fips -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>1.0.2.4</version>
</dependency>
The Secrets Manager Oracle Key Vault module can be installed using npm
npm install @keeper-security/secrets-manager-oracle-kv
The Secrets Manager OCI KSM module can be installed using pip
pip3 install keeper-secrets-manager-storage-oracle-kms
oci is a prerequisite for the Oracle Key Vault integration. Install it to your machine using pip.
pip3 install oci
The Secrets Manager oracle KSM module can be installed using dotnet nuget package manager.
dotnet add package Keeper.SecretsManager.OracleKeyManagement
The Secrets Manager oracle KSM module Integration can be installed using
go get github.com/keeper-security/secrets-manager-go/integrations/oracle
Ensure that you have an Oracle Key Vault instance available, and you know its OCID (Oracle Cloud Identifier). By default, the `oci key management` library will use the default OCI configuration file (~/.oci/config
)
Alternatively, You will need to add the correct configuration for your OCI environment, including the details for accessing Oracle Key Vault.
Once Oracle connection has been configured, You can fetch the Key to encrypt / decrypt KSM configuration using integration and you need to tell the Secrets Manager SDK to utilize the KMS as storage.
Once setup, the Secrets Manager Oracle Key Vault integration supports all Secrets Manager SDK functionality. Your code will need to be able to access the OCI Keys in order to manage the encryption and decryption of the KSM configuration file. Using Specified Connection credentials
To do this, create OracleKeyValueStorage
instance and use this in SecretManagerOptions
constructor.
The OracleKeyValueStorage
will require the name of the Secrets Manager configuration file with profile and configuration.
import java.security.Security;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import static com.keepersecurity.secretsManager.core.SecretsManager.initializeStorage;
import com.keepersecurity.secretmanager.oracle.kv.OracleKeyValueStorage;
import com.keepersecurity.secretmanager.oracle.kv.OracleSessionConfig;
import com.keepersecurity.secretsManager.core.SecretsManagerOptions;
import com.oracle.bmc.Region;
class Test {
public static void main(String args[]){
String configPath = "<~/.oci/config>";
String cryptoEndpoint = "https://<>-crypto.kms.<oracle_cloud_region>.oraclecloud.com";
String vaultId = "<OCI VAULT ID>";
String keyId = "<OCI KEY ID>";
String keyVersionId = "<OCI KEY VERSION>";
String configFileLocation = "<KSM CONFIG FILE LOCATION>";
String profile = "<OCI CONFIG PROFILE EX: DEFAULT>"; // name of your profile
String oneTimeToken = "<Keeper One Time Token>";
String managementEndpoint = "https://<>-management.kms.<oracle_cloud_region>.oraclecloud.com";
Region region = Region.<cloud_region>;
Security.addProvider(new BouncyCastleFipsProvider());
try{
//set Oracle KV configuration,
OracleSessionConfig oracleSessionConfig = new OracleSessionConfig(configPath, cryptoEndpoint, managementEndpoint, vaultId, keyId, keyVersionId, region);
//Get Storage
OracleKeyValueStorage oracleKeyValueStorage = new OracleKeyValueStorage(configFileLocation, profile, oracleSessionConfig);
initializeStorage(oracleKeyValueStorage, oneTimeToken);
SecretsManagerOptions options = new SecretsManagerOptions(oracleKeyValueStorage);
//getSecrets(options)
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
To do this, use OracleKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require an Oracle config file location
, Oracle configuration profile
(if there are multiple profile configurations) and the Oracle KMS Crypto endpoint
, Oracle KMS Management endpoint
as well as the name of the Secrets Manager configuration file
which will be encrypted by Oracle KMS.
import { OCISessionConfig, OciKeyValueStorage } from "@keeper-security/secrets-manager-oracle-kv";
const getKeeperRecordsOCI = async () => {
const oracleConfigFileLocation = "/home/...../.oci/config";
const oracleProfile = "DEFAULT";
const kmsCryptoEndpoint = "https://<>-crypto.kms.<location>.oraclecloud.com";
const kmsManagementEndpoint = "https://<>-management.kms.<location>.oraclecloud.com";
const ociSessionConfig = await new OCISessionConfig(oracleConfigFileLocation, oracleProfile, kmsCryptoEndpoint,kmsManagementEndpoint);
const logLevel = LoggerLogLevelOptions.info;
let config_path = "<Keeper config File Path>";
const oneTimeToken = "<one time token>";
const keyId = 'ocid1.key.oc1.iad.<>.<>';
const keyVersionId = "ocid1.keyversion.oc1.iad.<>.<>";
const storage = await new OciKeyValueStorage(keyId, keyVersionId, config_path, ociSessionConfig,logLevel).init();
await initializeStorage(storage, oneTimeToken);
const { records } = await getSecrets({ storage: storage });
console.log(records);
const firstRecord = records[0];
const firstRecordPassword = firstRecord.data.fields.find((x: { type: string; }) => x.type === 'bankAccount');
console.log(firstRecordPassword.value[0]);
};
console.log("start");
getKeeperRecordsOCI();
To do this, use OracleKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require a OCI Key ID, key version Id, KMS Crypto endpoint, KMS management endpoint, oracle config file location, configuration profile as well as the name of the Secrets Manager configuration file which will be encrypted by Oracle KMS and OCI session configuration shown below.
from keeper_secrets_manager_storage_oracle_kms import OracleKeyValueStorage, OCISessionConfig
from keeper_secrets_manager_core import SecretsManager
config_file_location = "/home/<user>/.oci/config"
profile = "DEFAULT"
kms_crypto_endpoint = "https://<kmsendpoint>.oraclecloud.com"
kms_mgmt_endpoint = "https://<kmsendpoint>.oraclecloud.com"
key_id = '<key_id>'
key_version_id = "<key_version_id>"
config_path = "<path to config json>"
one_time_token = "<Keeper One Time Token>"
oci_session_config = OCISessionConfig(config_file_location, profile, kms_crypto_endpoint, kms_management_endpoint)
storage = OracleKeyValueStorage(key_id=key_id, key_version=key_version_id, config_file_location=config_path, oci_session_config=oci_session_config,logger=None)
secrets_manager = SecretsManager(one_time_token,config=storage)
all_records = secrets_manager.get_secrets()
first_record = all_records[0]
print(first_record)
To do this, use OracleKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The storage will require a OCI Key ID, key version Id, KMS Crypto endpoint, KMS management endpoint, oracle config file location, configuration profile as well as the name of the Secrets Manager configuration file which will be encrypted by Oracle KMS and OCI session configuration shown below.
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OracleKeyManagement;
using SecretsManager;
public class Program
{
private static async Task getOneIndividualSecret()
{
Console.WriteLine("execution started");
bool changeKey = false;
bool decryptConfiguration = false;
var OCIConfigFileLocation = "location";
var profile = "DEFAULT";
var kmsCryptoEndpoint = "crypto_endpoint";
var kmsManagementEndpoint = "management_endpoint";
var ociSessionConfig1 = new OciSessionConfig(OCIConfigFileLocation, profile, kmsCryptoEndpoint, kmsManagementEndpoint);
var path = "oci_ksm_conf_test.json";
string keyId1 = "key1";
string keyId2 = "key2";
string keyVersionId1 = "key1version";
string keyVersionId2 = "key2version";
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger<OracleKeyValueStorage>();
var oracle_storage = new OracleKeyValueStorage(keyId2,keyVersionId2,path,ociSessionConfig1,logger );
var dotnet_access_token = "<accesstoken>";
SecretsManagerClient.InitializeStorage(oracle_storage, dotnet_access_token);
if (changeKey)
{
oracle_storage.ChangeKeyAsync(keyId1,keyVersionId1,null).Wait();
}
if (decryptConfiguration)
{
var conf = await oracle_storage.DecryptConfigAsync(true);
Console.WriteLine(conf);
}
var options = new SecretsManagerOptions(oracle_storage);
var records_1 = await SecretsManagerClient.GetSecrets(options);
records_1.Records.ToList().ForEach(record => Console.WriteLine(record.RecordUid + " - " + record.Data.title));
}
static async Task Main()
{
await getOneIndividualSecret();
}
}
To do this, use NewOracleKeyValueStorage
as your Secrets Manager storage in the SecretsManager
constructor.
The NewOracleKeyVaultStorage requires the following parameters to encrypt the KSM configuration using Oracle Vault:
ksmConfigFileName
: The file name of KSM configuration.
keyConfig
: Provide oracle key credentials KeyID
and KeyVersionID
.
oracleConfig
: Provide oracle credentials VaultManagementEndpoint
, VaultCryptoEndpoint
.
By default, the oci-keymanagement library will use the default OCI configuration file (~/.oci/config
).
package main
import (
"encoding/json"
"fmt"
"github.com/keeper-security/secrets-manager-go/core"
oraclekv "github.com/keeper-security/secrets-manager-go/integrations/oracle"
)
func main() {
decryptConfig := true
changeKey := true
ksmConfigFile := ""
oneTimeToken := "oneTimeToken"
keyConfig := &oraclekv.KeyConfig{
KeyID: "ocid1.key.oc1.<>.<>.<>",
KeyVersionID: "ocid1.keyversion.oc1.<>.<>.<>.<>",
}
oracleConfig := &oraclekv.OracleConfig{
VaultManagementEndpoint: "https://<>-management.kms.<>.oraclecloud.com",
VaultCryptoEndpoint: "https://<>-crypto.kms.<>.oraclecloud.com",
Profile: "",
ProfileConfigPath: "",
}
cfg := oraclekv.NewOracleKeyVaultStorage(ksmConfigFile, keyConfig, oracleConfig)
secrets_manager := core.NewSecretsManager(
&core.ClientOptions{
Token: oneTimeToken,
Config: cfg,
},
)
secrets, err := secrets_manager.GetSecrets([]string{})
if err != nil {
// do something
fmt.Printf("Error: %s\n", err)
} else {
for _, secret := range secrets {
fmt.Printf("Recieved secret: %s\n", secret.Title())
}
}
}
We can change key that is used for encrypting the KSM configuration, examples below show the code needed to use it
//The method changeKey(keyID, keyVersion) will be used to encrypt the KSM config file with new Key and version.
String newKeyID = "<new Key ID>";
String newKeyVersion = "<New Key Version>";
OracleKeyValueStorage oracleKeyValueStorage = new OracleKeyValueStorage(configFileLocation, profile, oracleSessionConfig);
oracleKeyValueStorage.changeKey(newKeyID, newKeyVersion); // Change the key for encryption/decryption
// To change the Oracle KMS key used for encryption, you can call the `changeKey` method on the `OciKeyValueStorage` instance.
const storage = await new OciKeyValueStorage(keyId, keyVersionId, configPath, ociSessionConfig).init();
await storage.changeKey(keyId2, keyVersionId2);
storage = OracleKeyValueStorage(key_id=key_id, key_version=key_version_id, config_file_location=config_path, oci_session_config=oci_session_config,logger=None)
new_key_id = "<new key id>"
new_key_version_id = "<new key version>"
isChanged = storage.change_key(new_key_id, new_key_version_id)
print("Key is changed " + isChanged)
// To change the Oracle KMS key used for encryption, you can call the `ChangeKeyAsync` method on the `OracleKeyValueStorage` instance.
// using Microsoft.Extensions.Logging;
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger<OracleKeyValueStorage>();
var oracle_storage = new OracleKeyValueStorage(keyId2,keyVersionId2,path,ociSessionConfig1,logger );
// If you want to change the key not oracle config, then pass nil in place of oracle config.
updatedKeyConfig := &oraclekv.KeyConfig{
KeyID: "ocid1.key.oc1.<>.<>.<>",
KeyVersionID: "ocid1.keyversion.oc1.<>.<>.<>.<>",
}
isChanged, err := cfg.ChangeKey(updatedKeyConfig, nil)
We can decrypt the config if current implementation is to be migrated onto a different cloud or if you want your raw credentials back. The function accepts a boolean which when set to true will save the decrypted configuration to file and if it is false, will just return decrypted configuration.
OracleKeyValueStorage oracleKeyValueStorage = new OracleKeyValueStorage(configFileLocation, profile, oracleSessionConfig);
oracleKeyValueStorage.decryptConfig(false); // Set false as a parameter to extract only plaintext.
//OR
oracleKeyValueStorage.decryptConfig(true); // Set true as a parameter to extract plaintext and save config as a plaintext.
const storage = await new OciKeyValueStorage(keyId, keyVersionId, config_path, ociSessionConfig).init();
await storage.decryptConfig(true); // Saves to file
const decryptedConfig = await storage.decryptConfig(true); // returns the decrypted config
storage = OracleKeyValueStorage(key_id=key_id, key_version=key_version_id, config_file_location=config_path, oci_session_config=oci_session_config,logger=None)
storage.decrypt_config(True)
//To decrypt the config file and save it again in plaintext, you can call the `DecryptConfigAsync` method on the `OracleKeyValueStorage` instance.
var conf = await oracle_storage.DecryptConfigAsync(true);
Console.WriteLine(conf);
cfg := oraclekv.NewOracleKeyVaultStorage(ksmConfigFile, keyConfig, oracleConfig)
secrets_manager := core.NewSecretsManager(
&core.ClientOptions{
Token: oneTimeToken,
Config: cfg,
},
)
// Pass true if you want to save decryptconfig in ksm config file, else pass false.
decryptedConfig, err := cfg.DecryptConfig(true)
You're ready to use the KSM integration 👍
Utilize PowerShell's Secret Management module to access secrets with the Keeper Secrets Manager PowerShell Plugin
Retrieve secrets from the Keeper Vault to use in PowerShell
Integrate Keeper vault with PowerShell Secrets Manager
Update secret values in the Keeper Vault from PowerShell
Get files from the Keeper vault
This page documents the Secrets Manager PowerShell integration. In order to utilize this integration, you will need:
Secrets Manager requires PowerShell version 6 or greater. Microsoft distributes PowerShell version 6+ as a separate application from versions 5 and earlier.
See Microsoft's Documentation for installation details
PowerShell Version 6.0 or later
See Microsoft's Documentation for installation details
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
The Keeper Secrets Manager PowerShell plugin utilizes Microsoft PowerShell's Secret Management module to inject secrets from the Keeper Vault into your PowerShell scripts.
The Keeper Secrets Manager extension can be easily configured added as a secret vault into new or existing PowerShell Secret Management workflows.
For more information about PowerShell Secret Management, see the PowerShell docs on their GitHub page.
Keeper Secrets Manager uses the Microsoft.PowerShell.SecretManagement module to manage secrets in PowerShell.
Install using PowerShell:
Install-Module -Name Microsoft.PowerShell.SecretManagement
See PowerShell Gallery for other installation options
Install the Keeper Secrets Manager PowerShell extension from the PowerShell Gallery.
Install-Module -Name SecretManagement.Keeper
See the PowerShell Gallery page for more installation options, or find the source code in GitHub.
The Keeper Secrets Manager PowerShell plugin will need a secret management extension to store the plugin configuration locally to your machine.
Keeper recommends Microsoft.Powershell.SecretStore or SecretManagement.KeyChain
Install-Module -Name Microsoft.Powershell.SecretStore
Install-Module -Name SecretManagement.KeyChain
Register a secret vault for the previously installed secret management extension, so that the Keeper Secrets Manager plugin configuration can be stored.
Register-SecretVault -Name LocalStore -ModuleName Microsoft.Powershell.SecretStore
Register-SecretVault -Name LocalStore -ModuleName SecretManagement.KeyChain
The name of this vault will be used to register the Keeper extension. We used LocalStore
in this example.
The Secret Management extension that you use for local storage may ask you to create a password for securely accessing the local vault.
Depending on your system settings, you may need to allow PowerShell to trust external modules. To do this, run the command:
set-executionpolicy remotesigned
Register the Keeper Secrets Manager Vault using the local vault registered above to save your credentials, and a one time token to connect to Keeper.
Replace 'XXX' below with a one time token.
Register-KeeperVault -Name Keeper -LocalVaultName LocalStore -OneTimeToken XXX
Alternatively you can use already generated config - replace 'XXX' below with a base64 encoded config.
Register-KeeperVault -Name Keeper -LocalVaultName LocalStore -Config XXX
Set the Keeper vault you just added as the default secret storage. This will tell the PowerShell SecretsManagement module to use your Keeper vault when getting and setting secrets.
Set-SecretVaultDefault Keeper
This step is optional, but if you choose not to do it, you may receive secrets from your default vault if they have the same name, and you will need to add -Vault <keeper vault name>
(e.g. -Vault keeper
) to Get-Secret, Set-Secret
commands
The Keeper Secrets Manager PowerShell Plugin is now ready to be used
Find the Keeper Secrets Manager PowerShell Plugin source code in the GitHub repository.
Find descriptions and examples of the most common usage of the Keeper Secrets Manager PowerShell plugin below.
For more information about PowerShell Secret Management commands, see the PowerShell docs on their GitHub page.
Starting with version 16.6.6 Get/Set
commands allow use of \
as and escape character for dots in title. Use escape character only if there's dot in title, and escape both .
and \
(ex. \.
, \\
)
Run the following PowerShell command to see a list of secrets from Keeper
Get-SecretInfo -Vault <KEEPER VAULT NAME>
PS> Get-SecretInfo -Vault Keeper
Name Type VaultName
---- ---- ---------
bf3dg-99-Juh3feswgtFxg Home SSH Hashtable Keeper
_3zT0HvBtRdYzKTMw1IySA ACME Login Hashtable Keeper
Use the name set for your Keeper secrets vault, in the examples above we use Keeper
.
The secrets shown are any records shared with the Secrets Manager Application. The Name column displays each record's UID and title.
Get information and values of a single secret
Get-Secret -Vault <KEEPER VAULT NAME> <RECORD NAME or UID> -AsPlainText
PS> Get-Secret -Vault Keeper "ACME Login" -AsPlainText
Name Value
---- -----
login user2
password 123
Files {file1.json, file2.zip}
Wrap the record name in quotation marks when there is a space in it.
Utilize Keeper Dot Notation to identify a field to access. Note that you do not need the 'keeper://' prefix.
Get-Secret -Vault <KEEPER VAULT NAME> <RECORD NAME OR UID>.<FIELD> -AsPlainText
PS> Get-Secret -Vault Keeper "ACME Login.password" -AsPlainText
gmzN6E8@9E97%xPB6Pg0
Update the value of a single secret field
Set-Secret -Vault <KEEPER VAULT NAME> <RECORD NAME OR UID>.<FIELD> <VALUE TO SET>
Use dot notation to specify a file attached to a secret in the Keeper vault. Then pass that file to the Set-Content
command to download it.
Get-Secret -Vault <KEEPER VAULT NAME> <RECORD NAME OR UID>.files[<FILENAME>] `
| Set-Content -Path <FILE PATH> -AsByteStream
PS> Get-Secret -Vault Keeper my_record.files[file1.json] `
| Set-Content -Path ./file1.json -AsByteStream
The specified file will be downloaded to the path location given to Set-Content
Keeper credential storage integration with ServiceNow
The Management, Instrumentation, and Discovery (MID) Server integration with the Keeper Vault enables ServiceNow Orchestration, ServiceNow Discovery, and ServiceNow Service Mapping to dynamically retrieve credentials from the Keeper Vault without storing any credentials on the instance.
The instance maintains an unique identifier for every credential, along with its credential type (e.g., SSH, SNMP, or Windows) and any associated credential affinities. The MID Server obtains the credential identifier, credential type, and IP address from the instance, and then uses Keeper vault to resolve these elements into a usable credential.
Use secrets from the Keeper vault as credentials for ServiceNow Orchestration, Discovery, and Service Mapping
Supports External Credential Storage for Discovery and Orchestration
Allows usage as a Custom Credential Provider
Trigger: An admin in ServiceNow initiates a discovery process for newly added infrastructure.
Action: ServiceNow sends a request to the MID Server to start the discovery.
MID Server: Retrieves the necessary credentials (SSH, SNMP, etc.) from Keeper Vault and performs the discovery.
Result: The discovered assets are added to the ServiceNow Configuration Management Database (CMDB).
Trigger: An incident is created in ServiceNow, requiring immediate action on a specific server.
Action: ServiceNow triggers an orchestration workflow that involves the MID Server.
MID Server: Fetches the required credentials from Keeper Vault to log into the affected server and execute predefined remediation steps.
Result: The incident is resolved, and the actions taken are logged in ServiceNow.
Trigger: A custom application integrated with ServiceNow requires specific credentials for operation.
Action: The application queries ServiceNow for the required credentials.
MID Server: Intercepts the request, fetches the credentials from Keeper Vault, and provides them to the custom application.
Result: The custom application can proceed with its operation, using the credentials securely fetched from Keeper Vault.
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper subscription
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
A ServiceNow instance with External Credential Storage plugin enabled
The External Credential Storage plugin must be active.
The Enable External Credential Storage Discovery property is enabled.
A property called Enable External Credential Storage [com.snc.use_external_credentials]
enables or disables the External Credential Storage plugin after it is activated. This property is located in Discovery Definition > Properties and Orchestration > MID Server Properties, and is enabled when you activate the plugin.
If you disable external credential storage with the system property, the system automatically sets all the external credentials to inactive in the instance. If you re-enable the feature with this property, the system does not reset the external credential records to active. You must reactivate each credential record manually.
Download the latest version of Keeper Credential Resolver JAR file from here.
In ServiceNow, navigate to "MID server - JAR files" -> New
Manage Attachments -> upload Keeper Credential Resolver JAR
Fill in name, version etc. as desired
Click Submit
Navigate to "MID server - Properties" -> New
Set Name: ext.cred.keeper.ksm_config
, Value: base64 version of the configuration generated for the corresponding KSM Application.
Optional: Set the property ext.cred.keeper.ksm_label_prefix
to the desired prefix (by default resolver uses mid_
as a label prefix)
Optional: Set the property ext.cred.keeper.use_ksm_cache
to "true"
to enable caching (use when you expect at least a few thousand requests per 10 seconds)
Alternatively, you can edit config.xml
directly (by default in /opt/servicenow/mid/agent/)
by adding the keys and restarting the server (setting the label prefix is optional - the default prefix is shown below)
<parameter name="ext.cred.keeper.ksm_config" secure="true" value="[KSM_CONFIG_BASE64_STRING]"/>
<!-- optional -->
<parameter name="ext.cred.keeper.ksm_label_prefix" value="mid_"/>
<!-- optional -->
<parameter name="ext.cred.keeper.use_ksm_cache" value="true"/>
Use secure="true" option for all sensitive parameters and remember to restart the server to encrypt the values.
To consume Keeper vault credentials from your MID server, you will need to:
Create a secret in Keeper vault and share it to the corresponding KSM Application
Configure the resolver to use that secret
Keeper record types are dynamic and easy to customize, and there are no specific record types matching corresponding credential types in ServiceNow.
Keeper External Credential Resolver uses custom field labels to match record data with MID Server's table columns (discovery_credential
table). Just label all required custom fields to match the table columns for a given credential type and prefix that label with "mid_" (see below how to configure custom prefix)
Credential types that require username/password should use records of type Login, and add any custom fields required by the credential type - ex. type=hidden, label="mid_pkey"
Any other types that may not have username/password is best to use File/Photo records which don't have any standard fields and that makes it easier to navigate the custom fields.
To change the custom field labels prefix update the config.xml in MID Server with the parameters below and restart the MID Server.
<parameter name="ext.cred.keeper.ksm_label_prefix" value="mid_"/>
You may use custom fields with type text
, multiline
or hidden
depending on the visibility you want in your Keeper Vault.
When Login record type is used, any custom fields for username/password are ignored (even if properly labeled mid_user, mid_pswd) as these values always come from the Login record type standard fields - Login/Password.
When used with "External credential store" option the map keys returned from resolve method must conform to IExternalCredential interface from snc-automation-api.jar
(values start with VAL_ prefix).
Supported key values in current version (Utah): user, pswd, passphrase, pkey, authprotocol, authkey, privprotocol, privkey, secret_key, client_id, tenant_id, email - corresponding field labels should be prefixed with mid_
in Keeper records to be extracted and mapped properly.
When used as Custom External Credential Resolver, any custom field could be mapped if properly prefixed in Keeper vault and present in corresponding credential type. The credential map returned from the resolve method is expected to have keys matching with the column names in discovery_credential table ex. sn_cfg_ansible, sn_disco_certmgmt_certificate_ca, cfg_chef_credentials, etc.
Credential type jdbc
- map to Keeper record type Login
(using standard Login/Password fields, no additional setup required)
Credential type api_key
- map to Keeper record type Login
and manually add custom fields of type hidden
with labels mid_ssh_private_key
, and mid_ssh_passphrase
(optional)
Credential type gcp
- map to Keeper record type File Attachment/Photo
and manually add the required custom fields mid_email
- text, mid_secret_key
- hidden.
The Credential ID passed from MID Server to the Credential Resolver must be either a valid record UID (22 alphanumeric characters incl. "-" and "_") or in the following format type:title
The type:title format allows searching by record type or by title (or both, but single ":" is an invalid combination)
When using the type:title
format for the credential, please make sure there's only one matching record, since multiple matches will result in an error.
Using record UID for matching is recommended to guarantee a single record match, and to avoid downloading all records with every single request to do local searches by type:title (due to the zero knowledge nature of the Keeper vault - searches must be local).
Note: Zero or two or more matches result in an error
Find by Record UID - Credential ID: ABCDABCDABCDABCDABCDAB
Find by type and title - Credential ID: login:MyLogin
Find by title - Credential ID: :MyLogin
Find by type - Credential ID: login:
In the ServiceNow UI:
Navigate to "Discovery - Credentials" -> New
Select a credential type from the list
Tick the "External credential store" check box. The Username and Password fields disappear, and the Credential ID field and Credential storage vault menu appear.
Fill in a meaningful name
Set "Credential ID" to the record UID of your secret or provide a search string in the form type:title
or just :title
and make sure it resolves to a single record
From the Credential storage vault menu, you can select either None, the Keeper vault, or a custom external credential storage vault.
To use a custom external credential storage vault, navigate to Vault Configurations [vault_configuration.list]
in the instance.
Create a new record using a name associated with an imported JAR file for a custom credential resolver.
Optional: Click "Test credential" and select a MID server and a target to test against to test everything is working
If too many requests are sent to Keeper within a certain time period, we will respond with a throttle error response. The plugin will try to resolve "throttled" errors by default by adding a random delays and retrying later, which works well for up to 1000-3000 requests per 10 sec interval (throttles start after 300-600 requests/10 sec).
If you expect 5000+ requests in less than 10 seconds we recommend to enable caching by setting ext.cred.keeper.use_ksm_cache
parameter to "true"
in config.xml and restarting the MID Server. Cached data is stored in an encrypted file ksm_cache.dat
in MID Server's work folder. Cache is updated at most once every 5 minutes or with the next request.
Check the log files inside logs/
in the agent installation folder for logs and errors. The resolver logs a line for each credential ID that it successfully queries, and also logs the fields that the credentials were extracted from.
If a particular credential ID is failing, search for that ID in the logs, and check that it is successfully queried and that the credentials were extracted from the fields you expected.
You will also find any exceptions that the resolver throws in the logs, including errors locating a record or finding fields, or if it couldn't communicate with Keeper vault.
When creating or configuring a credential in the ServiceNow UI, you should be able to click "Test credential" to perform a quick targeted test. Select the MID server that should query the Keeper vault, and select a target that the credential should work for to check that everything works as expected. If it doesn't, check the logs for errors and debug information as detailed above.
Keeper Secrets Manager plugin for accessing secrets in TeamCity builds
TeamCity is a general-purpose CI/CD software platform that allows for flexible workflows, collaboration and development practices. A solution that will allow for successful continuous integration, continuous delivery, and continuous deployment within your DevOps process.
The plugin allows TeamCity servers (version 2018.1 or newer) to integrate with Keeper Secrets Manager to make managing secrets in TeamCity easier and more secure.
Use secrets from the Keeper vault in TeamCity builds
Keeper Secrets Manager plugin installs as a TeamCity Connection
Keeper Secrets Manager access (See the Quick Start Guide for more details)
Secrets Manager add-on enabled for your Keeper subscription
Membership in a Role with the Secrets Manager enforcement policy enabled
A Keeper Secrets Manager Application with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The TeamCity plugin accepts Base 64 format configurations
Go to Administration | Plugins in TeamCity and click Browse plugins repository.
Find the Keeper Secrets Manager plugin, click Get, and then Install to http[s]://<teamcityUrl>.
Confirm the plugin installation by clicking Install.
To enable the plugin after installation, click the plugin context menu and select Load.
Download the latest version of TeamCity KSM plugin ZIP file from here.
Go to the Administration | Plugins page and upload the plugin ZIP archive from your local machine using the corresponding link.
Copy the ZIP plugin package into the<
TeamCity Data Directory
>/plugins
directory. If you have an earlier version of the plugin in the directory (though the plugin package can be named differently), remove it.
To enable the plugin after installation, click the plugin context menu and select Load. The plugin will be enabled without the server restart.
Go to Administration | Plugins, locate an external plugin in the list, click the arrow icon next to it, and select Delete.
Once the plugin is deleted, the option to restart the server appears on the page. Click it and check that the plugin version is no longer listed in Administration | Plugins.
Remove the plugin package from the <
TeamCity Data Directory
>/plugins
directory and restart the TeamCity server.
When created, a connection can be used in all the nested subprojects of the current project. If you add a connection in the Root project, it will become available on the whole server.
To add a connection, go the target project's settings, open the Connections page, and click Add Connection. Select the connection type Keeper Vault, set its Display name to distinguish it from the others, and configure it as described below.
In Project Administration | Connections, click Add Connection.
Select Keeper Vault as the connection type.
Specify the token - paste a valid KSM config (see Prerequisites).
Save the connection.
To consume Keeper vault secrets from your TeamCity server, you will need to:
Create a secret in Keeper vault and share it to the corresponding KSM Application
Configure a TeamCity parameter that resolves the secret using Secrets Manager Notation URIs
In most build configuration settings, you can use a reference to a build parameter instead of using the actual plain-text value. Before starting a build, TeamCity resolves all references with the available parameters. If there are references that cannot be resolved, they are left as is, and a respective warning appears in the build log. To reference a build parameter, use its name enclosed in percentage characters: for example, %env.KsmSecret1%
.
Parameters tab allows adding, editing, and deleting new parameters/properties/variables, or redefining their predefined values.
Any text enclosed in percentage characters will be interpreted by TeamCity as a reference to a parameter. If the parameter cannot be found in the build configuration, this reference becomes an implicit agent requirement and such build configuration can only be run on an agent with this parameter defined. The agent-defined value will be used in the build.
If you want to prevent TeamCity from treating the text in the percentage characters as a reference to a parameter, use two percentage characters. Every occurrence of %%
in the values where parameter references are supported will be replaced with %
before passing the value to the build. For example, if you want to pass %Y%m%d%H%M%S
into the build, change it to %%Y%%m%%d%%H%%M%%S
.
Define a build parameter on a build configuration level and use it in a build step.
Go to Build Configuration Settings | Parameters.
Click Add new parameter.
Enter the parameter's name and value. Change parameter's Kind to Environment variable (env.).
Name: username
Value: %keeper://UserRecord1/fields/login%
Save the parameter.
Go to Build Steps.
Click Add build step.
Choose the Command Line runner type.
In the Custom script field, enter the following command:
echo UserName %env.username%
For a build, this command will be resolved as follows (note that actual value is masked in logs but used in actual commands):
echo UserName *****
Save the build step and run a new build.
The plugin accepts both Keeper Notation prefix keeper://NotationURI
and TeamCity style prefix keeper:NotationURI
in build parameters, environment variables etc. Check the examples below.
Parameter Examples:
Environment variable env.User
- keeper:abcdABCDabcdABCDuvwxyz/field/login
Environment variable env.Secret
- keeper://MyRecord1/custom_field/Secret1
Keeper Secrets Manager integration with Teller for dynamic secrets retrieval
Retrieve secrets from the Keeper Vault within Teller environments
Set secret credentials as environment variables in Teller
This page documents the Secrets Manager Teller integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The Teller integration accepts Base64 format configurations
Using Keeper Commander, add a new client to an application and initialize the configuration to a Base64 string. This will be the long text hash that appears after the "Initialized Config:" label.
My Vault> sm client add --app MyApp --config-init b64
Successfully generated Client Device
====================================
Initialized Config: eyJob3N0bmFtZSI6ICJr....OUk1ZTV1V2toRucXRsaWxqUT0ifQ==
IP Lock: Enabled
Token Expires On: 2021-10-19 15:31:31
App Access Expires on: Never
That value needs to be assigned to an environment variable with the name KSM_CONFIG.
teller
will pull variables from your Keeper Vault, and will populate your current working session so you can work safely and much more productively.
teller
needs a tellerfile. This is a .teller.yml
file that lives in your repo, or one that you point teller to with teller -c your-conf.yml
.
Run teller new
and follow the wizard, pick the providers you like and it will generate a .teller.yml
for you.
Alternatively, you can use the following minimal template:
project: project_name
opts:
stage: development
providers:
# requires a configuration in: KSM_CONFIG=base64_config
# or file path KSM_CONFIG_FILE=ksm_config.json
keeper_secretsmanager:
# pull multiple key-value pairs from a single record
# all non-empty fields are mapped by their labels,
# if empty then by field type, and numeric suffix 1,2,...,N on duplicates
env_sync:
path: [recordUID]
# use Keeper Notation to select individual field values
# https://docs.keeper.io/secrets-manager/secrets-manage
env:
USER:
path: [recordUID]/field/login
PSWD:
path: [recordUID]/field/password
With a .teller.yml
file in the current directory, or one that you point teller to with teller -c your-conf.yml
now you can just run processes with:.
$ teller run node src/server.js
Service is up.
Loaded configuration: Mailgun, SMTP
Port: 5050
Add a teller step.
# set up teller step
- name: Setup Teller
uses: spectralops/setup-teller@v2
- name: Run a Teller task (show, scan, run, etc.)
run: teller run [args]
Full example below is using the default config file .teller.yml
which can be replaced in the run
command with a custom file that you point teller to with teller -c your-conf.yml
.
name: run with teller
on:
push:
branches:
- master
- main
pull_request:
jobs:
build:
name: Build your code
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@master
# set up teller
- name: Setup Teller
uses: spectralops/setup-teller@v2
- name: Run a Teller task (show, scan, run, etc.)
run: teller run npm run build
Keeper Secrets Manager Terraform plugin for accessing secrets in Terraform builds
Retrieve secrets from the Keeper Vault to use in Terraform builds
Inject credentials directly into Terraform build scripts
Get Files from the Keeper Vault
This page documents the Secrets Manager Terraform integration. In order to utilize this integration, you will need:
Keeper Secrets Manager access (See the 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 with secrets shared to it
See the Quick Start Guide for instructions on creating an Application
An initialized Keeper Secrets Manager Configuration
The Terraform integration accepts JSON and Base 64 format configurations
The Keeper Terraform Plugin utilizes Keeper Secrets Manager to provide access to secret credentials saved in the Keeper Vault. The Keeper Terraform plugin allows for injecting secrets directly into Terraform builds securely using Keeper's zero-knowledge infrastructure.
To install this provider, add the following code to your Terraform configuration and run terraform init
:
terraform {
required_providers {
secretsmanager = {
source = "keeper-security/secretsmanager"
version = ">= 1.0.0"
}
}
}
provider "secretsmanager" {
# Configuration options
}
Download the latest version of the Terraform Provider for your platform from our GitHub release page and copy the archive to the corresponding Terraform plugin folder (creating any missing folders in the path). Initialize source with full provider URL: source = "github.com/keeper-security/secretsmanager"
SETLOCAL EnableExtensions && ^
mkdir %APPDATA%\.terraform.d\plugins\github.com\keeper-security\secretsmanager && ^
cd %APPDATA%\.terraform.d\plugins\github.com\keeper-security\secretsmanager && ^
curl -SfLOJ https://github.com/keeper-security/terraform-provider-secretsmanager/releases/download/v1.0.0/terraform-provider-secretsmanager_1.0.0_windows_amd64.zip
mkdir -p ~/.terraform.d/plugins/github.com/keeper-security/secretsmanager && \
cd ~/.terraform.d/plugins/github.com/keeper-security/secretsmanager && \
curl -SfLOJ https://github.com/keeper-security/terraform-provider-secretsmanager/releases/download/v1.0.0/terraform-provider-secretsmanager_1.0.0_darwin_amd64.zip
mkdir -p ~/.terraform.d/plugins/github.com/keeper-security/secretsmanager && \
cd ~/.terraform.d/plugins/github.com/keeper-security/secretsmanager && \
curl -SfLOJ https://github.com/keeper-security/terraform-provider-secretsmanager/releases/download/v1.0.0/terraform-provider-secretsmanager_1.0.0_linux_amd64.zip
For help on manually installing Terraform Providers, please refer to the official Terraform documentation.
The Keeper Secrets Manager provider is used to interact with the resources supported by Keeper Secrets Manager. The provider needs to be configured with Keeper credentials before it can be used.
terraform {
required_providers {
secretsmanager = {
source = "keeper-security/secretsmanager"
version = ">= 1.0.0"
}
}
}
provider "secretsmanager" {
# Specify config contents as a string or load from file
# credential = "<CONFIG FILE CONTENTS BASE64>"
credential = file("/path/to/config.json")
}
app_key
- (Required) Application key.
client_id
- (Required) Client ID.
private_key
- (Required) Private key.
hostname
- (Optional) By default plugin will connect to keepersecurity.com
A data source is provided for each standard Keeper record type, which facilitates easy fetching of secret credentials.
Data sources are accessed using the following format:
data "<data_source_name>" "<record_type_reference>" {
path = "<record_uid>"
}
For example, using a Login type record:
data "secretsmanager_login" "my_login_record" {
path = "<RECORD_UID>"
}
To access any additional custom fields or standard fields for user defined record types use secretsmanager_field
data source
"secretsmanager_address"
"secretsmanager_bank_account"
"secretsmanager_bank_card"
"secretsmanager_birth_certificate"
"secretsmanager_contact"
"secretsmanager_database_credentials"
"secretsmanager_drivers_license"
"secretsmanager_encrypted_notes"
"secretsmanager_field"
"secretsmanager_file"
"secretsmanager_health_insurance"
"secretsmanager_login"
"secretsmanager_membership"
"secretsmanager_passport"
"secretsmanager_photo"
"secretsmanager_record"
"secretsmanager_server_credentials"
"secretsmanager_software_license"
"secretsmanager_ssh_keys"
"secretsmanager_ssn_card"
To see the fields available to each data source see Record Types Data Source Reference
For more information on record types see record types documentation
To access a secret credential saved to a field in a record, access the field as part of the data source.
Access the field of a typed record data source
Use this format to access fields of a typed data resource
${ data.<data_source_name>.<record_type_reference>.<field> }
Example: access the password of a login type data source
${ data.secretsmanager_login.my_login_secret.password }
Use the field data source to query any field in a record with Keeper Notation
Create a data source using the "secretsmanager_field" data source type, and specify a field query in the path property.
data "secretsmanager_field" "my_field" {
path = "<record UID>/field/login"
}
The field query uses the format: "<UID>/field/<field type>"
Keeper provides Terraform resources for the major Keeper record types shown above. Using these resources, Keeper records can be created using the Keeper Secrets Manager Terraform plugin.
To create a record, use the resource corresponding to the record type that you would like to use.
Each record resource requires at least a folder_uid
and title
as well as values for each record field.
Example login resource
resource "secretsmanager_login" "login" {
folder_uid: "4PbDLf8UF4od87wJt-fdyQ"
tile: "My Login Record"
[...]
}
To create records, Keeper Secrets Manager requires a folder UID so that it knows where to create the new records.
A folder UID can be found in the Keeper Vault or by using Keeper Commander.
The given folder must by accessible by the Keeper Secrets Manager Application being used by your Terraform plugin. The folder must also have at least one record in it before being used by Keeper Secrets Manager.
The record title.
The value and settings for each record field can be set in the resource. For information on the available fields per record type, see the resource definitions.
Each field is represented as an object in the resource.
Example login field
resource "secretsmanager_login" "login" {
[...]
login {
value = "MyUsername"
label = "Username"
required = true
}
}
Use the value
field to set the intended value for each field. The format of fields can differ, for example the login
field type takes a string, while the name
field takes an object with "first", "middle" and "last" fields.
For reference of each field's value format see the resource documentation.
Setting Field Settings
Each field can be configured with various settings:
label
string
The field label
required
boolean
if True, the field will be considered required by the Keeper Vault
privacy_screen
boolean
if True, the field will be hidden in the Keeper Vault
The password field has some special features.
Password Generation
Records created using the Terraform plugin can have a password generated automatically. To have the plugin generate a password, do not provide a value
field to the password, and instead use generate = "True"
The password generation can be configured to generate a password of a specified length using the complexity field
complexity {
length: 16
}
Additionally, password fields have an extra configuration setting: enforce_generation
which when true will make the Keeper Vault enforce that the password can only be generated and not set by a user.
This example provisions Keeper Secrets Manager, reads a login type data source, and accesses each field of the data source.
terraform {
required_providers {
secretsmanager = {
source = "keeper-security/secretsmanager"
version = ">= 1.0.0"
}
local = {
source = "hashicorp/local"
version = "2.1.0"
}
}
}
provider "local" { }
provider "secretsmanager" {
# Specify config contents as a string or load from file
# credential = "<CONFIG FILE CONTENTS BASE64>"
credential = file("~/.keeper/ksm-config.json")
}
data "secretsmanager_login" "db_server" {
path = "<record UID>"
}
resource "local_file" "out" {
filename = "${path.module}/out.txt"
file_permission = "0644"
content = <<EOT
UID: ${ data.secretsmanager_login.db_server.path }
Type: ${ data.secretsmanager_login.db_server.type }
Title: ${ data.secretsmanager_login.db_server.title }
Notes: ${ data.secretsmanager_login.db_server.notes }
======
Login: ${ data.secretsmanager_login.db_server.login }
Password: ${ data.secretsmanager_login.db_server.password }
URL: ${ data.secretsmanager_login.db_server.url }
TOTP:
-----
%{ for t in data.secretsmanager_login.db_server.totp ~}
URL: ${ t.url }
Token: ${ t.token }
TTL: ${ t.ttl }
%{ endfor ~}
FileRefs:
---------
%{ for fr in data.secretsmanager_login.db_server.file_ref ~}
UID: ${ fr.uid }
Title: ${ fr.title }
Name: ${ fr.name }
Type: ${ fr.type }
Size: ${ fr.size }
Last Modified: ${ fr.last_modified }
Content/Base64: ${ fr.content_base64 }
%{ endfor ~}
EOT
}
output "db_secret_login" {
value = data.secretsmanager_login.db_server.login
}
terraform {
required_version = ">= 1.0.0"
required_providers {
secretsmanager = {
source = "keeper-security/secretsmanager"
version = ">= 1.1.0"
}
local = {
source = "hashicorp/local"
version = "2.1.0"
}
}
}
provider "local" { }
provider "secretsmanager" {
# Specify config contents as a string or load from file
# credential = "<CONFIG FILE CONTENTS BASE64>"
credential = file("~/.keeper/ksm-config.json")
}
resource "secretsmanager_membership" "membership" {
folder_uid = "<FOLDER UID>"
title = "test_membership_resource"
notes = "test_membership_resource"
account_number {
label = "MyAccountNumber"
required = true
privacy_screen = true
value = "AccountNumber#1234"
}
name {
label = "Jane"
required = true
privacy_screen = true
value {
first = "Jane"
middle = "D"
last = "Doe"
}
}
password {
label = "MyPass"
required = true
privacy_screen = true
enforce_generation = true
generate = "true"
complexity {
length = 16
}
#value = "to_be_generated"
}
}
resource "local_file" "out" {
filename = "${path.module}/out.txt"
file_permission = "0644"
content = <<EOT
FUID: ${ secretsmanager_membership.membership.folder_uid }
UID: ${ secretsmanager_membership.membership.uid }
Type: ${ secretsmanager_membership.membership.type }
Title: ${ secretsmanager_membership.membership.title }
Notes: ${ secretsmanager_membership.membership.notes }
======
Account Number:
---------------
%{ for n in secretsmanager_membership.membership.account_number ~}
Type: ${ n.type }
Label: ${ n.label }
Required: ${ n.required }
Privacy Screen: ${ n.privacy_screen }
Value: ${ n.value }
%{ endfor }
Name:
-----
%{ for n in secretsmanager_membership.membership.name ~}
Type: ${ n.type }
Label: ${ n.label }
Required: ${ n.required }
Privacy Screen: ${ n.privacy_screen }
First Name: ${ n.value.0.first }
Middle Name: ${ n.value.0.middle }
Last Name: ${ n.value.0.last }
%{ endfor }
Password:
---------
%{ for n in secretsmanager_membership.membership.password ~}
Type: ${ n.type }
Label: ${ n.label }
Required: ${ n.required }
Privacy Screen: ${ n.privacy_screen }
Enforce Generation: ${ n.enforce_generation }
Generate: %{ if n.generate != null }${n.generate}%{ endif }
Complexity: Length = ${ n.complexity.0.length }
Value: ${ n.value }
%{ endfor }
EOT
}
output "record_uid" {
value = secretsmanager_membership.membership.uid
}
output "record_title" {
value = secretsmanager_membership.membership.title
}
For more examples, check out the examples folder in the source code.
Store and Retrieve Secrets from the Windows Credential Manager
Windows Credential Manager is a native Windows utility that stores sensitive information, such as passwords and secrets, and allows applications to securely access it.
Keeper provides a utility, the Windows Credential Utility, that interacts with native windows APIs to store and retrieve secrets from the Windows Credential Manager. It can be used by any integration, plugin, or code base to store and retrieve credentials, secrets, and passwords in the Windows Credential Manager simply and natively.
The code base for the Windows Credential Utility can be found here:
The binary needed to use the above utility can be found here:
To use the Windows Credential Utility, you can either
deploy the pre-built binary from the releases page
or import it into your code base.
Both use cases are covered below.
Download the latest version executable from the releases page and optionally add it to PATH to get started.
The executable supports two commands:
set
get
Both commands require an application name
(i.e. the name of the credential in / to be stored in the Windows Credential Manager) as the first argument.
set
set
requires a second argument of the secret to be stored. This can be either a:
BASE64 string
JSON string
Path to an existing JSON file
When the secret is saved to Windows Credential Manager it is first encoded into a BASE64 format (if not already a BASE64 string). This standardizes the format for both consistent storage and to make it easier to consume by Keeper integrations and products.
get
get
returns the stored BASE64 encoded config to stdout
and exits with a 0
exit code. The requesting integration can capture the output for consumption. Any errors encountered retrieving the config will return an non-zero
exit code and write to stderr
.
# Save a secret
wcu set APPNAME eyJ1c2VybmFtZSI6ICJnb2xsdW0iLCAicGFzc3dvcmQiOiAiTXlQcmVjaW91cyJ9
# or
wcu set APPNAME config.json
# Retrieve a secret
wcu get APPNAME
Use Secrets Manager with automated workflows in Cortex XSOAR
Use credentials from your Keeper Vault in XSOAR workflows. Integrate with Keeper Secrets Manager to securely access all the platforms and services you connect to with XSOAR.
Follow the Quick Start Guide to enable Keeper Secrets Manager on your account.
Follow the steps in the documentation page to create a Secrets Manager configuration.
In XSOAR, follow these steps to configure the Keeper Secrets Manager integration.
Navigate to Settings > Integrations > Servers & Services.
Search for "Keeper Secrets Manager"
Click Add instance to create and configure a new integration instance.
The following options are available to configure your XSOAR integration:
KSM Configuration (Required)
The KSM config to use for connection. Paste in the configuration generated by the steps above.
Trust any certificate
When 'trust any certificate' is selected, the integration ignores TLS/SSL certificate validation errors. Use to test connection issues or connect to a server without a valid certificate.
Fetches credentials
If selected, credentials are fetched from login records.
Concat username to credential object name
when selected, the username and credential name will be combined. Use to make the credential object unique in case of duplicate names in different folders/secrets.
A comma-separated list of credential names to fetch.
Partial names are not supported. If left empty, all credentials will be fetched.
The following commands can be used in XSOAR. Use these commands to fetch records and files from the Keeper Vault. Only records that are shared to the Secrets Manager Application can be accessed by these commands.
!ksm-list-credentials
This command will only show records which can be used as credentials in XSOAR. Records must have a login and password to be used as a credential.
!ksm-list-records
This command shows all records available to XSOAR through the KSM Application.
!ksm-find-records title="<RECORD TITLE>"
add partial_match=True
to use partial matching of the record title
!ksm-get-field notation="keeper://<UID>/field/login"
!ksm-list-files
!ksm-get-file file_uid="<UID>"
!ksm-get-infofile file_uid="<UID>"
!ksm-find-files file_name="<FILENAME>"
To use Keeper Secrets Manager commands in your XSOAR playbooks, click "Task Library" and search for "Keeper" to show all the available commands.
Select a command to use and fill in the required fields if any.
Fetch a password from the Keeper Vault to login to other services in your playbook.
Search for the "ksm-get-field" command and click to add it to your playbook
Enter Keeper notation pointing to the password using the UID of the record you want to use.
This will look like: <UID>/fields/password
Any field in a record can be fetched this way. See Keeper Notation documentation for more information
Click "OK" to add the task to your playbook
You can add additional tasks after the ksm-get-field task to use the password.