-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat(parametermanager): Added samples for kms_key in regional parameter #5262
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
Changes from all commits
021cd8b
759160c
e2bf56a
79dbcb9
f8dfcf3
1ebd9d0
f44a7bf
ee7b02b
f5aa8ca
13df36e
ac0114c
f08613f
37c3d90
9a26195
ac868e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2025 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 | ||
// | ||
// https://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 regional_parametermanager | ||
|
||
// [START parametermanager_create_regional_param_with_kms_key] | ||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
|
||
parametermanager "cloud.google.com/go/parametermanager/apiv1" | ||
parametermanagerpb "cloud.google.com/go/parametermanager/apiv1/parametermanagerpb" | ||
"google.golang.org/api/option" | ||
) | ||
|
||
// createRegionalParamWithKmsKey creates a regional parameter with kms_key using the Parameter Manager SDK for GCP. | ||
// | ||
// w: The io.Writer object used to write the output. | ||
// projectID: The ID of the project where the parameter is located. | ||
// locationID: The ID of the location where the parameter is located. | ||
// parameterID: The ID of the parameter to be created. | ||
// kmsKey: The ID of the KMS key to be used for encryption. | ||
// (e.g. "projects/my-project/locations/us-central1/keyRings/my-key-ring/cryptoKeys/my-encryption-key") | ||
// (For more information, see: https://cloud.google.com/secret-manager/parameter-manager/docs/cmek) | ||
// | ||
// The function returns an error if the parameter creation fails. | ||
func createRegionalParamWithKmsKey(w io.Writer, projectID, locationID, parameterID, kmsKey string) error { | ||
// Create a context and a Parameter Manager client. | ||
ctx := context.Background() | ||
|
||
// Create a Parameter Manager client. | ||
endpoint := fmt.Sprintf("parametermanager.%s.rep.googleapis.com:443", locationID) | ||
client, err := parametermanager.NewClient(ctx, option.WithEndpoint(endpoint)) | ||
if err != nil { | ||
return fmt.Errorf("failed to create Parameter Manager client: %w", err) | ||
} | ||
defer client.Close() | ||
|
||
// Construct the name of the create parameter. | ||
parent := fmt.Sprintf("projects/%s/locations/%s", projectID, locationID) | ||
|
||
// Create a parameter with unformatted format. | ||
req := ¶metermanagerpb.CreateParameterRequest{ | ||
Parent: parent, | ||
ParameterId: parameterID, | ||
Parameter: ¶metermanagerpb.Parameter{ | ||
Format: parametermanagerpb.ParameterFormat_UNFORMATTED, | ||
KmsKey: &kmsKey, | ||
}, | ||
} | ||
parameter, err := client.CreateParameter(ctx, req) | ||
if err != nil { | ||
return fmt.Errorf("failed to create parameter: %w", err) | ||
} | ||
|
||
fmt.Fprintf(w, "Created regional parameter %s with kms_key %s\n", parameter.Name, *parameter.KmsKey) | ||
return nil | ||
} | ||
|
||
// [END parametermanager_create_regional_param_with_kms_key] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,8 @@ import ( | |
"testing" | ||
"time" | ||
|
||
kms "cloud.google.com/go/kms/apiv1" | ||
"cloud.google.com/go/kms/apiv1/kmspb" | ||
parametermanager "cloud.google.com/go/parametermanager/apiv1" | ||
parametermanagerpb "cloud.google.com/go/parametermanager/apiv1/parametermanagerpb" | ||
secretmanager "cloud.google.com/go/secretmanager/apiv1" | ||
|
@@ -91,6 +93,37 @@ func testParameter(t *testing.T, projectID string, format parametermanagerpb.Par | |
return parameter, parameterID | ||
} | ||
|
||
// testParameterWithKmsKey creates a parameter with a KMS key in the specified GCP project. | ||
// It returns the created parameter and its ID or fails the test if parameter creation fails. | ||
func testParameterWithKmsKey(t *testing.T, projectID, kms_key string) (*parametermanagerpb.Parameter, string) { | ||
t.Helper() | ||
parameterID := testName(t) | ||
locationId := testLocation(t) | ||
|
||
ctx := context.Background() | ||
endpoint := fmt.Sprintf("parametermanager.%s.rep.googleapis.com:443", locationId) | ||
client, err := parametermanager.NewClient(ctx, option.WithEndpoint(endpoint)) | ||
if err != nil { | ||
t.Fatalf("failed to create client: %v", err) | ||
} | ||
defer client.Close() | ||
|
||
parent := fmt.Sprintf("projects/%s/locations/%s", projectID, locationId) | ||
parameter, err := client.CreateParameter(ctx, ¶metermanagerpb.CreateParameterRequest{ | ||
Parent: parent, | ||
ParameterId: parameterID, | ||
Parameter: ¶metermanagerpb.Parameter{ | ||
Format: parametermanagerpb.ParameterFormat_UNFORMATTED, | ||
KmsKey: &kms_key, | ||
}, | ||
}) | ||
if err != nil { | ||
t.Fatalf("testParameter: failed to create parameter: %v", err) | ||
} | ||
|
||
return parameter, parameterID | ||
} | ||
|
||
// testParameterVersion creates a version of a parameter with the given payload in the specified GCP project. | ||
// It returns the created parameter version and its ID or fails the test if parameter version creation fails. | ||
func testParameterVersion(t *testing.T, projectID, parameterID, payload string) (*parametermanagerpb.ParameterVersion, string) { | ||
|
@@ -281,6 +314,105 @@ func testCleanupSecret(t *testing.T, name string) { | |
} | ||
} | ||
|
||
// testCleanupKeyVersions deletes the specified key version in the GCP project. | ||
// It fails the test if the key version deletion fails. | ||
func testCleanupKeyVersions(t *testing.T, name string) { | ||
t.Helper() | ||
ctx := context.Background() | ||
|
||
client, err := kms.NewKeyManagementClient(ctx) | ||
if err != nil { | ||
t.Fatalf("failed to create client: %v", err) | ||
} | ||
defer client.Close() | ||
|
||
if _, err := client.DestroyCryptoKeyVersion(ctx, &kmspb.DestroyCryptoKeyVersionRequest{ | ||
Name: name, | ||
}); err != nil { | ||
if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { | ||
t.Fatalf("testCleanupKeyVersion: failed to delete key version: %v", err) | ||
} | ||
} | ||
Comment on lines
+317
to
+335
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
} | ||
|
||
// testCreateKeyRing creates a key ring in the specified GCP project. | ||
// It fails the test if the key ring creation fails. | ||
func testCreateKeyRing(t *testing.T, projectID, keyRingId string) { | ||
t.Helper() | ||
ctx := context.Background() | ||
locationID := testLocation(t) | ||
|
||
client, err := kms.NewKeyManagementClient(ctx) | ||
if err != nil { | ||
t.Fatalf("failed to create client: %v", err) | ||
} | ||
defer client.Close() | ||
|
||
parent := fmt.Sprintf("projects/%s/locations/%s", projectID, locationID) | ||
|
||
// Check if key ring already exists | ||
req := &kmspb.GetKeyRingRequest{ | ||
Name: parent + "/keyRings/" + keyRingId, | ||
} | ||
_, err = client.GetKeyRing(ctx, req) | ||
if err != nil { | ||
if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { | ||
t.Fatalf("failed to get key ring: %v", err) | ||
} | ||
// Key ring not found, create it | ||
req := &kmspb.CreateKeyRingRequest{ | ||
Parent: parent, | ||
KeyRingId: keyRingId, | ||
} | ||
_, err = client.CreateKeyRing(ctx, req) | ||
if err != nil { | ||
t.Fatalf("failed to create key ring: %v", err) | ||
} | ||
} | ||
Comment on lines
+353
to
+371
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test functions |
||
} | ||
|
||
// testCreateKeyHSM creates a HSM key in the specified key ring in the GCP project. | ||
// It fails the test if the key creation fails. | ||
func testCreateKeyHSM(t *testing.T, projectID, keyRing, id string) { | ||
t.Helper() | ||
ctx := context.Background() | ||
locationID := testLocation(t) | ||
client, err := kms.NewKeyManagementClient(ctx) | ||
if err != nil { | ||
t.Fatalf("failed to create client: %v", err) | ||
} | ||
defer client.Close() | ||
|
||
parent := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", projectID, locationID, keyRing) | ||
|
||
// Check if key already exists | ||
req := &kmspb.GetCryptoKeyRequest{ | ||
Name: parent + "/cryptoKeys/" + id, | ||
} | ||
_, err = client.GetCryptoKey(ctx, req) | ||
if err != nil { | ||
if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { | ||
t.Fatalf("failed to get crypto key: %v", err) | ||
} | ||
// Key not found, create it | ||
req := &kmspb.CreateCryptoKeyRequest{ | ||
Parent: parent, | ||
CryptoKeyId: id, | ||
CryptoKey: &kmspb.CryptoKey{ | ||
Purpose: kmspb.CryptoKey_ENCRYPT_DECRYPT, | ||
VersionTemplate: &kmspb.CryptoKeyVersionTemplate{ | ||
ProtectionLevel: kmspb.ProtectionLevel_HSM, | ||
Algorithm: kmspb.CryptoKeyVersion_GOOGLE_SYMMETRIC_ENCRYPTION, | ||
}, | ||
}, | ||
} | ||
_, err = client.CreateCryptoKey(ctx, req) | ||
if err != nil { | ||
t.Fatalf("failed to create crypto key: %v", err) | ||
} | ||
} | ||
} | ||
|
||
// TestCreateRegionalParam tests the createRegionalParam function by creating a regional parameter, | ||
// then verifies if the parameter was successfully created by checking the output. | ||
func TestCreateRegionalParam(t *testing.T) { | ||
|
@@ -610,3 +742,79 @@ func TestListRegionalParamVersion(t *testing.T) { | |
t.Errorf("ListParameterVersion: expected %q to contain %q", got, want) | ||
} | ||
} | ||
|
||
// TestCreateRegionalParamWithKmsKey tests the createRegionalParamWithKmsKey function by creating a regional parameter with a KMS key, | ||
// and verifies if the parameter was successfully created by checking the output. | ||
func TestCreateRegionalParamWithKmsKey(t *testing.T) { | ||
tc := testutil.SystemTest(t) | ||
|
||
parameterID := testName(t) | ||
locationID := testLocation(t) | ||
parameterName := fmt.Sprintf("projects/%s/locations/%s/parameters/%s", tc.ProjectID, locationID, parameterID) | ||
|
||
keyId := testName(t) | ||
testCreateKeyRing(t, tc.ProjectID, "go-test-key-ring") | ||
testCreateKeyHSM(t, tc.ProjectID, "go-test-key-ring", keyId) | ||
kms_key := fmt.Sprintf("projects/%s/locations/%s/keyRings/go-test-key-ring/cryptoKeys/%s", tc.ProjectID, locationID, keyId) | ||
|
||
defer testCleanupParameter(t, parameterName) | ||
defer testCleanupKeyVersions(t, fmt.Sprintf("%s/cryptoKeyVersions/1", kms_key)) | ||
|
||
var buf bytes.Buffer | ||
if err := createRegionalParamWithKmsKey(&buf, tc.ProjectID, locationID, parameterID, kms_key); err != nil { | ||
t.Fatalf("Failed to create regional parameter: %v", err) | ||
} | ||
if got, want := buf.String(), fmt.Sprintf("Created regional parameter %s with kms_key %s", parameterName, kms_key); !strings.Contains(got, want) { | ||
t.Errorf("createParameter: expected %q to contain %q", got, want) | ||
} | ||
} | ||
|
||
// TestUpdateRegionalParamKmsKey tests the updateRegionalParamKmsKey function by creating a regional parameter with a KMS key, | ||
// updating the KMS key, and verifying if the parameter was successfully updated by checking the output. | ||
func TestUpdateRegionalParamKmsKey(t *testing.T) { | ||
tc := testutil.SystemTest(t) | ||
|
||
locationID := testLocation(t) | ||
|
||
keyId := testName(t) | ||
testCreateKeyRing(t, tc.ProjectID, "go-test-key-ring") | ||
testCreateKeyHSM(t, tc.ProjectID, "go-test-key-ring", keyId) | ||
kms_key := fmt.Sprintf("projects/%s/locations/%s/keyRings/go-test-key-ring/cryptoKeys/%s", tc.ProjectID, locationID, keyId) | ||
|
||
parameter, parameterID := testParameterWithKmsKey(t, tc.ProjectID, kms_key) | ||
defer testCleanupParameter(t, parameter.Name) | ||
defer testCleanupKeyVersions(t, fmt.Sprintf("%s/cryptoKeyVersions/1", kms_key)) | ||
|
||
var buf bytes.Buffer | ||
if err := updateRegionalParamKmsKey(&buf, tc.ProjectID, locationID, parameterID, kms_key); err != nil { | ||
t.Fatalf("Failed to update regional parameter: %v", err) | ||
} | ||
if got, want := buf.String(), fmt.Sprintf("Updated regional parameter %s with kms_key %s", parameter.Name, kms_key); !strings.Contains(got, want) { | ||
t.Errorf("createParameter: expected %q to contain %q", got, want) | ||
} | ||
} | ||
|
||
// TestRemoveRegionalParamKmsKey tests the removeRegionalParamKmsKey function by creating a regional parameter with a KMS key, | ||
// removing the KMS key, and verifying if the KMS key was successfully removed by checking the output. | ||
func TestRemoveRegionalParamKmsKey(t *testing.T) { | ||
tc := testutil.SystemTest(t) | ||
|
||
locationID := testLocation(t) | ||
|
||
keyId := testName(t) | ||
testCreateKeyRing(t, tc.ProjectID, "go-test-key-ring") | ||
testCreateKeyHSM(t, tc.ProjectID, "go-test-key-ring", keyId) | ||
kms_key := fmt.Sprintf("projects/%s/locations/%s/keyRings/go-test-key-ring/cryptoKeys/%s", tc.ProjectID, locationID, keyId) | ||
|
||
parameter, parameterID := testParameterWithKmsKey(t, tc.ProjectID, kms_key) | ||
defer testCleanupParameter(t, parameter.Name) | ||
defer testCleanupKeyVersions(t, fmt.Sprintf("%s/cryptoKeyVersions/1", kms_key)) | ||
|
||
var buf bytes.Buffer | ||
if err := removeRegionalParamKmsKey(&buf, tc.ProjectID, locationID, parameterID); err != nil { | ||
t.Fatalf("Failed to create regional parameter: %v", err) | ||
} | ||
if got, want := buf.String(), fmt.Sprintf("Removed kms_key for regional parameter %s", parameter.Name); !strings.Contains(got, want) { | ||
t.Errorf("createParameter: expected %q to contain %q", got, want) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using
go 1.22
instead ofgo 1.23
to align with the go version used in other golang-samples, unless there is a specific reason to use go 1.23.