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

# Google Cloud Key Management Encryption

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2F6mxHlHnrBXD2jVhRoqvF%2Fksm-Google%20Cloud.jpg?alt=media&#x26;token=620bd9e5-f05a-40e4-aeaa-712da3223699" alt=""><figcaption></figcaption></figure>

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.

## Features

* 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.

## Prerequisites

To configure Google Cloud Key Management with Keeper Security, you need a service account key file (`.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>`

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

* Support the Java/Kotlin Secrets Manager SDK.
* Required GCP package `google-cloud-kms`
* GCP KMS key needs `ENCRYPT` and `DECRYPT` permissions.
  {% endtab %}

{% tab title="JavaScript" %}

* Supports the [JavaScript Secrets Manager SDK](https://github.com/Keeper-Security/gitbook-secrets-manager/blob/master/keeperpam/secrets-manager/developer-sdk-library/javascript-sdk/README.md)
* `@google-cloud/kms` is bundled — no separate install required.
* GCP KMS key needs the following IAM permissions on the service account:
  * Cloud KMS CryptoKey Encrypter
  * Cloud KMS CryptoKey Decrypter
  * Cloud KMS CryptoKey Public Key Viewer (required for asymmetric keys)
    {% endtab %}

{% tab title="Python" %}

> **Note:** v1.1.0+ requires Python 3.9+. Users on Python 3.6–3.8 should pin to `keeper-secrets-manager-storage-gcp-kms<1.1.0`.

* Supports the [Python Secrets Manager SDK](https://github.com/Keeper-Security/gitbook-secrets-manager/blob/master/keeperpam/secrets-manager/developer-sdk-library/python-sdk/README.md)
* Requires `google-cloud-kms` package and these permissions
  * Cloud KMS CryptoKey Encrypter
  * Cloud KMS CryptoKey Decrypter
  * Cloud KMS CryptoKey Public Key Viewer
  * Cloud KMS Viewer (provides `cloudkms.cryptoKeys.get`, required for key introspection on initialization)
    {% endtab %}

{% tab title=".Net" %}

* Supports the [.Net Secrets Manager SDK](https://github.com/Keeper-Security/gitbook-secrets-manager/blob/master/keeperpam/secrets-manager/developer-sdk-library/.net-sdk/README.md)
* Requires [Google.Apis.CloudKMS.v1](https://www.nuget.org/packages/Google.Apis.CloudKMS.v1)
* GCP KMS key needs `ENCRYPT` and `DECRYPT` permissions.
  {% endtab %}
  {% endtabs %}

## Setup

### 1. Install Module

{% tabs %}
{% tab title="Java" %}
Setting up project using Gradle or Maven

**Gradle**

```java
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**

```xml
<!-- 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-databind</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>
```

{% endtab %}

{% tab title="JavaScript" %}
The Secrets Manager Google Cloud Key Management module can be installed using npm

```bash
npm install @keeper-security/secrets-manager-gcp
```

{% endtab %}

{% tab title="Python" %}
The Secrets Manager Google Cloud Key Management module can be installed using pip

```bash
pip3 install keeper-secrets-manager-storage-gcp-kms
```

{% endtab %}

{% tab title=".Net" %}
The Secrets Manager Google Cloud Key Management module can be installed using dotnet nuget package manager.

```bash
dotnet add package Keeper.SecretsManager.GCPKeyManagement
```

{% endtab %}
{% endtabs %}

### 2. Configure **GCP KMS** Connection

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.

{% hint style="warning" %}
**Python v1.1.0+:** The service account must have the **Cloud KMS Viewer** IAM role (`cloudkms.cryptoKeys.get`) in addition to the Encrypter/Decrypter roles. Without it, `GCPKeyValueStorage` raises a permission error on initialization. See the Python Prerequisites tab for the full required role list.
{% endhint %}

{% hint style="info" %}
See the Google documentation for more information on generating keys:

<https://cloud.google.com/iam/docs/keys-create-delete>
{% endhint %}

### 3. Add GCP KMS Storage to Your Code

Once GCP connection has been configured, you can use the GCP KMS integration to encrypt and decrypt the KSM configuration. Tell the Secrets Manager SDK to use GCP KMS as storage.

## Using **GCP KMS Integration**

Once set up, the Secrets Manager GCP KMS integration supports all Secrets Manager SDK functionality. Your code will need to be able to access the GCP KMS keys in order to manage the encryption and decryption of the KSM configuration file.\
\
**Using Specified Connection credentials**

{% tabs %}
{% tab title="Java" %}
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.

```java
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());
		}
	}
}
```

{% endtab %}

{% tab title="JavaScript" %}
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.

```javascript
import { getSecrets, initializeStorage } from "@keeper-security/secrets-manager-core";
import { GCPKeyValueStorage, GCPKeyConfig, GCPKSMClient, LoggerLogLevelOptions } from "@keeper-security/secrets-manager-gcp";

const getKeeperRecordsGCP = async () => {
    const gcpCredFile = "<path_to_gcp_credentials.json>";
    const keyConfig = new GCPKeyConfig("<key_version_resource_url>");
    const gcpSessionConfig = new GCPKSMClient().createClientFromCredentialsFile(gcpCredFile);
    const configPath = "<path_to_client-config.json>";
    const logLevel = LoggerLogLevelOptions.info;

    // oneTimeToken is used only once to initialize the storage
    // after the first run, subsequent calls will use the encrypted config file
    const oneTimeToken = "<one_time_token>";

    const storage = await new GCPKeyValueStorage(configPath, keyConfig, gcpSessionConfig, logLevel).init();
    await initializeStorage(storage, oneTimeToken);

    const { records } = await getSecrets({ storage: storage });
    const firstRecord = records[0];
    const password = firstRecord.data.fields.find((x) => x.type === "password");
    console.log(password.value[0]);
};
getKeeperRecordsGCP();
```

{% endtab %}

{% tab title="Python" %}
To do this, use `GCPKeyValueStorage` as your Secrets Manager storage in the `SecretsManager` constructor.

The storage will require `gcp_key_config` (generated by `GCPKeyConfig` ), `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.

```python
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 = GCPKeyConfig("<key_resource_uri>")

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

{% endtab %}

{% tab title=".Net" %}
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.

```csharp
using System;
using System.Linq;
using System.Threading.Tasks;
using SecretsManager;
using GCPKeyManagement;
using Microsoft.Extensions.Logging;

public class Program {
    private static async Task Main() {
        string keyResourceName = "<key_version_resource_url>";
        string gcpConfigFilePath = "<path_to_gcp_credentials.json>";
        var keyConfig = new GCPKeyConfig(keyResourceName);
        var gcpSessionConfig = new GCPKMSClient().CreateClientFromCredentialsFile(gcpConfigFilePath);
        var ksmConfigPath = "ksm_config.json";
        var oneTimeToken = "<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, oneTimeToken);
    }
}
```

{% endtab %}
{% endtabs %}

## **Using Application Default Credentials**

{% tabs %}
{% tab title="JavaScript" %}
If you have configured credentials via `gcloud auth application-default login`, the `GOOGLE_APPLICATION_CREDENTIALS` environment variable, or are running on a GCP compute instance with a service account attached, you can omit the credentials file entirely.

```javascript
import { getSecrets, initializeStorage } from "@keeper-security/secrets-manager-core";
import { GCPKeyValueStorage, GCPKeyConfig, GCPKSMClient, LoggerLogLevelOptions } from "@keeper-security/secrets-manager-gcp";

const getKeeperRecordsGCP = async () => {
    // No credentials file needed — uses Application Default Credentials automatically
    const gcpSessionConfig = new GCPKSMClient();
    const keyConfig = new GCPKeyConfig("<key_version_resource_url>");
    const configPath = "<path_to_client-config.json>";
    const logLevel = LoggerLogLevelOptions.info;

    const oneTimeToken = "<one_time_token>";

    const storage = await new GCPKeyValueStorage(configPath, keyConfig, gcpSessionConfig, logLevel).init();
    await initializeStorage(storage, oneTimeToken);

    const { records } = await getSecrets({ storage: storage });
    const firstRecord = records[0];
    const password = firstRecord.data.fields.find((x) => x.type === "password");
    console.log(password.value[0]);
};
getKeeperRecordsGCP();
```

Alternatively, you can pass the service account email and private key directly without a file:

```javascript
const gcpSessionConfig = new GCPKSMClient().createClientUsingCredentials(
    "<service_account_email>",
    "<private_key>"
);
```

{% endtab %}

{% tab title="Python" %}
If you have configured credentials via `gcloud auth application-default login`, the `GOOGLE_APPLICATION_CREDENTIALS` environment variable, or are running on a GCP compute instance with a service account attached, you can omit the credentials file entirely.

```python
from keeper_secrets_manager_storage_gcp_kms import GCPKeyConfig, GCPKeyValueStorage, GCPKMSClientConfig
from keeper_secrets_manager_core import SecretsManager

gcp_key_config = GCPKeyConfig("<key_resource_uri>")

# Uses Application Default Credentials (gcloud auth application-default login,
# GOOGLE_APPLICATION_CREDENTIALS env var, or attached service account)
gcp_session_config = GCPKMSClientConfig().get_default_crypto_client()

config_path = "ksm_config.json"
one_time_token = "<one_time_token>"

storage = GCPKeyValueStorage(config_path, gcp_key_config, 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)
```

{% hint style="warning" %}
**ADC + RAW\_ENCRYPT\_DECRYPT limitation:** ADC cannot be used with `RAW_ENCRYPT_DECRYPT` key types. The raw KMS API path requires an OAuth token that the default client does not expose. Use `create_client_from_credentials_file()` or `create_client_using_credentials()` for raw symmetric keys.
{% endhint %}

Alternatively, you can pass the service account email and private key directly without a file:

```python
gcp_session_config = GCPKMSClientConfig().create_client_using_credentials(
    "<service_account_email>",
    "<private_key>"  # PEM-formatted private key string (the private_key field from the service account JSON), not a file path
)
```

{% endtab %}
{% endtabs %}

## 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

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

```java
GcpKeyValueStorage storage = new GcpKeyValueStorage(configFileLocation, sessionConfig);
String newKeyID = "<new_key_id>";
boolean isChanged = storage.changeKey(newKeyID);
System.out.println("Key Changed: " + isChanged);
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
// To change the GCP KMS key used for encryption, call the changeKey method on the GCPKeyValueStorage instance.
const newKeyConfig = new GCPKeyConfig("<new_key_version_resource_url>");
const storage = await new GCPKeyValueStorage(configPath, keyConfig, gcpSessionConfig).init();
await storage.changeKey(newKeyConfig);
```

{% endtab %}

{% tab title="Python" %}

```python
new_key_config = GCPKeyConfig("<new_key_resource_uri>")
storage = GCPKeyValueStorage(config_path, gcp_key_config, gcp_session_config)
is_changed = storage.change_key(new_key_config)
print("Key is changed:", is_changed)
```

{% endtab %}

{% tab title=".Net" %}

```csharp
// To change the GCP KMS key used for encryption, call ChangeKeyAsync on the GCPKeyValueStorage instance.
var gcp_storage = new GCPKeyValueStorage(keyConfig, gcpSessionConfig, path, logger);
bool isChanged = await gcp_storage.ChangeKeyAsync(newKeyConfig);
Console.WriteLine(isChanged);
```

{% endtab %}
{% endtabs %}

### Decrypt Config

You can decrypt the configuration file to migrate to a different cloud provider or to retrieve your raw credentials. Pass `true` to save the decrypted configuration back to the file, or `false` to return the plaintext without modifying the file.

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

```java
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.
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
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.
```

{% endtab %}

{% tab title="Python" %}
{% hint style="warning" %}
**v1.1.0 change:** `decrypt_config()` called without arguments now defaults to `autosave=False` (returns plaintext only, does not write to disk). In v1.0.x the default was `True`, which would overwrite the encrypted config file with plaintext credentials. Always pass the argument explicitly.
{% endhint %}

```python
storage = GCPKeyValueStorage(config_path, gcp_key_config, gcp_session_config)

# Extract only plaintext
plaintext = storage.decrypt_config(autosave=False)
print(plaintext)

# OR extract plaintext and save config as plaintext
plaintext = storage.decrypt_config(autosave=True)
print(plaintext)
```

{% endtab %}

{% tab title=".Net" %}

```csharp
// To decrypt the config file and revert to plaintext, call DecryptConfigAsync on the GCPKeyValueStorage instance.
var gcp_storage = new GCPKeyValueStorage(keyConfig, gcpSessionConfig, path, logger);
var conf = await gcp_storage.DecryptConfigAsync(false); // Returns plaintext only
Console.WriteLine(conf);
// OR
var conf = await gcp_storage.DecryptConfigAsync(true); // Returns plaintext and saves config as plaintext
Console.WriteLine(conf);
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
You're ready to use the KSM integration :thumbsup:
{% endhint %}

{% hint style="info" %}
Check out the [KSM SDKs documentation](/keeperpam/secrets-manager/developer-sdk-library.md) for more examples and functionality
{% endhint %}


---

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

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

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

```
GET https://docs.keeper.io/keeperpam/secrets-manager/integrations/google-cloud-key-management-encryption.md?ask=<question>
```

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

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