From 90de6a06634f326ea35b964aede9e84393fbea77 Mon Sep 17 00:00:00 2001
From: Dan Lorenc <lorenc.d@gmail.com>
Date: Sun, 12 Sep 2021 08:27:22 -0500
Subject: [PATCH] Support GCP environments without workload identity (GCB).

This requires the use of an environment variable called "GOOGLE_SERVICE_ACCOUNT_NAME"
to direct the client on which account to impersonate.

Signed-off-by: Dan Lorenc <lorenc.d@gmail.com>
---
 go.mod                         |  3 +--
 go.sum                         |  2 --
 pkg/providers/google/google.go | 31 +++++++++++++++++++++++++++++++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/go.mod b/go.mod
index 566030f5502b..fad82a7f6d49 100644
--- a/go.mod
+++ b/go.mod
@@ -23,7 +23,6 @@ require (
 	github.com/sigstore/fulcio v0.1.2-0.20210831152525-42f7422734bb
 	github.com/sigstore/rekor v0.3.0
 	github.com/sigstore/sigstore v0.0.0-20210729211320-56a91f560f44
-	github.com/spf13/pflag v1.0.5
 	github.com/stretchr/testify v1.7.0
 	github.com/theupdateframework/go-tuf v0.0.0-20210722233521-90e262754396
 	golang.org/x/mod v0.5.0 // indirect
@@ -36,7 +35,7 @@ require (
 	k8s.io/api v0.22.1
 	k8s.io/apimachinery v0.22.1
 	k8s.io/client-go v0.22.1
-	k8s.io/klog/v2 v2.10.0
+	k8s.io/klog/v2 v2.10.0 // indirect
 )
 
 require (
diff --git a/go.sum b/go.sum
index f141a90f22c3..d51dca65b21a 100644
--- a/go.sum
+++ b/go.sum
@@ -2505,8 +2505,6 @@ k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
 k8s.io/utils v0.0.0-20210802155522-efc7438f0176 h1:Mx0aa+SUAcNRQbs5jUzV8lkDlGFU8laZsY9jrcVX5SY=
 k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 knative.dev/hack v0.0.0-20210806075220-815cd312d65c/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
-knative.dev/pkg v0.0.0-20210907232433-26db1ba732f6 h1:nLHaEQP+SNW4E6zsgSS6wwpHNpSpag8vw8SSsH4ILw8=
-knative.dev/pkg v0.0.0-20210907232433-26db1ba732f6/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
 knative.dev/pkg v0.0.0-20210908025933-71508fc69a57 h1:du+do3to2zboxuk0Uj8Xvf2onOxthyaBSr98+hVB7z4=
 knative.dev/pkg v0.0.0-20210908025933-71508fc69a57/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
 nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
diff --git a/pkg/providers/google/google.go b/pkg/providers/google/google.go
index 1e3edb0c056e..6daa2fcdd8e8 100644
--- a/pkg/providers/google/google.go
+++ b/pkg/providers/google/google.go
@@ -18,15 +18,18 @@ package google
 import (
 	"context"
 	"io/ioutil"
+	"os"
 	"strings"
 
 	"google.golang.org/api/idtoken"
+	"google.golang.org/api/impersonate"
 
 	"github.com/sigstore/cosign/pkg/providers"
 )
 
 func init() {
 	providers.Register("google-workload-identity", &googleWorkloadIdentity{})
+	providers.Register("google-impersonate", &googleImpersonate{})
 }
 
 type googleWorkloadIdentity struct{}
@@ -66,3 +69,31 @@ func (gwi *googleWorkloadIdentity) Provide(ctx context.Context, audience string)
 	}
 	return tok.AccessToken, nil
 }
+
+type googleImpersonate struct{}
+
+var _ providers.Interface = (*googleImpersonate)(nil)
+
+// Enabled implements providers.Interface
+func (gi *googleImpersonate) Enabled(ctx context.Context) bool {
+	// The "impersonate" method requires a target service account to impersonate.
+	return os.Getenv("GOOGLE_SERVICE_ACCOUNT_NAME") != ""
+}
+
+// Provide implements providers.Interface
+func (gi *googleImpersonate) Provide(ctx context.Context, audience string) (string, error) {
+	target := os.Getenv("GOOGLE_SERVICE_ACCOUNT_NAME")
+	ts, err := impersonate.IDTokenSource(ctx, impersonate.IDTokenConfig{
+		Audience:        "sigstore",
+		TargetPrincipal: target,
+		IncludeEmail:    true,
+	})
+	if err != nil {
+		return "", err
+	}
+	tok, err := ts.Token()
+	if err != nil {
+		return "", err
+	}
+	return tok.AccessToken, nil
+}