Skip to content

Commit

Permalink
Support GCP environments without workload identity (GCB). (#652)
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Dan Lorenc <[email protected]>
  • Loading branch information
dlorenc authored Sep 12, 2021
1 parent 118399c commit 3f83940
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
10 changes: 10 additions & 0 deletions KEYLESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ $ cosign sign --identity-token=$(
In order to impersonate an IAM service account, your account must have the
`roles/iam.serviceAccountTokenCreator` role.

**Note**: On Google Cloud Build, standard identity tokens are not supported through the GCE metadata server.
`cosign` has a special flow for this case, where you can instruct the Cloud Build service account to impersonate
another service account.
To configure this flow:

1. Create a service account to use for signatures (the email address will be present in the certificate subject).
2. Grant the Cloud Build service account the `roles/iam.serviceAccountTokenCreator` role for this target account.
3. Set the `GOOGLE_SERVICE_ACCOUNT_NAME` environment variable to the name of the target account in your cloudbuid.yaml
4. Sign images in GCB, without keys!

### Timestamps

Signature timestamps are checked in the [rekor](https://github.com/sigstore/rekor) transparency log. Rekor's `IntegratedTime` is signed as part of its `signedEntryTimestamp`. Cosign verifies the signature over the timestamp and checks that the signature was created while the certificate was valid.
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 (
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
31 changes: 31 additions & 0 deletions pkg/providers/google/google.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand Down Expand Up @@ -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
}

0 comments on commit 3f83940

Please sign in to comment.