diff --git a/cmd/cosign/cli/verify.go b/cmd/cosign/cli/verify.go index ce2280ff2ef..e1b8b32be47 100644 --- a/cmd/cosign/cli/verify.go +++ b/cmd/cosign/cli/verify.go @@ -59,7 +59,13 @@ against the transparency log.`, cosign verify --key hashivault://[KEY] # verify image with public key stored in a Kubernetes secret - cosign verify --key k8s://[NAMESPACE]/[KEY] `, + cosign verify --key k8s://[NAMESPACE]/[KEY] + + # verify image with public key stored in GitLab with project name + cosign verify --key gitlab://[OWNER]/[PROJECT_NAME] + + # verify image with public key stored in GitLab with project id + cosign verify --key gitlab://[PROJECT_ID] `, Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { @@ -119,7 +125,13 @@ against the transparency log.`, cosign verify-attestation --key gcpkms://projects//locations/global/keyRings//cryptoKeys/ # verify image with public key stored in Hashicorp Vault - cosign verify-attestation --key hashivault:/// `, + cosign verify-attestation --key hashivault:/// + + # verify image with public key stored in GitLab with project name + cosign verify-attestation --key gitlab://[OWNER]/[PROJECT_NAME] + + # verify image with public key stored in GitLab with project id + cosign verify-attestation --key gitlab://[PROJECT_ID] `, Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { @@ -182,7 +194,13 @@ The blob may be specified as a path to a file or - for stdin.`, cosign verify-blob --key gcpkms://projects/[PROJECT ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY] --signature $sig # Verify a signature against Hashicorp Vault - cosign verify-blob --key hashivault://[KEY] --signature $sig `, + cosign verify-blob --key hashivault://[KEY] --signature $sig + + # Verify a signature against GitLab with project name + cosign verify-blob --key gitlab://[OWNER]/[PROJECT_NAME] --signature $sig + + # Verify a signature against GitLab with project id + cosign verify-blob --key gitlab://[PROJECT_ID] --signature $sig `, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/doc/cosign_verify-attestation.md b/doc/cosign_verify-attestation.md index 17cb350c16d..d5174cb1b35 100644 --- a/doc/cosign_verify-attestation.md +++ b/doc/cosign_verify-attestation.md @@ -39,6 +39,12 @@ cosign verify-attestation [flags] # verify image with public key stored in Hashicorp Vault cosign verify-attestation --key hashivault:/// + + # verify image with public key stored in GitLab with project name + cosign verify-attestation --key gitlab://[OWNER]/[PROJECT_NAME] + + # verify image with public key stored in GitLab with project id + cosign verify-attestation --key gitlab://[PROJECT_ID] ``` ### Options diff --git a/doc/cosign_verify-blob.md b/doc/cosign_verify-blob.md index e6540a93a30..61be42bf358 100644 --- a/doc/cosign_verify-blob.md +++ b/doc/cosign_verify-blob.md @@ -46,6 +46,12 @@ cosign verify-blob [flags] # Verify a signature against Hashicorp Vault cosign verify-blob --key hashivault://[KEY] --signature $sig + + # Verify a signature against GitLab with project name + cosign verify-blob --key gitlab://[OWNER]/[PROJECT_NAME] --signature $sig + + # Verify a signature against GitLab with project id + cosign verify-blob --key gitlab://[PROJECT_ID] --signature $sig ``` ### Options diff --git a/doc/cosign_verify.md b/doc/cosign_verify.md index 37f769d37d0..31c90a131e1 100644 --- a/doc/cosign_verify.md +++ b/doc/cosign_verify.md @@ -42,6 +42,12 @@ cosign verify [flags] # verify image with public key stored in a Kubernetes secret cosign verify --key k8s://[NAMESPACE]/[KEY] + + # verify image with public key stored in GitLab with project name + cosign verify --key gitlab://[OWNER]/[PROJECT_NAME] + + # verify image with public key stored in GitLab with project id + cosign verify --key gitlab://[PROJECT_ID] ``` ### Options diff --git a/pkg/cosign/git/git.go b/pkg/cosign/git/git.go index c9b886a7d2b..57a6777c549 100644 --- a/pkg/cosign/git/git.go +++ b/pkg/cosign/git/git.go @@ -30,6 +30,7 @@ var providerMap = map[string]Git{ type Git interface { PutSecret(ctx context.Context, ref string, pf cosign.PassFunc) error + GetSecret(ctx context.Context, ref string) (string, error) } func GetProvider(provider string) Git { diff --git a/pkg/cosign/git/github/github.go b/pkg/cosign/git/github/github.go index a8967cad2f2..0fabf39c51f 100644 --- a/pkg/cosign/git/github/github.go +++ b/pkg/cosign/git/github/github.go @@ -135,3 +135,8 @@ func (g *Gh) PutSecret(ctx context.Context, ref string, pf cosign.PassFunc) erro return nil } + +// NOTE: GetSecret is not implemented for GitHub +func (g *Gh) GetSecret(ctx context.Context, ref string) (string, error) { + return "", nil +} diff --git a/pkg/cosign/git/gitlab/gitlab.go b/pkg/cosign/git/gitlab/gitlab.go index 3c6dcc68f9c..95146b14b6c 100644 --- a/pkg/cosign/git/gitlab/gitlab.go +++ b/pkg/cosign/git/gitlab/gitlab.go @@ -124,3 +124,39 @@ func (g *Gl) PutSecret(ctx context.Context, ref string, pf cosign.PassFunc) erro return nil } + +func (g *Gl) GetSecret(ctx context.Context, ref string) (string, error) { + token, tokenExists := os.LookupEnv("GITLAB_TOKEN") + var varPubKeyValue string + if !tokenExists { + return varPubKeyValue, errors.New("could not find \"GITLAB_TOKEN\"") + } + + var client *gitlab.Client + var err error + if url, baseURLExists := os.LookupEnv("GITLAB_HOST"); baseURLExists { + client, err = gitlab.NewClient(token, gitlab.WithBaseURL(url)) + if err != nil { + return varPubKeyValue, errors.Wrap(err, "could not create GitLab client") + } + } else { + client, err = gitlab.NewClient(token) + if err != nil { + return varPubKeyValue, errors.Wrap(err, "could not create GitLab client") + } + } + + varPubKey, pubKeyResp, err := client.ProjectVariables.GetVariable(ref, "COSIGN_PUBLIC_KEY") + if err != nil { + return varPubKeyValue, errors.Wrap(err, "could not retrieve \"COSIGN_PUBLIC_KEY\" variable") + } + + varPubKeyValue = varPubKey.Value + + if pubKeyResp.StatusCode < 200 && pubKeyResp.StatusCode >= 300 { + bodyBytes, _ := io.ReadAll(pubKeyResp.Body) + return varPubKeyValue, errors.Errorf("%s", bodyBytes) + } + + return varPubKeyValue, nil +} diff --git a/pkg/signature/keys.go b/pkg/signature/keys.go index 580762c5e5f..c2e0376700b 100644 --- a/pkg/signature/keys.go +++ b/pkg/signature/keys.go @@ -25,6 +25,8 @@ import ( "github.com/sigstore/cosign/pkg/blob" "github.com/sigstore/cosign/pkg/cosign" + "github.com/sigstore/cosign/pkg/cosign/git" + "github.com/sigstore/cosign/pkg/cosign/git/gitlab" "github.com/sigstore/cosign/pkg/cosign/kubernetes" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" @@ -110,6 +112,25 @@ func PublicKeyFromKeyRef(ctx context.Context, keyRef string) (signature.Verifier } } + if strings.HasPrefix(keyRef, gitlab.ReferenceScheme) { + split := strings.Split(keyRef, "://") + + if len(split) < 2 { + return nil, errors.New("could not parse scheme, use :// format") + } + + provider, targetRef := split[0], split[1] + + keyValue, err := git.GetProvider(provider).GetSecret(ctx, targetRef) + if err != nil { + return nil, err + } + + if len(keyValue) > 0 { + return loadPublicKey([]byte(keyValue)) + } + } + return LoadPublicKey(ctx, keyRef) }