Oracle Key Vault Encryption
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.
Features
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
Prerequisites
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
andDECRYPT
permissions.
Supports the JavaScript Secrets Manager SDK
Requires the oci-keymanagement package from OCI SDK.
OCI KMS Key needs
ENCRYPT
andDECRYPT
permissions.
Supports the Python Secrets Manager SDK
Requires
oci
packageUser credentials to be used will need to have key vault permissions
Supports the .Net Secrets Manager SDK.
Requires OCI.DotNetSDK.Keymanagement.
Requires
Encrypt
andDecrypt
permissions.
Supports the GoLang Secrets Manager SDK
Requires the oci-keymanagement package from OCI SDK.
OCI KMS Key needs
ENCRYPT
andDECRYPT
permissions.
Setup
1. Install Module
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
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
2. Configure Oracle KV Connection
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
)
See the Oracle documentation for more information on setting up an Oracle Keys:
https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm
Alternatively, You will need to add the correct configuration for your OCI environment, including the details for accessing Oracle Key Vault.
The configuration file should look like this (replace with your actual details):
[DEFAULT] user=ocid1.user.oc1..example_unique_id fingerprint=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx key_file=/path/to/your/private/api/key.pem tenancy=ocid1.tenancy.oc1..example_unique_id region=us-phoenix-1
3. Add Oracle Key Vault Storage to Your Code
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.
Using Oracle Key Vault Integration
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.storage_oci_key_management 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_mgmt_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())
}
}
}
Additional Options
Change Key
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)
Decrypt Config
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 👍
Check out the KSM SDKs documentation for more examples and functionality
Last updated
Was this helpful?