Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep 145 oci python develop #23

Open
wants to merge 2 commits into
base: KEEP-145-oracle-python-review
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,848 changes: 1,848 additions & 0 deletions sdk/javascript/packages/oracle/package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Oracle Key Vault Integration
Keeper Secrets Manager integrates with Oracle KMS 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 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 Python SDK functionality

## Prerequisites
* Supports the Python Secrets Manager SDK
* Requires `oci` package
* user credentials to be used will need to have key vault permissions

## Setup

1. Install KSM Storage Module

The Secrets Manager OCI KSM module can be installed using pip

> `pip install oci`

2. Configure OCI Connection

By default the oci library will utilize the default connection session setup located at `/home/<user>/.oci/config`.

See the OCI (documentation)[https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm] for more information on setting up an OCI session.

Alternatively, configuration variables can be provided explicitly as a service account file using the `OCISessionConfig` data class and providing a path to the service account json file, profile name, and ksm endpoint name.

To use the integration to encrypt and decrypt the configuration, please use the following steps

1. Add Oracle KMS Storage to Your Code

Now that the connection has been configured, you need to tell the Secrets Manager SDK to utilize the OracleKMS as storage.

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, as well as the name of the Secrets Manager configuration file which will be encrypted by Oracle KMS and OCI session configuration defined above.
```
from storage.keeper_secrets_manager_storage.storage_oci_key_management import OracleKeyValueStorage,OCISessionConfig
from core.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>"

oci_session_config = OCISessionConfig(config_file_location, profile, kms_crypto_endpoint,ksm_mgmt_endpoint)

config_path = "<path to config json>"
one_time_token = "<OTT>"

key_id_2 = "<second key id>"
key_version_id_2 = "<second key version>"

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.change_key(key_id, key_version_id) # this is optional and only if you want to change the key from previous configuration
print(storage.config)
secrets_manager = SecretsManager(config=storage)
all_records = secrets_manager.get_secrets()

first_record = all_records[0]
first_record_password = next(field.value[0] for field in first_record.data.fields if field.type == 'bankAccount')
print(first_record_password)
```

## Change Key

If you want to change the key from previous configuration, you can use the `change_key` method.

```
storage = OracleKeyValueStorage(key_id=key_id, key_version=key_version_id, config_file_location=config_path, oci_session_config=oci_session_config,logger=None)

key_id_2 = "<second key id>"
key_version_id_2 = "<second key version>"

storage.change_key(key_id, key_version_id)
```

## Decrypt config

Note : Danger Zone :: You can use this method to decrypt the config file. This is not recommended for production use.

```
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()
```

You're ready to use the KSM integration 👍
Using the OCI KMS Integration

Once setup, the Secrets Manager OCI KMS integration supports all Secrets Manager Python SDK functionality. Your code will need to be able to access the Oracle KMS APIs in order to manage the decryption of the configuration file when run.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# _ __
# | |/ /___ ___ _ __ ___ _ _ (R)
# | ' </ -_) -_) '_ \/ -_) '_|
# |_|\_\___\___| .__/\___|_|
# |_|
#
# Keeper Secrets Manager
# Copyright 2025 Keeper Security Inc.
# Contact: [email protected]

from .oci_session_config import OCISessionConfig
from .oracle_key_value_storage import OracleKeyValueStorage

__all__ = [
"OCISessionConfig",
"OracleKeyValueStorage",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# _ __
# | |/ /___ ___ _ __ ___ _ _ (R)
# | ' </ -_) -_) '_ \/ -_) '_|
# |_|\_\___\___| .__/\___|_|
# |_|
#
# Keeper Secrets Manager
# Copyright 2025 Keeper Security Inc.
# Contact: [email protected]

BLOB_HEADER = b"\xff\xff" # Encrypted BLOB Header: U+FFFF is a non-character
UTF_8_ENCODING = "utf-8"
AES_256_GCM = "aes-256-gcm"
MD5_HASH = "md5"
HEX_DIGEST = "hex"
DEFAULT_JSON_INDENT = 4
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# _ __
# | |/ /___ ___ _ __ ___ _ _ (R)
# | ' </ -_) -_) '_ \/ -_) '_|
# |_|\_\___\___| .__/\___|_|
# |_|
#
# Keeper Secrets Manager
# Copyright 2025 Keeper Security Inc.
# Contact: [email protected]

import logging
import traceback
from .oci_session_config import OCISessionConfig

try:
from oci.key_management import KmsCryptoClient,KmsManagementClient
except ImportError:
logging.getLogger().error("Missing OCI import dependencies."
" To install missing packages run: \r\n"
"pip install --upgrade \"oci\"\r\n")
raise Exception(f"Missing import dependencies: oci. Additional data related to error is as follows: {traceback.format_exc()}")

class OciKmsClient:
def __init__(self, session_config: OCISessionConfig):
self.oci_kms_crypto_client = KmsCryptoClient(session_config.get_provider(), session_config.get_kms_crypto_endpoint())
self.oci_kms_management_client = KmsManagementClient(session_config.get_provider(), session_config.get_kms_management_endpoint())

def get_crypto_client(self) -> KmsCryptoClient:
return self.oci_kms_crypto_client

def get_management_client(self) -> KmsManagementClient:
return self.oci_kms_management_client
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# _ __
# | |/ /___ ___ _ __ ___ _ _ (R)
# | ' </ -_) -_) '_ \/ -_) '_|
# |_|\_\___\___| .__/\___|_|
# |_|
#
# Keeper Secrets Manager
# Copyright 2025 Keeper Security Inc.
# Contact: [email protected]

from oci.config import from_file
from typing import Optional

class OCISessionConfig:
def __init__(self, oci_config_file_location: str, profile: Optional[str] = None, kms_crypto_endpoint: str = "",kms_management_endpoint: str = ""):
self.oci_config_file_location = oci_config_file_location
self.profile = profile if profile else "DEFAULT"
self.kms_crypto_endpoint = kms_crypto_endpoint
self.kms_management_endpoint = kms_management_endpoint

def get_provider(self):
return from_file(self.oci_config_file_location, self.profile)

def get_kms_crypto_endpoint(self) -> str:
return self.kms_crypto_endpoint

def get_kms_management_endpoint(self) -> str:
return self.kms_management_endpoint
Loading