Skip to content

Commit d744090

Browse files
feat(secretmanager): add examples for creating, updating and deleting secret rotation policies and topics
1 parent 15b8d11 commit d744090

File tree

11 files changed

+817
-2
lines changed

11 files changed

+817
-2
lines changed

secretmanager/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,28 @@ the Secret Manager API using the Google Java API Client Libraries.
1212

1313
### Enable the API
1414

15-
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
15+
You must enable the [Secret Manager API](https://console.cloud.google.com/flows/enableapi?apiid=secretmanager.googleapis.com), [Cloud KMS API](https://console.cloud.google.com/flows/enableapi?apiid=cloudkms.googleapis.com) and [Pub/Sub API](https://console.cloud.google.com/flows/enableapi?apiid=pubsub.googleapis.com) for your project in order to use these samples
1616

1717
### Set Environment Variables
1818

19-
You must set your project ID, KMS Keys (Global and Regional) in order to run the tests
19+
You must set your project ID, KMS Keys (Global and Regional), and Pub/Sub Topic in order to run the tests
2020

2121
```text
2222
$ export GOOGLE_CLOUD_PROJECT=<your-project-id-here>
2323
$ export GOOGLE_CLOUD_REGIONAL_KMS_KEY=<full-name-of-regional-kms-key> (region same as location)
2424
$ export GOOGLE_CLOUD_KMS_KEY=<full-name-of-global-kms-key>
25+
$ export GOOGLE_CLOUD_PUBSUB_TOPIC=<full-name-of-pubsub-topic>
2526
```
2627

28+
The Pub/Sub topic should be in the format `projects/PROJECT_ID/topics/TOPIC_ID` and is used for testing secret notifications.
29+
2730
### Grant Permissions
2831

2932
You must ensure that the [user account or service account](https://cloud.google.com/iam/docs/service-accounts#differences_between_a_service_account_and_a_user_account) you used to authorize your gcloud session has the proper permissions to edit Secret Manager resources for your project. In the Cloud Console under IAM, add the following roles to the project whose service account you're using to test:
3033

3134
* Secret Manager Admin (`roles/secretmanager.admin`)
3235
* Secret Manager Secret Accessor (`roles/secretmanager.secretAccessor`)
3336
* Cloud KMS Encrypter / Decrypter (`roles/cloudkms.cryptoKeyEncrypterDecrypter`) on the regional and global KMS key used for testing
37+
* Pub/Sub Publisher (`roles/pubsub.publisher`) on the Pub/Sub topic used for testing
3438

3539
More information can be found in the [Secret Manager Docs](https://cloud.google.com/secret-manager/docs/access-control)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package secretmanager;
18+
19+
// [START secretmanager_create_secret_with_rotation]
20+
import com.google.cloud.secretmanager.v1.ProjectName;
21+
import com.google.cloud.secretmanager.v1.Replication;
22+
import com.google.cloud.secretmanager.v1.Rotation;
23+
import com.google.cloud.secretmanager.v1.Secret;
24+
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
25+
import com.google.cloud.secretmanager.v1.Topic;
26+
import com.google.protobuf.Duration;
27+
import com.google.protobuf.Timestamp;
28+
import java.io.IOException;
29+
import java.time.Instant;
30+
31+
public class CreateSecretWithRotation {
32+
33+
public static void main(String[] args) throws IOException {
34+
// TODO(developer): Replace these variables before running the sample.
35+
36+
// This is the id of the GCP project
37+
String projectId = "your-project-id";
38+
// This is the id of the secret to create
39+
String secretId = "your-secret-id";
40+
// This is the rotation period in seconds (e.g., 2592000 for 30 days)
41+
long rotationPeriodSeconds = 2592000;
42+
// This is the topic name in the format projects/PROJECT_ID/topics/TOPIC_ID
43+
String topicName = "projects/your-project-id/topics/your-topic-id";
44+
createSecretWithRotation(projectId, secretId, rotationPeriodSeconds, topicName);
45+
}
46+
47+
// Create a new secret with automatic rotation.
48+
public static Secret createSecretWithRotation(
49+
String projectId, String secretId, long rotationPeriodSeconds, String topicName)
50+
throws IOException {
51+
// Initialize client that will be used to send requests. This client only needs to be created
52+
// once, and can be reused for multiple requests. After completing all of your requests, call
53+
// the "close" method on the client to safely clean up any remaining background resources.
54+
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
55+
// Build the parent name from the project.
56+
ProjectName projectName = ProjectName.of(projectId);
57+
58+
// Calculate the next rotation time.
59+
Instant nextRotationTime = Instant.now().plusSeconds(rotationPeriodSeconds);
60+
Timestamp nextRotationTimestamp = Timestamp.newBuilder()
61+
.setSeconds(nextRotationTime.getEpochSecond())
62+
.setNanos(nextRotationTime.getNano())
63+
.build();
64+
65+
// Build the rotation policy.
66+
Rotation rotation = Rotation.newBuilder()
67+
.setNextRotationTime(nextRotationTimestamp)
68+
.setRotationPeriod(Duration.newBuilder().setSeconds(rotationPeriodSeconds).build())
69+
.build();
70+
71+
// Build the topic for rotation notifications.
72+
Topic topic = Topic.newBuilder()
73+
.setName(topicName)
74+
.build();
75+
76+
// Build the secret to create with rotation and topic.
77+
Secret secret =
78+
Secret.newBuilder()
79+
.setReplication(
80+
Replication.newBuilder()
81+
.setAutomatic(Replication.Automatic.newBuilder().build())
82+
.build())
83+
.setRotation(rotation)
84+
.addTopics(topic)
85+
.build();
86+
87+
// Create the secret.
88+
Secret createdSecret = client.createSecret(projectName, secretId, secret);
89+
System.out.printf("Created secret %s with rotation\n", createdSecret.getName());
90+
91+
return createdSecret;
92+
}
93+
}
94+
}
95+
// [END secretmanager_create_secret_with_rotation]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package secretmanager;
18+
19+
// [START secretmanager_create_secret_with_topic]
20+
import com.google.cloud.secretmanager.v1.ProjectName;
21+
import com.google.cloud.secretmanager.v1.Replication;
22+
import com.google.cloud.secretmanager.v1.Secret;
23+
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
24+
import com.google.cloud.secretmanager.v1.Topic;
25+
import java.io.IOException;
26+
27+
public class CreateSecretWithTopic {
28+
29+
public static void main(String[] args) throws IOException {
30+
// TODO(developer): Replace these variables before running the sample.
31+
32+
// This is the id of the GCP project
33+
String projectId = "your-project-id";
34+
// This is the id of the secret to create
35+
String secretId = "your-secret-id";
36+
// This is the topic name in the format projects/PROJECT_ID/topics/TOPIC_ID
37+
String topicName = "projects/your-project-id/topics/your-topic-id";
38+
createSecretWithTopic(projectId, secretId, topicName);
39+
}
40+
41+
// Create a new secret with a Pub/Sub topic for notifications.
42+
public static Secret createSecretWithTopic(
43+
String projectId, String secretId, String topicName) throws IOException {
44+
// Initialize client that will be used to send requests. This client only needs to be created
45+
// once, and can be reused for multiple requests. After completing all of your requests, call
46+
// the "close" method on the client to safely clean up any remaining background resources.
47+
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
48+
// Build the parent name from the project.
49+
ProjectName projectName = ProjectName.of(projectId);
50+
51+
// Build the topic.
52+
Topic topic = Topic.newBuilder()
53+
.setName(topicName)
54+
.build();
55+
56+
// Build the secret to create with topic.
57+
Secret secret =
58+
Secret.newBuilder()
59+
.setReplication(
60+
Replication.newBuilder()
61+
.setAutomatic(Replication.Automatic.newBuilder().build())
62+
.build())
63+
.addTopics(topic)
64+
.build();
65+
66+
// Create the secret.
67+
Secret createdSecret = client.createSecret(projectName, secretId, secret);
68+
System.out.printf("Created secret %s with topic\n", createdSecret.getName());
69+
70+
return createdSecret;
71+
}
72+
}
73+
}
74+
// [END secretmanager_create_secret_with_topic]
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package secretmanager;
18+
19+
// [START secretmanager_delete_secret_rotation]
20+
import com.google.cloud.secretmanager.v1.Secret;
21+
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
22+
import com.google.cloud.secretmanager.v1.SecretName;
23+
import com.google.protobuf.FieldMask;
24+
import com.google.protobuf.util.FieldMaskUtil;
25+
import java.io.IOException;
26+
27+
public class DeleteSecretRotation {
28+
29+
public static void main(String[] args) throws IOException {
30+
// TODO(developer): Replace these variables before running the sample.
31+
32+
// This is the id of the GCP project
33+
String projectId = "your-project-id";
34+
// This is the id of the secret to update
35+
String secretId = "your-secret-id";
36+
deleteSecretRotation(projectId, secretId);
37+
}
38+
39+
// Delete the rotation policy from an existing secret.
40+
public static Secret deleteSecretRotation(String projectId, String secretId)
41+
throws IOException {
42+
// Initialize client that will be used to send requests. This client only needs to be created
43+
// once, and can be reused for multiple requests. After completing all of your requests, call
44+
// the "close" method on the client to safely clean up any remaining background resources.
45+
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
46+
// Build the secret name.
47+
SecretName secretName = SecretName.of(projectId, secretId);
48+
49+
// Build the updated secret without rotation.
50+
Secret secret =
51+
Secret.newBuilder()
52+
.setName(secretName.toString())
53+
.build();
54+
55+
// Build the field mask to clear the rotation.
56+
FieldMask fieldMask = FieldMaskUtil.fromString("rotation");
57+
58+
// Update the secret to remove rotation.
59+
Secret updatedSecret = client.updateSecret(secret, fieldMask);
60+
System.out.printf("Deleted rotation from secret %s\n", updatedSecret.getName());
61+
62+
return updatedSecret;
63+
}
64+
}
65+
}
66+
// [END secretmanager_delete_secret_rotation]
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package secretmanager;
18+
19+
// [START secretmanager_update_secret_rotation]
20+
import com.google.cloud.secretmanager.v1.Rotation;
21+
import com.google.cloud.secretmanager.v1.Secret;
22+
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
23+
import com.google.cloud.secretmanager.v1.SecretName;
24+
import com.google.cloud.secretmanager.v1.Topic;
25+
import com.google.protobuf.Duration;
26+
import com.google.protobuf.FieldMask;
27+
import com.google.protobuf.Timestamp;
28+
import com.google.protobuf.util.FieldMaskUtil;
29+
import java.io.IOException;
30+
import java.time.Instant;
31+
32+
public class UpdateSecretRotation {
33+
34+
public static void main(String[] args) throws IOException {
35+
// TODO(developer): Replace these variables before running the sample.
36+
37+
// This is the id of the GCP project
38+
String projectId = "your-project-id";
39+
// This is the id of the secret to update
40+
String secretId = "your-secret-id";
41+
// This is the rotation period in seconds (e.g., 2592000 for 30 days)
42+
long rotationPeriodSeconds = 2592000;
43+
// This is the topic name in the format projects/PROJECT_ID/topics/TOPIC_ID
44+
String topicName = "projects/your-project-id/topics/your-topic-id";
45+
updateSecretRotation(projectId, secretId, rotationPeriodSeconds, topicName);
46+
}
47+
48+
// Update an existing secret with a new rotation policy.
49+
public static Secret updateSecretRotation(
50+
String projectId, String secretId, long rotationPeriodSeconds, String topicName)
51+
throws IOException {
52+
// Initialize client that will be used to send requests. This client only needs to be created
53+
// once, and can be reused for multiple requests. After completing all of your requests, call
54+
// the "close" method on the client to safely clean up any remaining background resources.
55+
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
56+
// Build the secret name.
57+
SecretName secretName = SecretName.of(projectId, secretId);
58+
59+
// Calculate the next rotation time.
60+
Instant nextRotationTime = Instant.now().plusSeconds(rotationPeriodSeconds);
61+
Timestamp nextRotationTimestamp = Timestamp.newBuilder()
62+
.setSeconds(nextRotationTime.getEpochSecond())
63+
.setNanos(nextRotationTime.getNano())
64+
.build();
65+
66+
// Build the rotation policy.
67+
Rotation rotation = Rotation.newBuilder()
68+
.setNextRotationTime(nextRotationTimestamp)
69+
.setRotationPeriod(Duration.newBuilder().setSeconds(rotationPeriodSeconds).build())
70+
.build();
71+
72+
// Build the topic for rotation notifications.
73+
Topic topic = Topic.newBuilder()
74+
.setName(topicName)
75+
.build();
76+
77+
// Build the updated secret with new rotation policy and topic.
78+
Secret secret =
79+
Secret.newBuilder()
80+
.setName(secretName.toString())
81+
.setRotation(rotation)
82+
.addTopics(topic)
83+
.build();
84+
85+
// Build the field mask to update rotation and topics.
86+
FieldMask fieldMask = FieldMaskUtil.fromString("rotation,topics");
87+
88+
// Update the secret.
89+
Secret updatedSecret = client.updateSecret(secret, fieldMask);
90+
System.out.printf("Updated secret %s with new rotation policy\n", updatedSecret.getName());
91+
92+
return updatedSecret;
93+
}
94+
}
95+
}
96+
// [END secretmanager_update_secret_rotation]

0 commit comments

Comments
 (0)