Skip to content

Commit

Permalink
Support GCP environments without workload identity (GCB).
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 <lorenc.d@gmail.com>
Signed-off-by: Dan Lorenc <dlorenc@google.com>
  • Loading branch information
dlorenc authored and Dan Lorenc committed Sep 12, 2021
1 parent f8f2e7a commit 6393129
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 6393129

Please sign in to comment.