From 50f1e4eaa40aedad9254c564487ef729af6673cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Garc=C3=ADa=20Veytia=20=28Puerco=29?= Date: Tue, 22 Feb 2022 22:36:58 -0600 Subject: [PATCH] Add GetIdentityToken() function to the promoter implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds a new function GetIdentityToken to the promoter implementation. This function allows the current workload identity to impersonate a GCP service account and obtain an identity token from it. In order for the tests to work, the workload id that runs the test has to have the needed permissions to impersonate the test SA. Signed-off-by: Adolfo GarcĂ­a Veytia (Puerco) --- go.mod | 3 ++- internal/promoter/image/sign.go | 33 +++++++++++++++++++++++ internal/promoter/image/sign_test.go | 39 ++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 internal/promoter/image/sign_test.go diff --git a/go.mod b/go.mod index 2a5ea53e1..a4c34ff5d 100644 --- a/go.mod +++ b/go.mod @@ -35,11 +35,12 @@ require ( sigs.k8s.io/yaml v1.3.0 ) +require cloud.google.com/go/iam v0.2.0 + require ( bitbucket.org/creachadair/shell v0.0.6 // indirect cloud.google.com/go v0.100.2 // indirect cloud.google.com/go/compute v1.3.0 // indirect - cloud.google.com/go/iam v0.2.0 // indirect cloud.google.com/go/kms v1.3.0 // indirect cuelang.org/go v0.4.2 // indirect github.com/Azure/azure-sdk-for-go v61.3.0+incompatible // indirect diff --git a/internal/promoter/image/sign.go b/internal/promoter/image/sign.go index b1288a293..0e82f2a6e 100644 --- a/internal/promoter/image/sign.go +++ b/internal/promoter/image/sign.go @@ -17,17 +17,24 @@ limitations under the License. package imagepromoter import ( + "context" "fmt" "os" + credentials "cloud.google.com/go/iam/credentials/apiv1" "github.com/pkg/errors" "github.com/sirupsen/logrus" + credentialspb "google.golang.org/genproto/googleapis/iam/credentials/v1" reg "sigs.k8s.io/promo-tools/v3/legacy/dockerregistry" options "sigs.k8s.io/promo-tools/v3/promoter/image/options" "sigs.k8s.io/release-sdk/sign" ) +const ( + TestSigningAccount = "" +) + // ValidateStagingSignatures checks if edges (images) have a signature // applied during its staging run. If they do it verifies them and // returns an error if they are not valid. @@ -98,3 +105,29 @@ func (di *DefaultPromoterImplementation) WriteSBOMs( ) error { return nil } + +// GetIdentityToken returns an identity token for the selected service account +// in order for this function to work, an account has to be already logged. This +// can be achieved using the +func (di *DefaultPromoterImplementation) GetIdentityToken( + opts *options.Options, serviceAccount string, +) (tok string, err error) { + ctx := context.Background() + c, err := credentials.NewIamCredentialsClient(ctx) + if err != nil { + return tok, errors.Wrap(err, "creating credentials token") + } + defer c.Close() + req := &credentialspb.GenerateIdTokenRequest{ + Name: fmt.Sprintf("projects/-/serviceAccounts/%s", serviceAccount), + Audience: "sigstore", + IncludeEmail: true, + } + + resp, err := c.GenerateIdToken(ctx, req) + if err != nil { + return tok, errors.Wrap(err, "getting error account") + } + + return resp.Token, nil +} diff --git a/internal/promoter/image/sign_test.go b/internal/promoter/image/sign_test.go new file mode 100644 index 000000000..cb33d3e3c --- /dev/null +++ b/internal/promoter/image/sign_test.go @@ -0,0 +1,39 @@ +/* +Copyright 2022 The Kubernetes Authors. + +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 imagepromoter + +import ( + "testing" + + "github.com/stretchr/testify/require" + options "sigs.k8s.io/promo-tools/v3/promoter/image/options" + "sigs.k8s.io/release-utils/env" +) + +// TestGetIdentityToken tests the identity token generation logic. By default +// it will test using the testSigningAccount defined in sign.go. For local testing +// purposes you can override the target account with another one you have access +// to setting TEST_SERVICE_ACCOUNT to the service account's address. +func TestGetIdentityToken(t *testing.T) { + di := DefaultPromoterImplementation{} + _, err := di.GetIdentityToken(&options.Options{}, "fakeAccount@iam.project..") + require.Error(t, err) + + tok, err := di.GetIdentityToken(&options.Options{}, env.Default("TEST_SERVICE_ACCOUNT", TestSigningAccount)) + require.NoError(t, err) + require.NotEmpty(t, tok) +}