From e337c21551b685e42b0c8d3f9fffa2fe672a0b01 Mon Sep 17 00:00:00 2001 From: Dhaval Bhensdadiya Date: Wed, 21 Jan 2026 10:58:27 +0530 Subject: [PATCH 1/5] Adding code samples for creating secret with customer managed encryption key and deleting annotations from the secret --- secretmanager/README.md | 4 +- .../secretmanager/CreateSecretWithCmek.java | 76 ++++++++++++++++ .../DeleteSecretAnnotations.java | 77 ++++++++++++++++ .../CreateRegionalSecretWithCmek.java | 75 ++++++++++++++++ .../DeleteRegionalSecretAnnotations.java | 88 +++++++++++++++++++ .../test/java/secretmanager/SnippetsIT.java | 28 +++++- .../regionalsamples/SnippetsIT.java | 29 ++++++ 7 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java create mode 100644 secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java create mode 100644 secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java create mode 100644 secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java diff --git a/secretmanager/README.md b/secretmanager/README.md index 0af70bfd6bf..0ffcc0d9ec0 100644 --- a/secretmanager/README.md +++ b/secretmanager/README.md @@ -16,10 +16,12 @@ You must [enable the Secret Manager API](https://console.cloud.google.com/flows/ ### Set Environment Variables -You must set your project ID in order to run the tests +You must set your project ID, KMS Keys (Global and Regional) in order to run the tests ```text $ export GOOGLE_CLOUD_PROJECT= +$ export GOOGLE_CLOUD_REGIONAL_KMS_KEY= (region same as location) +$ export GOOGLE_CLOUD_KMS_KEY= ``` ### Grant Permissions diff --git a/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java b/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java new file mode 100644 index 00000000000..b185047a2e0 --- /dev/null +++ b/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java @@ -0,0 +1,76 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package secretmanager; + +// [START secretmanager_create_secret_with_annotations] +import com.google.cloud.secretmanager.v1.CustomerManagedEncryption; +import com.google.cloud.secretmanager.v1.ProjectName; +import com.google.cloud.secretmanager.v1.Replication; +import com.google.cloud.secretmanager.v1.Secret; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import java.io.IOException; + +public class CreateSecretWithCmek { + + public static void main() throws IOException { + // TODO(developer): Replace these variables before running the sample. + + // This is the id of the GCP project + String projectId = "your-project-id"; + // This is the id of the secret to act on + String secretId = "your-secret-id"; + // This is the Full kms key name to be used for Cmek. + String kmsKeyName = "your-kms-key-name"; + createSecretWithCmek(projectId, secretId, kmsKeyName); + } + + // Create a secret with annotations. + public static Secret createSecretWithCmek(String projectId, String secretId, String kmsKeyName) + throws IOException { + + // Initialize client that will be used to send requests. This client only needs + // to be created + // once, and can be reused for multiple requests. + try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) { + + // Build the secret name. + ProjectName projectName = ProjectName.of(projectId); + + // Build the Cmek configuration. + CustomerManagedEncryption customerManagedEncryption = + CustomerManagedEncryption.newBuilder().setKmsKeyName(kmsKeyName).build(); + + // Build the replication using Cmek. + Replication secretReplication = + Replication.newBuilder() + .setAutomatic( + Replication.Automatic.newBuilder() + .setCustomerManagedEncryption(customerManagedEncryption) + .build()) + .build(); + + // Build the secret to create with labels. + Secret secret = Secret.newBuilder().setReplication(secretReplication).build(); + + // Create the secret. + Secret createdSecret = client.createSecret(projectName, secretId, secret); + System.out.printf("Created secret %s\n", createdSecret.getName()); + return createdSecret; + } + } +} +// [END secretmanager_create_secret_with_annotations] diff --git a/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java b/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java new file mode 100644 index 00000000000..679d57b357b --- /dev/null +++ b/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java @@ -0,0 +1,77 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package secretmanager; + +// [START secretmanager_delete_secret_annotations] +import com.google.cloud.secretmanager.v1.Secret; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretName; +import com.google.protobuf.FieldMask; +import com.google.protobuf.util.FieldMaskUtil; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class DeleteSecretAnnotations { + + public static void main() throws IOException { + // TODO(developer): Replace these variables before running the sample. + + // This is the id of the GCP project + String projectId = "your-project-id"; + // This is the id of the secret to act on + String secretId = "your-secret-id"; + deleteSecretAnnotations(projectId, secretId); + } + + // Delete annotations from an existing secret. + public static Secret deleteSecretAnnotations(String projectId, String secretId) + throws IOException { + // Initialize client that will be used to send requests. This client only needs + // to be created + // once, and can be reused for multiple requests. + try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) { + // Build the name of the secret. + SecretName secretName = SecretName.of(projectId, secretId); + + // Get the current secret + Secret existingSecret = client.getSecret(secretName); + + // Remove all annotations + Map existingAnnotationsMap = + new HashMap(existingSecret.getAnnotationsMap()); + existingAnnotationsMap.clear(); + + // Build the updated secret. + Secret secret = + Secret.newBuilder() + .setName(secretName.toString()) + .putAllAnnotations(existingAnnotationsMap) + .build(); + + // Create the field mask for updating only the annotations + FieldMask fieldMask = FieldMaskUtil.fromString("annotations"); + + // Update the secret. + Secret updatedSecret = client.updateSecret(secret, fieldMask); + System.out.printf("Deleted annotations from %s\n", updatedSecret.getName()); + + return updatedSecret; + } + } +} +// [END secretmanager_delete_secret_annotations] diff --git a/secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java b/secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java new file mode 100644 index 00000000000..21f139bfad6 --- /dev/null +++ b/secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java @@ -0,0 +1,75 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package secretmanager.regionalsamples; + +// [START secretmanager_create_regional_secret_with_cmek] +import com.google.cloud.secretmanager.v1.CustomerManagedEncryption; +import com.google.cloud.secretmanager.v1.LocationName; +import com.google.cloud.secretmanager.v1.Secret; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; +import java.io.IOException; + +public class CreateRegionalSecretWithCmek { + + public static void main() throws IOException { + // TODO(developer): Replace these variables before running the sample. + + // This is the id of the GCP project + String projectId = "your-project-id"; + // Location of the secret. + String locationId = "your-location-id"; + // This is the id of the secret to act on + String secretId = "your-secret-id"; + // This is the Full kms key name to be used for Cmek. + String kmsKeyName = "your-kms-key-name"; + createRegionalSecretWithCmek(projectId, locationId, secretId, kmsKeyName); + } + + // Create a new regional secret with customer-managed encryption key. + public static Secret createRegionalSecretWithCmek( + String projectId, String locationId, String secretId, String kmsKeyName) throws IOException { + + // Endpoint to call the regional secret manager server + String apiEndpoint = String.format("secretmanager.%s.rep.googleapis.com:443", locationId); + SecretManagerServiceSettings secretManagerServiceSettings = + SecretManagerServiceSettings.newBuilder().setEndpoint(apiEndpoint).build(); + + // Initialize client that will be used to send requests. This client only needs + // to be created + // once, and can be reused for multiple requests. + try (SecretManagerServiceClient client = + SecretManagerServiceClient.create(secretManagerServiceSettings)) { + // Build the parent name from the project and location. + LocationName locationName = LocationName.of(projectId, locationId); + + // Build the customer-managed encryption configuration. + CustomerManagedEncryption customerManagedEncryption = + CustomerManagedEncryption.newBuilder().setKmsKeyName(kmsKeyName).build(); + + // Build the secret with customer-managed encryption key. + Secret secret = + Secret.newBuilder().setCustomerManagedEncryption(customerManagedEncryption).build(); + + // Create the secret. + Secret createdSecret = client.createSecret(locationName.toString(), secretId, secret); + System.out.printf("Created secret %s\n", createdSecret.getName()); + return createdSecret; + } + } +} +// [END secretmanager_create_regional_secret_with_cmek] diff --git a/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java b/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java new file mode 100644 index 00000000000..ddd4c46fa40 --- /dev/null +++ b/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java @@ -0,0 +1,88 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package secretmanager.regionalsamples; + +// [START secretmanager_delete_regional_secret_annotations] +import com.google.cloud.secretmanager.v1.Secret; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; +import com.google.cloud.secretmanager.v1.SecretName; +import com.google.protobuf.FieldMask; +import com.google.protobuf.util.FieldMaskUtil; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class DeleteRegionalSecretAnnotations { + + public static void main() throws IOException { + // TODO(developer): Replace these variables before running the sample. + + // This is the id of the GCP project + String projectId = "your-project-id"; + // Location of the secret. + String locationId = "your-location-id"; + // This is the id of the secret to act on + String secretId = "your-secret-id"; + deleteRegionalSecretAnnotations(projectId, locationId, secretId); + } + + // Delete annotations from an existing regional secret. + public static Secret deleteRegionalSecretAnnotations( + String projectId, String locationId, String secretId) throws IOException { + + // Endpoint to call the regional secret manager server + String apiEndpoint = String.format("secretmanager.%s.rep.googleapis.com:443", locationId); + SecretManagerServiceSettings secretManagerServiceSettings = + SecretManagerServiceSettings.newBuilder().setEndpoint(apiEndpoint).build(); + + // Initialize client that will be used to send requests. This client only needs + // to be created + // once, and can be reused for multiple requests. + try (SecretManagerServiceClient client = + SecretManagerServiceClient.create(secretManagerServiceSettings)) { + // Build the name of the secret. + SecretName secretName = + SecretName.ofProjectLocationSecretName(projectId, locationId, secretId); + + // Get the current secret + Secret existingSecret = client.getSecret(secretName); + + // Remove all annotations + Map existingAnnotationsMap = + new HashMap(existingSecret.getAnnotationsMap()); + existingAnnotationsMap.clear(); + + // Build the updated secret. + Secret secret = + Secret.newBuilder() + .setName(secretName.toString()) + .putAllAnnotations(existingAnnotationsMap) + .build(); + + // Create the field mask for updating only the annotations + FieldMask fieldMask = FieldMaskUtil.fromString("annotations"); + + // Update the secret. + Secret updatedSecret = client.updateSecret(secret, fieldMask); + System.out.printf("Deleted annotations from %s\n", updatedSecret.getName()); + + return updatedSecret; + } + } +} +// [END secretmanager_delete_regional_secret_annotations] diff --git a/secretmanager/src/test/java/secretmanager/SnippetsIT.java b/secretmanager/src/test/java/secretmanager/SnippetsIT.java index 41f88a1e6d9..81d58119be4 100644 --- a/secretmanager/src/test/java/secretmanager/SnippetsIT.java +++ b/secretmanager/src/test/java/secretmanager/SnippetsIT.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import com.google.api.gax.longrunning.OperationFuture; import com.google.cloud.resourcemanager.v3.CreateTagKeyMetadata; @@ -77,11 +78,13 @@ public class SnippetsIT { private static final String IAM_USER = "serviceAccount:iam-samples@java-docs-samples-testing.iam.gserviceaccount.com"; private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String KMS_KEY_NAME = System.getenv("GOOGLE_CLOUD_KMS_KEY"); private static final String LABEL_KEY = "examplelabelkey"; private static final String LABEL_VALUE = "examplelabelvalue"; private static final String UPDATED_LABEL_KEY = "updatedlabelkey"; private static final String UPDATED_LABEL_VALUE = "updatedlabelvalue"; - private static final String ANNOTATION_KEY = "exampleannotationkey"; + private static final String ANNOTATION_KEY = + "exampleannotationkey"; private static final String ANNOTATION_VALUE = "exampleannotationvalue"; private static final String UPDATED_ANNOTATION_KEY = "updatedannotationkey"; private static final String UPDATED_ANNOTATION_VALUE = "updatedannotationvalue"; @@ -96,6 +99,7 @@ public class SnippetsIT { private static SecretName TEST_SECRET_WITH_LABEL_TO_CREATE_NAME; private static SecretName TEST_SECRET_WITH_TAGS_TO_CREATE_NAME; private static SecretName TEST_SECRET_WITH_ANNOTATION_TO_CREATE_NAME; + private static SecretName TEST_SECRET_WITH_CMEK_TO_CREATE_NAME; private static SecretName TEST_UMMR_SECRET_TO_CREATE_NAME; private static SecretVersion TEST_SECRET_VERSION; private static SecretVersion TEST_SECRET_VERSION_TO_DESTROY; @@ -125,6 +129,7 @@ public static void beforeAll() throws Exception { TEST_SECRET_WITH_TAGS_TO_CREATE_NAME = SecretName.of(PROJECT_ID, randomSecretId()); TEST_SECRET_WITH_LABEL_TO_CREATE_NAME = SecretName.of(PROJECT_ID, randomSecretId()); TEST_SECRET_WITH_ANNOTATION_TO_CREATE_NAME = SecretName.of(PROJECT_ID, randomSecretId()); + TEST_SECRET_WITH_CMEK_TO_CREATE_NAME = SecretName.of(PROJECT_ID, randomSecretId()); TEST_SECRET_VERSION = addSecretVersion(TEST_SECRET_WITH_VERSIONS); TEST_SECRET_VERSION_TO_DESTROY = addSecretVersion(TEST_SECRET_WITH_VERSIONS); @@ -154,12 +159,14 @@ public void afterEach() { @AfterClass public static void afterAll() throws Exception { Assert.assertFalse("missing GOOGLE_CLOUD_PROJECT", Strings.isNullOrEmpty(PROJECT_ID)); + Assert.assertFalse("missing GOOGLE_CLOUD_KMS_KEY", Strings.isNullOrEmpty(KMS_KEY_NAME)); deleteSecret(TEST_SECRET.getName()); deleteSecret(TEST_SECRET_TO_CREATE_NAME.toString()); deleteSecret(TEST_SECRET_WITH_TAGS_TO_CREATE_NAME.toString()); deleteSecret(TEST_SECRET_WITH_LABEL_TO_CREATE_NAME.toString()); deleteSecret(TEST_SECRET_WITH_ANNOTATION_TO_CREATE_NAME.toString()); + deleteSecret(TEST_SECRET_WITH_CMEK_TO_CREATE_NAME.toString()); deleteSecret(TEST_UMMR_SECRET_TO_CREATE_NAME.toString()); deleteSecret(TEST_SECRET_TO_DELETE.getName()); deleteSecret(TEST_SECRET_TO_DELETE_WITH_ETAG.getName()); @@ -367,6 +374,16 @@ public void testCreateSecretWithAnnotations() throws IOException { assertThat(secret.getAnnotationsMap()).containsEntry(ANNOTATION_KEY, ANNOTATION_VALUE); } + @Test + public void testCreateSecretWithCmek() throws IOException { + SecretName name = TEST_SECRET_WITH_CMEK_TO_CREATE_NAME; + Secret secret = CreateSecretWithCmek.createSecretWithCmek( + name.getProject(), name.getSecret(), KMS_KEY_NAME); + + assertThat(secret.getReplication().getAutomatic().getCustomerManagedEncryption() + .getKmsKeyName()).isEqualTo(KMS_KEY_NAME); + } + @Test public void testCreateSecretWithUserManagedReplication() throws IOException { SecretName name = TEST_UMMR_SECRET_TO_CREATE_NAME; @@ -581,6 +598,15 @@ public void testEditSecretAnnotations() throws IOException { UPDATED_ANNOTATION_KEY, UPDATED_ANNOTATION_VALUE); } + @Test + public void testDeleteSecretAnnotations() throws IOException { + SecretName name = SecretName.parse(TEST_SECRET.getName()); + Secret updatedSecret = + DeleteSecretAnnotations.deleteSecretAnnotations(name.getProject(), name.getSecret()); + + assertTrue(updatedSecret.getAnnotationsMap().isEmpty()); + } + @Test public void testUpdateSecretWithAlias() throws IOException { SecretName name = SecretName.parse(TEST_SECRET_WITH_VERSIONS.getName()); diff --git a/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java b/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java index 11ca876dc30..59aab3567bf 100644 --- a/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java +++ b/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java @@ -83,6 +83,8 @@ public class SnippetsIT { private static final String IAM_USER = "serviceAccount:iam-samples@java-docs-samples-testing.iam.gserviceaccount.com"; private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGIONAL_KMS_KEY_NAME = + System.getenv("GOOGLE_CLOUD_REGIONAL_KMS_KEY"); private static final String LABEL_KEY = "examplelabelkey"; private static final String LABEL_VALUE = "examplelabelvalue"; private static final String UPDATED_LABEL_KEY = "updatedlabelkey"; @@ -105,6 +107,7 @@ public class SnippetsIT { private static SecretName TEST_REGIONAL_SECRET_WITH_LABEL_TO_CREATE_NAME; private static SecretName TEST_REGIONAL_SECRET_WITH_TAGS_TO_CREATE_NAME; private static SecretName TEST_REGIONAL_SECRET_WITH_ANNOTATION_TO_CREATE_NAME; + private static SecretName TEST_REGIONAL_SECRET_WITH_CMEK_TO_CREATE_NAME; private static SecretVersion TEST_REGIONAL_SECRET_VERSION; private static SecretVersion TEST_REGIONAL_SECRET_VERSION_TO_DESTROY; private static SecretVersion TEST_REGIONAL_SECRET_VERSION_TO_DESTROY_WITH_ETAG; @@ -123,6 +126,8 @@ public static void beforeAll() throws Exception { Assert.assertFalse("missing GOOGLE_CLOUD_PROJECT", Strings.isNullOrEmpty(PROJECT_ID)); Assert.assertFalse("missing GOOGLE_CLOUD_PROJECT_LOCATION", Strings.isNullOrEmpty(LOCATION_ID)); + Assert.assertFalse("missing REGIONAL_KMS_KEY_NAME", + Strings.isNullOrEmpty(REGIONAL_KMS_KEY_NAME)); TEST_REGIONAL_SECRET = createRegionalSecret(); TEST_REGIONAL_SECRET_TO_DELETE = createRegionalSecret(); @@ -135,6 +140,8 @@ public static void beforeAll() throws Exception { SecretName.ofProjectLocationSecretName(PROJECT_ID, LOCATION_ID, randomSecretId()); TEST_REGIONAL_SECRET_WITH_ANNOTATION_TO_CREATE_NAME = SecretName.ofProjectLocationSecretName(PROJECT_ID, LOCATION_ID, randomSecretId()); + TEST_REGIONAL_SECRET_WITH_CMEK_TO_CREATE_NAME = + SecretName.ofProjectLocationSecretName(PROJECT_ID, LOCATION_ID, randomSecretId()); TEST_REGIONAL_SECRET_WITH_LABEL_TO_CREATE_NAME = SecretName.ofProjectLocationSecretName(PROJECT_ID, LOCATION_ID, randomSecretId()); @@ -180,6 +187,7 @@ public static void afterAll() throws Exception { deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_LABEL_TO_CREATE_NAME.toString()); deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_TAGS_TO_CREATE_NAME.toString()); deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_ANNOTATION_TO_CREATE_NAME.toString()); + deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_CMEK_TO_CREATE_NAME.toString()); deleteRegionalSecret(TEST_REGIONAL_SECRET_TO_DELETE.getName()); deleteRegionalSecret(TEST_REGIONAL_SECRET_TO_DELETE_WITH_ETAG.getName()); deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_VERSIONS.getName()); @@ -398,6 +406,17 @@ public void testCreateRegionalSecretWithAnnotations() throws IOException { assertEquals(name.getSecret(), createdSecretName.getSecret()); } + @Test + public void testCreateRegionalSecretWithCmek() throws IOException { + SecretName name = TEST_REGIONAL_SECRET_WITH_CMEK_TO_CREATE_NAME; + Secret secret = CreateRegionalSecretWithCmek.createRegionalSecretWithCmek( + name.getProject(), name.getLocation(), name.getSecret(), REGIONAL_KMS_KEY_NAME); + + assertThat( + secret.getCustomerManagedEncryption().getKmsKeyName() + ).isEqualTo(REGIONAL_KMS_KEY_NAME); + } + @Test public void testDeleteRegionalSecret() throws IOException { SecretName name = SecretName.parse(TEST_REGIONAL_SECRET_TO_DELETE.getName()); @@ -682,6 +701,16 @@ public void testEditSecretAnnotations() throws IOException { UPDATED_ANNOTATION_KEY, UPDATED_ANNOTATION_VALUE); } + @Test + public void testDeleteRegionalSecretAnnotations() throws IOException { + SecretName name = SecretName.parse(TEST_REGIONAL_SECRET.getName()); + Secret updatedSecret = DeleteRegionalSecretAnnotations.deleteRegionalSecretAnnotations( + name.getProject(), name.getLocation(), name.getSecret()); + + assertTrue(updatedSecret.getAnnotationsMap().isEmpty()); + } + + @Test public void testCreateRegionalSecretWithDelayedDestroy() throws IOException { SecretName name = TEST_REGIONAL_SECRET_WITH_DELAYED_DESTROY; From 36203bb30aefeab19e4c0ca7168d01fa0a8f341f Mon Sep 17 00:00:00 2001 From: Dhaval Bhensdadiya Date: Wed, 21 Jan 2026 11:30:47 +0530 Subject: [PATCH 2/5] Improved readme and created new secret specific for deleting annotations --- secretmanager/README.md | 3 ++- secretmanager/src/test/java/secretmanager/SnippetsIT.java | 5 ++++- .../test/java/secretmanager/regionalsamples/SnippetsIT.java | 5 ++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/secretmanager/README.md b/secretmanager/README.md index 0ffcc0d9ec0..72e712540d1 100644 --- a/secretmanager/README.md +++ b/secretmanager/README.md @@ -12,7 +12,7 @@ the Secret Manager API using the Google Java API Client Libraries. ### Enable the API -You must [enable the Secret Manager API](https://console.cloud.google.com/flows/enableapi?apiid=secretmanager.googleapis.com) for your project in order to use these samples +You must enable the [Secret Manager API](https://console.cloud.google.com/flows/enableapi?apiid=secretmanager.googleapis.com) and [Cloud KMS API](https://console.cloud.google.com/flows/enableapi?apiid=cloudkms.googleapis.com) for your project in order to use these samples ### Set Environment Variables @@ -30,5 +30,6 @@ You must ensure that the [user account or service account](https://cloud.google. * Secret Manager Admin (`roles/secretmanager.admin`) * Secret Manager Secret Accessor (`roles/secretmanager.secretAccessor`) +* Cloud KMS Encrypter / Decrypter (`roles/cloudkms.cryptoKeyEncrypterDecrypter`) on the regional and global KMS key used for testing More information can be found in the [Secret Manager Docs](https://cloud.google.com/secret-manager/docs/access-control) diff --git a/secretmanager/src/test/java/secretmanager/SnippetsIT.java b/secretmanager/src/test/java/secretmanager/SnippetsIT.java index 81d58119be4..e2c6a362a45 100644 --- a/secretmanager/src/test/java/secretmanager/SnippetsIT.java +++ b/secretmanager/src/test/java/secretmanager/SnippetsIT.java @@ -92,6 +92,7 @@ public class SnippetsIT { private static Secret TEST_SECRET; private static Secret TEST_SECRET_TO_DELETE; private static Secret TEST_SECRET_TO_DELETE_WITH_ETAG; + private static Secret TEST_SECRET_TO_DELETE_ANNOTATIONS; private static Secret TEST_SECRET_TO_DELAYED_DESTROY; private static Secret TEST_SECRET_WITH_VERSIONS; private static SecretName TEST_SECRET_WITH_DELAYED_DESTROY; @@ -121,6 +122,7 @@ public static void beforeAll() throws Exception { TEST_SECRET = createSecret(true); TEST_SECRET_TO_DELETE = createSecret(false); TEST_SECRET_TO_DELETE_WITH_ETAG = createSecret(false); + TEST_SECRET_TO_DELETE_ANNOTATIONS = createSecret(true); TEST_SECRET_WITH_VERSIONS = createSecret(false); TEST_SECRET_TO_DELAYED_DESTROY = createSecret(false); TEST_SECRET_WITH_DELAYED_DESTROY = SecretName.of(PROJECT_ID, randomSecretId()); @@ -170,6 +172,7 @@ public static void afterAll() throws Exception { deleteSecret(TEST_UMMR_SECRET_TO_CREATE_NAME.toString()); deleteSecret(TEST_SECRET_TO_DELETE.getName()); deleteSecret(TEST_SECRET_TO_DELETE_WITH_ETAG.getName()); + deleteSecret(TEST_SECRET_TO_DELETE_ANNOTATIONS.getName()); deleteSecret(TEST_SECRET_WITH_VERSIONS.getName()); deleteSecret(TEST_SECRET_WITH_DELAYED_DESTROY.toString()); deleteSecret(TEST_SECRET_TO_DELAYED_DESTROY.getName()); @@ -600,7 +603,7 @@ public void testEditSecretAnnotations() throws IOException { @Test public void testDeleteSecretAnnotations() throws IOException { - SecretName name = SecretName.parse(TEST_SECRET.getName()); + SecretName name = SecretName.parse(TEST_SECRET_TO_DELETE_ANNOTATIONS.getName()); Secret updatedSecret = DeleteSecretAnnotations.deleteSecretAnnotations(name.getProject(), name.getSecret()); diff --git a/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java b/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java index 59aab3567bf..067a69b1e33 100644 --- a/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java +++ b/secretmanager/src/test/java/secretmanager/regionalsamples/SnippetsIT.java @@ -100,6 +100,7 @@ public class SnippetsIT { private static Secret TEST_REGIONAL_SECRET; private static Secret TEST_REGIONAL_SECRET_TO_DELETE; private static Secret TEST_REGIONAL_SECRET_TO_DELETE_WITH_ETAG; + private static Secret TEST_REGIONAL_SECRET_TO_DELETE_ANNOTATIONS; private static Secret TEST_REGIONAL_SECRET_WITH_VERSIONS; private static Secret TEST_REGIONAL_SECRET_TO_DELAYED_DESTROY; private static SecretName TEST_REGIONAL_SECRET_WITH_DELAYED_DESTROY; @@ -132,6 +133,7 @@ public static void beforeAll() throws Exception { TEST_REGIONAL_SECRET = createRegionalSecret(); TEST_REGIONAL_SECRET_TO_DELETE = createRegionalSecret(); TEST_REGIONAL_SECRET_TO_DELETE_WITH_ETAG = createRegionalSecret(); + TEST_REGIONAL_SECRET_TO_DELETE_ANNOTATIONS = createRegionalSecret(); TEST_REGIONAL_SECRET_WITH_VERSIONS = createRegionalSecret(); TEST_REGIONAL_SECRET_TO_DELAYED_DESTROY = createRegionalSecret(); TEST_REGIONAL_SECRET_WITH_DELAYED_DESTROY = @@ -190,6 +192,7 @@ public static void afterAll() throws Exception { deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_CMEK_TO_CREATE_NAME.toString()); deleteRegionalSecret(TEST_REGIONAL_SECRET_TO_DELETE.getName()); deleteRegionalSecret(TEST_REGIONAL_SECRET_TO_DELETE_WITH_ETAG.getName()); + deleteRegionalSecret(TEST_REGIONAL_SECRET_TO_DELETE_ANNOTATIONS.getName()); deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_VERSIONS.getName()); deleteRegionalSecret(TEST_REGIONAL_SECRET_WITH_DELAYED_DESTROY.toString()); deleteRegionalSecret(TEST_REGIONAL_SECRET_TO_DELAYED_DESTROY.getName()); @@ -703,7 +706,7 @@ public void testEditSecretAnnotations() throws IOException { @Test public void testDeleteRegionalSecretAnnotations() throws IOException { - SecretName name = SecretName.parse(TEST_REGIONAL_SECRET.getName()); + SecretName name = SecretName.parse(TEST_REGIONAL_SECRET_TO_DELETE_ANNOTATIONS.getName()); Secret updatedSecret = DeleteRegionalSecretAnnotations.deleteRegionalSecretAnnotations( name.getProject(), name.getLocation(), name.getSecret()); From 0acae1650bc78396a90c357f974dcb8ddbafb5c2 Mon Sep 17 00:00:00 2001 From: dhavalbhensdadiya-crest Date: Wed, 21 Jan 2026 11:38:44 +0530 Subject: [PATCH 3/5] Applied suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../java/secretmanager/CreateSecretWithCmek.java | 8 ++++---- .../java/secretmanager/DeleteSecretAnnotations.java | 12 ++---------- .../DeleteRegionalSecretAnnotations.java | 12 ++---------- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java b/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java index b185047a2e0..64d23cceefd 100644 --- a/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java +++ b/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java @@ -16,7 +16,7 @@ package secretmanager; -// [START secretmanager_create_secret_with_annotations] +// [START secretmanager_create_secret_with_cmek] import com.google.cloud.secretmanager.v1.CustomerManagedEncryption; import com.google.cloud.secretmanager.v1.ProjectName; import com.google.cloud.secretmanager.v1.Replication; @@ -38,7 +38,7 @@ public static void main() throws IOException { createSecretWithCmek(projectId, secretId, kmsKeyName); } - // Create a secret with annotations. + // Create a secret with a customer-managed encryption key (CMEK). public static Secret createSecretWithCmek(String projectId, String secretId, String kmsKeyName) throws IOException { @@ -63,7 +63,7 @@ public static Secret createSecretWithCmek(String projectId, String secretId, Str .build()) .build(); - // Build the secret to create with labels. + // Build the secret to create with the replication policy. Secret secret = Secret.newBuilder().setReplication(secretReplication).build(); // Create the secret. @@ -73,4 +73,4 @@ public static Secret createSecretWithCmek(String projectId, String secretId, Str } } } -// [END secretmanager_create_secret_with_annotations] +// [END secretmanager_create_secret_with_cmek] diff --git a/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java b/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java index 679d57b357b..20a6f9cc5cb 100644 --- a/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java +++ b/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java @@ -48,19 +48,11 @@ public static Secret deleteSecretAnnotations(String projectId, String secretId) // Build the name of the secret. SecretName secretName = SecretName.of(projectId, secretId); - // Get the current secret - Secret existingSecret = client.getSecret(secretName); - - // Remove all annotations - Map existingAnnotationsMap = - new HashMap(existingSecret.getAnnotationsMap()); - existingAnnotationsMap.clear(); - - // Build the updated secret. + // Build the updated secret with an empty annotations map. Secret secret = Secret.newBuilder() .setName(secretName.toString()) - .putAllAnnotations(existingAnnotationsMap) + .putAllAnnotations(new HashMap<>()) .build(); // Create the field mask for updating only the annotations diff --git a/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java b/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java index ddd4c46fa40..fd34f0db992 100644 --- a/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java +++ b/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java @@ -59,19 +59,11 @@ public static Secret deleteRegionalSecretAnnotations( SecretName secretName = SecretName.ofProjectLocationSecretName(projectId, locationId, secretId); - // Get the current secret - Secret existingSecret = client.getSecret(secretName); - - // Remove all annotations - Map existingAnnotationsMap = - new HashMap(existingSecret.getAnnotationsMap()); - existingAnnotationsMap.clear(); - - // Build the updated secret. + // Build the updated secret with an empty annotations map. Secret secret = Secret.newBuilder() .setName(secretName.toString()) - .putAllAnnotations(existingAnnotationsMap) + .putAllAnnotations(new HashMap<>()) .build(); // Create the field mask for updating only the annotations From 9d6e4ee2d3e7adf475b49165638efe78a20c8c39 Mon Sep 17 00:00:00 2001 From: Dhaval Bhensdadiya Date: Thu, 22 Jan 2026 12:49:52 +0530 Subject: [PATCH 4/5] Added args to main function --- .../src/main/java/secretmanager/CreateSecretWithCmek.java | 2 +- .../src/main/java/secretmanager/DeleteSecretAnnotations.java | 4 ++-- .../regionalsamples/CreateRegionalSecretWithCmek.java | 2 +- .../regionalsamples/DeleteRegionalSecretAnnotations.java | 3 +-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java b/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java index 64d23cceefd..4f4fae9f911 100644 --- a/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java +++ b/secretmanager/src/main/java/secretmanager/CreateSecretWithCmek.java @@ -26,7 +26,7 @@ public class CreateSecretWithCmek { - public static void main() throws IOException { + public static void main(String[] args) throws IOException { // TODO(developer): Replace these variables before running the sample. // This is the id of the GCP project diff --git a/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java b/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java index 20a6f9cc5cb..c689d1bc813 100644 --- a/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java +++ b/secretmanager/src/main/java/secretmanager/DeleteSecretAnnotations.java @@ -24,11 +24,11 @@ import com.google.protobuf.util.FieldMaskUtil; import java.io.IOException; import java.util.HashMap; -import java.util.Map; public class DeleteSecretAnnotations { - public static void main() throws IOException { + + public static void main(String[] args) throws IOException { // TODO(developer): Replace these variables before running the sample. // This is the id of the GCP project diff --git a/secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java b/secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java index 21f139bfad6..ac52811d658 100644 --- a/secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java +++ b/secretmanager/src/main/java/secretmanager/regionalsamples/CreateRegionalSecretWithCmek.java @@ -26,7 +26,7 @@ public class CreateRegionalSecretWithCmek { - public static void main() throws IOException { + public static void main(String[] args) throws IOException { // TODO(developer): Replace these variables before running the sample. // This is the id of the GCP project diff --git a/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java b/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java index fd34f0db992..babbd3ef636 100644 --- a/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java +++ b/secretmanager/src/main/java/secretmanager/regionalsamples/DeleteRegionalSecretAnnotations.java @@ -25,11 +25,10 @@ import com.google.protobuf.util.FieldMaskUtil; import java.io.IOException; import java.util.HashMap; -import java.util.Map; public class DeleteRegionalSecretAnnotations { - public static void main() throws IOException { + public static void main(String[] args) throws IOException { // TODO(developer): Replace these variables before running the sample. // This is the id of the GCP project From 710bb85be44637d01d776403c2ae197b9cd314f0 Mon Sep 17 00:00:00 2001 From: Dhaval Bhensdadiya Date: Thu, 22 Jan 2026 15:36:43 +0530 Subject: [PATCH 5/5] Moved KMS key validation check to BeforeClass setup --- secretmanager/src/test/java/secretmanager/SnippetsIT.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/secretmanager/src/test/java/secretmanager/SnippetsIT.java b/secretmanager/src/test/java/secretmanager/SnippetsIT.java index e2c6a362a45..fd219a3607a 100644 --- a/secretmanager/src/test/java/secretmanager/SnippetsIT.java +++ b/secretmanager/src/test/java/secretmanager/SnippetsIT.java @@ -118,6 +118,7 @@ public class SnippetsIT { @BeforeClass public static void beforeAll() throws Exception { Assert.assertFalse("missing GOOGLE_CLOUD_PROJECT", Strings.isNullOrEmpty(PROJECT_ID)); + Assert.assertFalse("missing GOOGLE_CLOUD_KMS_KEY", Strings.isNullOrEmpty(KMS_KEY_NAME)); TEST_SECRET = createSecret(true); TEST_SECRET_TO_DELETE = createSecret(false); @@ -160,8 +161,6 @@ public void afterEach() { @AfterClass public static void afterAll() throws Exception { - Assert.assertFalse("missing GOOGLE_CLOUD_PROJECT", Strings.isNullOrEmpty(PROJECT_ID)); - Assert.assertFalse("missing GOOGLE_CLOUD_KMS_KEY", Strings.isNullOrEmpty(KMS_KEY_NAME)); deleteSecret(TEST_SECRET.getName()); deleteSecret(TEST_SECRET_TO_CREATE_NAME.toString());