From fc645e542596b58c68b1663bed726eeb7aab7bff Mon Sep 17 00:00:00 2001 From: Google APIs Date: Mon, 13 Jul 2026 02:20:50 -0700 Subject: [PATCH] feat(secretmanager): add support for Managed Rotation This change introduces new RPCs and types to support the Managed Rotation feature for secrets: - New RPCs: - `EnableManagedRotation`: Enables managed rotation on a secret. - `RotateSecret`: Triggers an immediate rotation for a secret with managed rotation enabled. - New Types: - `SecretType` enum: Allows specifying the type of secret, including `CLOUD_SQL_DB_CREDENTIALS`. - New Fields: - Added `policy_member` to the `Secret` resource, which defines the policy member for the secret. - Added `managed_rotation_status` to the `Rotation` message, to surface the current state and any errors for managed rotation. PiperOrigin-RevId: 946895132 --- google/cloud/secretmanager/v1/BUILD.bazel | 3 + google/cloud/secretmanager/v1/resources.proto | 76 +++++++++++++++- google/cloud/secretmanager/v1/service.proto | 87 ++++++++++++++++++- 3 files changed, 164 insertions(+), 2 deletions(-) diff --git a/google/cloud/secretmanager/v1/BUILD.bazel b/google/cloud/secretmanager/v1/BUILD.bazel index 0a14fcdc81..2dd91e59b8 100644 --- a/google/cloud/secretmanager/v1/BUILD.bazel +++ b/google/cloud/secretmanager/v1/BUILD.bazel @@ -31,6 +31,8 @@ proto_library( "//google/api:resource_proto", "//google/iam/v1:iam_policy_proto", "//google/iam/v1:policy_proto", + "//google/iam/v1:resource_policy_member_proto", + "//google/rpc:status_proto", "@com_google_protobuf//:duration_proto", "@com_google_protobuf//:empty_proto", "@com_google_protobuf//:field_mask_proto", @@ -128,6 +130,7 @@ go_grpc_library( deps = [ "//google/api:annotations_go_proto", "//google/iam/v1:iam_go_proto", + "//google/rpc:status_go_proto", ], ) diff --git a/google/cloud/secretmanager/v1/resources.proto b/google/cloud/secretmanager/v1/resources.proto index d548a70780..2b8ee38e43 100644 --- a/google/cloud/secretmanager/v1/resources.proto +++ b/google/cloud/secretmanager/v1/resources.proto @@ -1,4 +1,4 @@ -// Copyright 2025 Google LLC +// 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. @@ -18,8 +18,10 @@ package google.cloud.secretmanager.v1; import "google/api/field_behavior.proto"; import "google/api/resource.proto"; +import "google/iam/v1/resource_policy_member.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; +import "google/rpc/status.proto"; option csharp_namespace = "Google.Cloud.SecretManager.V1"; option go_package = "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb;secretmanagerpb"; @@ -45,6 +47,30 @@ message Secret { singular: "secret" }; + // This defines the various values of the type of secret can be. + enum SecretType { + // Applicable to all secrets which do not have any restriction on the + // SecretVersions. + SECRET_TYPE_UNSPECIFIED = 0; + + // Applicable to secrets which are used for the managed rotation feature + // for Cloud SQL Single User. + CLOUD_SQL_DB_CREDENTIALS = 1; + + // Applicable to secrets where the payload contains an access key. + ACCESS_KEY = 2; + + // Applicable to secrets where the payload contains a certificate. + CERTIFICATE = 3; + + // Applicable to secrets where the payload contains database credentials. + OTHER_DB_CREDENTIALS = 4; + + // Applicable to secrets whose type doesn't belong to any of the above + // defined types. + OTHER = 50; + } + // Output only. The resource name of the // [Secret][google.cloud.secretmanager.v1.Secret] in the format // `projects/*/secrets/*`. @@ -175,6 +201,21 @@ message Secret { (google.api.field_behavior) = IMMUTABLE, (google.api.field_behavior) = OPTIONAL ]; + + // Optional. Immutable. This defines the type of the secret. + // Enforces certain structural requirements on the + // [SecretVersions][google.cloud.secretmanager.v1.SecretVersion]. + // For secret of type UNSPECIFIED, the SecretVersions can be of any type. + SecretType secret_type = 17 [ + (google.api.field_behavior) = IMMUTABLE, + (google.api.field_behavior) = OPTIONAL + ]; + + // Output only. Defines the policy member for the secret. + // This will be used to check if the caller has the permission to perform + // certain operations on the typed secret. + google.iam.v1.ResourcePolicyMember policy_member = 18 + [(google.api.field_behavior) = OUTPUT_ONLY]; } // A secret version resource in the Secret Manager API. @@ -449,6 +490,33 @@ message Topic { // Secret. [Secret.topics][google.cloud.secretmanager.v1.Secret.topics] must be // set to configure rotation. message Rotation { + // Represents the status of a managed rotation. + // + // This is applicable only to Typed Secrets. It indicates whether the + // rotation is active and any errors that may have occurred during the + // asynchronous managed rotation. + message ManagedRotationStatus { + // This defines the various states in which the managed rotation can be. + enum State { + // Not specified. This value is unused and invalid. + STATE_UNSPECIFIED = 0; + + // Indicates that the Managed rotation is ACTIVE. + ACTIVE = 1; + + // Indicates that the Managed rotation is INACTIVE. + INACTIVE = 2; + } + + // Output only. Indicates whether the Managed Rotation is active or not. + State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; + + // Output only. Displays customer-facing issues that occurred during an + // asynchronous managed rotation. For example, if there are some permission + // errors. + google.rpc.Status error = 2 [(google.api.field_behavior) = OUTPUT_ONLY]; + } + // Optional. Timestamp in UTC at which the // [Secret][google.cloud.secretmanager.v1.Secret] is scheduled to rotate. // Cannot be set to less than 300s (5 min) in the future and at most @@ -474,6 +542,12 @@ message Rotation { // rotation notifications. google.protobuf.Duration rotation_period = 2 [(google.api.field_behavior) = INPUT_ONLY]; + + // Output only. The current status of the managed rotation. + // This field is only applicable to Typed Secrets. + // This field is set by the service and cannot be set by the user. + ManagedRotationStatus managed_rotation_status = 3 + [(google.api.field_behavior) = OUTPUT_ONLY]; } // A secret payload resource in the Secret Manager API. This contains the diff --git a/google/cloud/secretmanager/v1/service.proto b/google/cloud/secretmanager/v1/service.proto index 7b70ab9dad..54966fe9fa 100644 --- a/google/cloud/secretmanager/v1/service.proto +++ b/google/cloud/secretmanager/v1/service.proto @@ -1,4 +1,4 @@ -// Copyright 2025 Google LLC +// 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. @@ -266,6 +266,40 @@ service SecretManagerService { } }; } + + // Enables the managed rotation feature for a + // [Secret][google.cloud.secretmanager.v1.Secret]. This method can only be + // triggered once for a secret. In order to do further rotations, RotateSecret + // should be used. This method will add a secret version and update the + // password in Cloud SQL. + rpc EnableManagedRotation(EnableManagedRotationRequest) + returns (SecretVersion) { + option (google.api.http) = { + post: "/v1/{parent=projects/*/secrets/*}:enableManagedRotation" + body: "*" + additional_bindings { + post: "/v1/{parent=projects/*/locations/*/secrets/*}:enableManagedRotation" + body: "*" + } + }; + option (google.api.method_signature) = + "parent,cloud_sql_single_user_credentials"; + } + + // Do a managed rotation for a [Secret][google.cloud.secretmanager.v1.Secret]. + // This can only be triggered after Managed rotation has been enabled. + // This method will add a secret version and update the password in Cloud SQL. + rpc RotateSecret(RotateSecretRequest) returns (SecretVersion) { + option (google.api.http) = { + post: "/v1/{parent=projects/*/secrets/*}:rotateSecret" + body: "*" + additional_bindings { + post: "/v1/{parent=projects/*/locations/*/secrets/*}:rotateSecret" + body: "*" + } + }; + option (google.api.method_signature) = "parent"; + } } // Request message for @@ -361,6 +395,57 @@ message AddSecretVersionRequest { SecretPayload payload = 2 [(google.api.field_behavior) = REQUIRED]; } +// Request message for +// [SecretManagerService.EnableManagedRotation][google.cloud.secretmanager.v1.SecretManagerService.EnableManagedRotation]. +message EnableManagedRotationRequest { + // These are the credentials required for Cloud SQL DB for Single user + // Managed Rotation. + message CloudSQLSingleUserCredentials { + // Required. Instance ID of the Cloud SQL instance. + string instance_id = 1 [(google.api.field_behavior) = REQUIRED]; + + // Required. Username of the Cloud SQL instance. + string username = 2 [(google.api.field_behavior) = REQUIRED]; + + // Optional. Password of the Cloud SQL instance. If this is not provided, + // a random password will be generated. + string password = 3 [(google.api.field_behavior) = OPTIONAL]; + } + + // Required. The resource name of the + // [Secret][google.cloud.secretmanager.v1.Secret] to associate with the + // [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] in the format + // `projects/*/secrets/*` or `projects/*/locations/*/secrets/*`. + string parent = 1 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "secretmanager.googleapis.com/Secret" + } + ]; + + // The credentials required for Managed Rotation. + // Right now, only Cloud SQL Single User credentials are supported. + oneof credentials { + // Credentials required for Cloud SQL DB for Single user Managed Rotation. + CloudSQLSingleUserCredentials cloud_sql_single_user_credentials = 2; + } +} + +// Request message for +// [SecretManagerService.RotateSecret][google.cloud.secretmanager.v1.SecretManagerService.RotateSecret]. +message RotateSecretRequest { + // Required. The resource name of the + // [Secret][google.cloud.secretmanager.v1.Secret] to associate with the + // [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] in the format + // `projects/*/secrets/*` or `projects/*/locations/*/secrets/*`. + string parent = 1 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "secretmanager.googleapis.com/Secret" + } + ]; +} + // Request message for // [SecretManagerService.GetSecret][google.cloud.secretmanager.v1.SecretManagerService.GetSecret]. message GetSecretRequest {