From 56729a12395020cc9c312995218b8cfd3e91537c Mon Sep 17 00:00:00 2001 From: Vatsal Vora Date: Wed, 2 Apr 2025 14:19:45 +0530 Subject: [PATCH 1/3] feat(parametermanager): add global parameter manager kms_key samples --- parametermanager/create_param_with_kms_key.go | 68 +++++ parametermanager/go.mod | 61 +++++ parametermanager/go.sum | 127 ++++++++++ parametermanager/parametermanager_test.go | 236 ++++++++++++++++++ parametermanager/remove_param_kms_key.go | 68 +++++ parametermanager/update_param_kms_key.go | 71 ++++++ 6 files changed, 631 insertions(+) create mode 100644 parametermanager/create_param_with_kms_key.go create mode 100644 parametermanager/go.mod create mode 100644 parametermanager/go.sum create mode 100644 parametermanager/parametermanager_test.go create mode 100644 parametermanager/remove_param_kms_key.go create mode 100644 parametermanager/update_param_kms_key.go diff --git a/parametermanager/create_param_with_kms_key.go b/parametermanager/create_param_with_kms_key.go new file mode 100644 index 0000000000..348096b141 --- /dev/null +++ b/parametermanager/create_param_with_kms_key.go @@ -0,0 +1,68 @@ +// 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 parametermanager + +// [START parametermanager_create_param_with_kms_key] +import ( + "context" + "fmt" + "io" + + parametermanager "cloud.google.com/go/parametermanager/apiv1" + parametermanagerpb "cloud.google.com/go/parametermanager/apiv1/parametermanagerpb" +) + +// createParamWithKmsKey creates a 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. +// 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/global/keyRings/my-key-ring/cryptoKeys/my-encryption-key") +// +// The function returns an error if the parameter creation fails. +func createParamWithKmsKey(w io.Writer, projectID, parameterID, kmsKey string) error { + // Create a context and a Parameter Manager client. + ctx := context.Background() + + // Create a Parameter Manager client. + client, err := parametermanager.NewClient(ctx) + 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/global", projectID) + + // 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 parameter %s with kms_key %s\n", parameter.Name, *parameter.KmsKey) + return nil +} + +// [END parametermanager_create_param_with_kms_key] diff --git a/parametermanager/go.mod b/parametermanager/go.mod new file mode 100644 index 0000000000..7d3b201765 --- /dev/null +++ b/parametermanager/go.mod @@ -0,0 +1,61 @@ +module github.com/GoogleCloudPlatform/golang-samples/parametermanager + +go 1.23.0 + +toolchain go1.23.4 + +require ( + cloud.google.com/go/kms v1.21.0 + cloud.google.com/go/parametermanager v0.2.0 + github.com/GoogleCloudPlatform/golang-samples v0.0.0-20250324181350-edee6f1df110 + github.com/gofrs/uuid v4.4.0+incompatible + google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb + google.golang.org/grpc v1.71.0 +) + +require ( + cel.dev/expr v0.19.1 // indirect + cloud.google.com/go v0.118.3 // indirect + cloud.google.com/go/auth v0.15.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/iam v1.4.2 // indirect + cloud.google.com/go/longrunning v0.6.5 // indirect + cloud.google.com/go/monitoring v1.24.0 // indirect + cloud.google.com/go/storage v1.50.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect + github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/oauth2 v0.28.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + golang.org/x/time v0.11.0 // indirect + google.golang.org/api v0.228.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect + google.golang.org/protobuf v1.36.6 // indirect +) diff --git a/parametermanager/go.sum b/parametermanager/go.sum new file mode 100644 index 0000000000..d2c4ab1ecf --- /dev/null +++ b/parametermanager/go.sum @@ -0,0 +1,127 @@ +cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= +cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cloud.google.com/go v0.118.3 h1:jsypSnrE/w4mJysioGdMBg4MiW/hHx/sArFpaBWHdME= +cloud.google.com/go v0.118.3/go.mod h1:Lhs3YLnBlwJ4KA6nuObNMZ/fCbOQBPuWKPoE0Wa/9Vc= +cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= +cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/iam v1.4.2 h1:4AckGYAYsowXeHzsn/LCKWIwSWLkdb0eGjH8wWkd27Q= +cloud.google.com/go/iam v1.4.2/go.mod h1:REGlrt8vSlh4dfCJfSEcNjLGq75wW75c5aU3FLOYq34= +cloud.google.com/go/kms v1.21.0 h1:x3EeWKuYwdlo2HLse/876ZrKjk2L5r7Uexfm8+p6mSI= +cloud.google.com/go/kms v1.21.0/go.mod h1:zoFXMhVVK7lQ3JC9xmhHMoQhnjEDZFoLAr5YMwzBLtk= +cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc= +cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA= +cloud.google.com/go/longrunning v0.6.5 h1:sD+t8DO8j4HKW4QfouCklg7ZC1qC4uzVZt8iz3uTW+Q= +cloud.google.com/go/longrunning v0.6.5/go.mod h1:Et04XK+0TTLKa5IPYryKf5DkpwImy6TluQ1QTLwlKmY= +cloud.google.com/go/monitoring v1.24.0 h1:csSKiCJ+WVRgNkRzzz3BPoGjFhjPY23ZTcaenToJxMM= +cloud.google.com/go/monitoring v1.24.0/go.mod h1:Bd1PRK5bmQBQNnuGwHBfUamAV1ys9049oEPHnn4pcsc= +cloud.google.com/go/parametermanager v0.2.0 h1:LnaRjsMe2bC459qQyEOJUCweF9XNYTdfuRFDnuYjsOA= +cloud.google.com/go/parametermanager v0.2.0/go.mod h1:yCpFUWcz5C5iIv5QxWg0vmjfT9lmtu+PCB4CLu0/DW8= +cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6QJs= +cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY= +cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE= +cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= +github.com/GoogleCloudPlatform/golang-samples v0.0.0-20250324181350-edee6f1df110 h1:5Lvl0BdE5CsSnWTTfBWMctDWwooU+TqOUDHqvb1GTbY= +github.com/GoogleCloudPlatform/golang-samples v0.0.0-20250324181350-edee6f1df110/go.mod h1:pro/7J5Dd9+sI+NAZUopa1sW4YuthozUkor+3MF6fIU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 h1:o90wcURuxekmXrtxmYWTyNla0+ZEHhud6DI1ZTxd1vI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0/go.mod h1:6fTWu4m3jocfUZLYF5KsZC1TUfRvEjs7lM4crme/irw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0 h1:jJKWl98inONJAr/IZrdFQUWcwUO95DLY1XMD1ZIut+g= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0/go.mod h1:l2fIqmwB+FKSfvn3bAD/0i+AXAxhIZjTK2svT/mgUXs= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= +github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= +github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= +github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//snGVIM3Tx6QRzlQBao= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs= +google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4= +google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= +google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE= +google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY= +google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/parametermanager/parametermanager_test.go b/parametermanager/parametermanager_test.go new file mode 100644 index 0000000000..bb03a80564 --- /dev/null +++ b/parametermanager/parametermanager_test.go @@ -0,0 +1,236 @@ +// 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 parametermanager + +import ( + "bytes" + "context" + "fmt" + "strings" + "testing" + + 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" + "github.com/GoogleCloudPlatform/golang-samples/internal/testutil" + "github.com/gofrs/uuid" + grpccodes "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" +) + +func testName(t *testing.T) string { + u, err := uuid.NewV4() + if err != nil { + t.Fatalf("testName: failed to generate uuid: %v", err) + } + return u.String() +} + +func testParameterWithKmsKey(t *testing.T, projectID, kms_key string) (*parametermanagerpb.Parameter, string) { + parameterID := testName(t) + ctx := context.Background() + client, err := parametermanager.NewClient(ctx) + if err != nil { + t.Fatalf("failed to create client: %v", err) + } + defer client.Close() + + parent := fmt.Sprintf("projects/%s/locations/global", projectID) + 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 +} + +func testCleanupParameter(t *testing.T, name string) { + ctx := context.Background() + + client, err := parametermanager.NewClient(ctx) + if err != nil { + t.Fatalf("failed to create client: %v", err) + } + defer client.Close() + + if err := client.DeleteParameter(ctx, ¶metermanagerpb.DeleteParameterRequest{ + Name: name, + }); err != nil { + if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + t.Fatalf("testCleanupParameter: failed to delete parameter: %v", err) + } + } +} + +func testCleanupKeyVersions(t *testing.T, name string) { + 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) + } + } +} + +func testCreateKeyRing(t *testing.T, projectID, keyRingId string) { + ctx := context.Background() + + 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/global", projectID) + + // 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) + } + } +} + +func testCreateKeyHSM(t *testing.T, projectID, keyRing, id string) { + ctx := context.Background() + 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/global/keyRings/%s", projectID, 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) + } + } +} + +func TestCreateParamWithKmsKey(t *testing.T) { + tc := testutil.SystemTest(t) + + parameterID := testName(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/global/keyRings/go-test-key-ring/cryptoKeys/%s", tc.ProjectID, keyId) + + defer testCleanupParameter(t, fmt.Sprintf("projects/%s/locations/global/parameters/%s", tc.ProjectID, parameterID)) + defer testCleanupKeyVersions(t, fmt.Sprintf("%s/cryptoKeyVersions/1", kms_key)) + + var b bytes.Buffer + if err := createParamWithKmsKey(&b, tc.ProjectID, parameterID, kms_key); err != nil { + t.Fatalf("Failed to create parameter: %v", err) + } + if got, want := b.String(), fmt.Sprintf("Created parameter %s with kms_key %s\n", fmt.Sprintf("projects/%s/locations/global/parameters/%s", tc.ProjectID, parameterID), kms_key); !strings.Contains(got, want) { + t.Errorf("createParameter: expected %q to contain %q", got, want) + } +} + +func TestUpdateParamKmsKey(t *testing.T) { + tc := testutil.SystemTest(t) + + testCreateKeyRing(t, tc.ProjectID, "go-test-key-ring") + + keyId := testName(t) + testCreateKeyHSM(t, tc.ProjectID, "go-test-key-ring", keyId) + kms_key := fmt.Sprintf("projects/%s/locations/global/keyRings/go-test-key-ring/cryptoKeys/%s", tc.ProjectID, 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 b bytes.Buffer + if err := updateParamKmsKey(&b, tc.ProjectID, parameterID, kms_key); err != nil { + t.Fatalf("Failed to update parameter: %v", err) + } + if got, want := b.String(), fmt.Sprintf("Updated parameter %s with kms_key %s\n", fmt.Sprintf("projects/%s/locations/global/parameters/%s", tc.ProjectID, parameterID), kms_key); !strings.Contains(got, want) { + t.Errorf("createParameter: expected %q to contain %q", got, want) + } +} + +func TestRemoveParamKmsKey(t *testing.T) { + tc := testutil.SystemTest(t) + + testCreateKeyRing(t, tc.ProjectID, "go-test-key-ring") + keyId := testName(t) + testCreateKeyHSM(t, tc.ProjectID, "go-test-key-ring", keyId) + kms_key := fmt.Sprintf("projects/%s/locations/global/keyRings/go-test-key-ring/cryptoKeys/%s", tc.ProjectID, 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 b bytes.Buffer + if err := removeParamKmsKey(&b, tc.ProjectID, parameterID); err != nil { + t.Fatalf("Failed to create parameter: %v", err) + } + if got, want := b.String(), fmt.Sprintf("Removed kms_key for parameter %s\n", fmt.Sprintf("projects/%s/locations/global/parameters/%s", tc.ProjectID, parameterID)); !strings.Contains(got, want) { + t.Errorf("createParameter: expected %q to contain %q", got, want) + } +} diff --git a/parametermanager/remove_param_kms_key.go b/parametermanager/remove_param_kms_key.go new file mode 100644 index 0000000000..c020f20859 --- /dev/null +++ b/parametermanager/remove_param_kms_key.go @@ -0,0 +1,68 @@ +// 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 parametermanager + +// [START parametermanager_remove_param_kms_key] +import ( + "context" + "fmt" + "io" + + parametermanager "cloud.google.com/go/parametermanager/apiv1" + parametermanagerpb "cloud.google.com/go/parametermanager/apiv1/parametermanagerpb" + "google.golang.org/genproto/protobuf/field_mask" +) + +// removeParamKmsKey removes a parameter 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. +// parameterID: The ID of the parameter to be updated. +// +// The function returns an error if the parameter creation fails. +func removeParamKmsKey(w io.Writer, projectID, parameterID string) error { + // Create a context and a Parameter Manager client. + ctx := context.Background() + + // Create a Parameter Manager client. + client, err := parametermanager.NewClient(ctx) + if err != nil { + return fmt.Errorf("failed to create Parameter Manager client: %w", err) + } + defer client.Close() + + // Construct the name of the create parameter. + name := fmt.Sprintf("projects/%s/locations/global/parameters/%s", projectID, parameterID) + + // Create a parameter with unformatted format. + req := ¶metermanagerpb.UpdateParameterRequest{ + Parameter: ¶metermanagerpb.Parameter{ + Name: name, + Format: parametermanagerpb.ParameterFormat_UNFORMATTED, + }, + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"kms_key"}, + }, + } + parameter, err := client.UpdateParameter(ctx, req) + if err != nil { + return fmt.Errorf("Failed to update parameter: %w", err) + } + + fmt.Fprintf(w, "Removed kms_key for parameter %s\n", parameter.Name) + return nil +} + +// [END parametermanager_remove_param_kms_key] diff --git a/parametermanager/update_param_kms_key.go b/parametermanager/update_param_kms_key.go new file mode 100644 index 0000000000..d3742eed15 --- /dev/null +++ b/parametermanager/update_param_kms_key.go @@ -0,0 +1,71 @@ +// 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 parametermanager + +// [START parametermanager_update_param_kms_key] +import ( + "context" + "fmt" + "io" + + parametermanager "cloud.google.com/go/parametermanager/apiv1" + parametermanagerpb "cloud.google.com/go/parametermanager/apiv1/parametermanagerpb" + "google.golang.org/genproto/protobuf/field_mask" +) + +// updateParamKmsKey updates a parameter 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. +// parameterID: The ID of the parameter to be updated. +// kmsKey: The ID of the KMS key to be used for encryption. +// (e.g. "projects/my-project/locations/global/keyRings/my-key-ring/cryptoKeys/my-encryption-key") +// +// The function returns an error if the parameter creation fails. +func updateParamKmsKey(w io.Writer, projectID, parameterID, kmsKey string) error { + // Create a context and a Parameter Manager client. + ctx := context.Background() + + // Create a Parameter Manager client. + client, err := parametermanager.NewClient(ctx) + if err != nil { + return fmt.Errorf("failed to create Parameter Manager client: %w", err) + } + defer client.Close() + + // Construct the name of the create parameter. + name := fmt.Sprintf("projects/%s/locations/global/parameters/%s", projectID, parameterID) + + // Create a parameter with unformatted format. + req := ¶metermanagerpb.UpdateParameterRequest{ + Parameter: ¶metermanagerpb.Parameter{ + Name: name, + Format: parametermanagerpb.ParameterFormat_UNFORMATTED, + KmsKey: &kmsKey, + }, + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"kms_key"}, + }, + } + parameter, err := client.UpdateParameter(ctx, req) + if err != nil { + return fmt.Errorf("Failed to update parameter: %w", err) + } + + fmt.Fprintf(w, "Updated parameter %s with kms_key %s\n", parameter.Name, *parameter.KmsKey) + return nil +} + +// [END parametermanager_update_param_kms_key] From aad97f6a55a5df5bdbdbecc89048562ba3ea665d Mon Sep 17 00:00:00 2001 From: Vatsal Vora Date: Wed, 2 Apr 2025 14:21:21 +0530 Subject: [PATCH 2/3] fix(parametermanager): update go.work file --- go.work | 1 + 1 file changed, 1 insertion(+) diff --git a/go.work b/go.work index 791d9a836a..da2f5af69d 100644 --- a/go.work +++ b/go.work @@ -108,6 +108,7 @@ use ( ./monitoring ./opentelemetry/instrumentation/app ./opentelemetry/trace + ./parametermanager ./privateca ./profiler ./profiler/shakesapp From 7c7ae4340a3ee8eec934e00ec85c072aa9c6534a Mon Sep 17 00:00:00 2001 From: Vatsal Vora Date: Fri, 4 Apr 2025 15:39:29 +0530 Subject: [PATCH 3/3] fix(parametermanager): add GoDoc comments to the test case functions --- parametermanager/parametermanager_test.go | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/parametermanager/parametermanager_test.go b/parametermanager/parametermanager_test.go index bb03a80564..cd4374a238 100644 --- a/parametermanager/parametermanager_test.go +++ b/parametermanager/parametermanager_test.go @@ -31,7 +31,11 @@ import ( grpcstatus "google.golang.org/grpc/status" ) +// testName generates a unique name for testing purposes by creating a new UUID. +// It returns the UUID as a string or fails the test if UUID generation fails. func testName(t *testing.T) string { + t.Helper() + u, err := uuid.NewV4() if err != nil { t.Fatalf("testName: failed to generate uuid: %v", err) @@ -39,7 +43,11 @@ func testName(t *testing.T) string { return u.String() } +// 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) ctx := context.Background() client, err := parametermanager.NewClient(ctx) @@ -64,7 +72,11 @@ func testParameterWithKmsKey(t *testing.T, projectID, kms_key string) (*paramete return parameter, parameterID } +// testCleanupParameter deletes the specified parameter in the GCP project. +// It fails the test if the parameter deletion fails. func testCleanupParameter(t *testing.T, name string) { + t.Helper() + ctx := context.Background() client, err := parametermanager.NewClient(ctx) @@ -82,7 +94,10 @@ func testCleanupParameter(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) @@ -100,7 +115,10 @@ func testCleanupKeyVersions(t *testing.T, name string) { } } +// 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() client, err := kms.NewKeyManagementClient(ctx) @@ -132,7 +150,10 @@ func testCreateKeyRing(t *testing.T, projectID, keyRingId string) { } } +// 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() client, err := kms.NewKeyManagementClient(ctx) if err != nil { @@ -170,6 +191,8 @@ func testCreateKeyHSM(t *testing.T, projectID, keyRing, id string) { } } +// TestCreateParamWithKmsKey tests the createParamWithKmsKey function by creating a parameter with a KMS key, +// and verifies if the parameter was successfully created by checking the output. func TestCreateParamWithKmsKey(t *testing.T) { tc := testutil.SystemTest(t) @@ -192,6 +215,8 @@ func TestCreateParamWithKmsKey(t *testing.T) { } } +// TestUpdateParamKmsKey tests the updateParamKmsKey function by creating a parameter with a KMS key, +// updating the KMS key, and verifying if the parameter was successfully updated by checking the output. func TestUpdateParamKmsKey(t *testing.T) { tc := testutil.SystemTest(t) @@ -214,6 +239,8 @@ func TestUpdateParamKmsKey(t *testing.T) { } } +// TestRemoveParamKmsKey tests the removeParamKmsKey function by creating a parameter with a KMS key, +// removing the KMS key, and verifying if the KMS key was successfully removed by checking the output. func TestRemoveParamKmsKey(t *testing.T) { tc := testutil.SystemTest(t)