Fix attestation verify source repository check bug (#9053)
* add build source repo URI extension when repo is provided, add integration tests for this change Signed-off-by: Meredith Lancaster <malancas@github.com> * add initial docs on specifying cert identity Signed-off-by: Meredith Lancaster <malancas@github.com> * wording Signed-off-by: Meredith Lancaster <malancas@github.com> * add reusable workflow example Signed-off-by: Meredith Lancaster <malancas@github.com> * add more test cases Signed-off-by: Meredith Lancaster <malancas@github.com> * tweak to verify docs --------- Signed-off-by: Meredith Lancaster <malancas@github.com> Co-authored-by: Phill MV <phillmv@github.com>
This commit is contained in:
parent
08e8ee6746
commit
c9e8fd6c64
3 changed files with 108 additions and 5 deletions
|
|
@ -28,17 +28,28 @@ func buildSANMatcher(san, sanRegex string) (verify.SubjectAlternativeNameMatcher
|
|||
return sanMatcher, nil
|
||||
}
|
||||
|
||||
func buildCertExtensions(opts *Options, runnerEnv string) certificate.Extensions {
|
||||
extensions := certificate.Extensions{
|
||||
Issuer: opts.OIDCIssuer,
|
||||
SourceRepositoryOwnerURI: fmt.Sprintf("https://github.com/%s", opts.Owner),
|
||||
RunnerEnvironment: runnerEnv,
|
||||
}
|
||||
|
||||
// if opts.Repo is set, set the SourceRepositoryURI field before returning the extensions
|
||||
if opts.Repo != "" {
|
||||
extensions.SourceRepositoryURI = fmt.Sprintf("https://github.com/%s", opts.Repo)
|
||||
}
|
||||
return extensions
|
||||
}
|
||||
|
||||
func buildCertificateIdentityOption(opts *Options, runnerEnv string) (verify.PolicyOption, error) {
|
||||
sanMatcher, err := buildSANMatcher(opts.SAN, opts.SANRegex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extensions := certificate.Extensions{
|
||||
Issuer: opts.OIDCIssuer,
|
||||
SourceRepositoryOwnerURI: fmt.Sprintf("https://github.com/%s", opts.Owner),
|
||||
RunnerEnvironment: runnerEnv,
|
||||
}
|
||||
extensions := buildCertExtensions(opts, runnerEnv)
|
||||
|
||||
certId, err := verify.NewCertificateIdentity(sanMatcher, extensions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -54,6 +54,16 @@ func NewVerifyCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Command
|
|||
To see the full results that are generated upon successful verification, i.e.
|
||||
for use with a policy engine, provide the %[1]s--json-result%[1]s flag.
|
||||
|
||||
The attestation's certificate's Subject Alternative Name (SAN) identifies the entity
|
||||
responsible for creating the attestation, which most of the time will be a GitHub
|
||||
Actions workflow file located inside your repository. By default, this command uses
|
||||
either the %[1]s--repo%[1]s or the %[1]s--owner%[1]s flag value to validate the SAN.
|
||||
|
||||
However, if you generate attestations with a reusable workflow then the SAN will
|
||||
identify the reusable workflow – which may or may not be located inside your %[1]s--repo%[1]s
|
||||
or %[1]s--owner%[1]s. In these situations, you can use the %[1]s--cert-identity%[1]s or
|
||||
%[1]s--cert-identity-regex%[1]s flags to specify the reusable workflow's URI.
|
||||
|
||||
For more policy verification options, see the other available flags.
|
||||
`, "`"),
|
||||
Example: heredoc.Doc(`
|
||||
|
|
|
|||
82
pkg/cmd/attestation/verify/verify_integration_test.go
Normal file
82
pkg/cmd/attestation/verify/verify_integration_test.go
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//go:build integration
|
||||
|
||||
package verify
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cli/cli/v2/pkg/cmd/attestation/api"
|
||||
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact/oci"
|
||||
"github.com/cli/cli/v2/pkg/cmd/attestation/io"
|
||||
"github.com/cli/cli/v2/pkg/cmd/attestation/verification"
|
||||
"github.com/cli/cli/v2/pkg/cmd/factory"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestVerifyIntegration(t *testing.T) {
|
||||
logger := io.NewTestHandler()
|
||||
|
||||
sigstoreConfig := verification.SigstoreConfig{
|
||||
Logger: logger,
|
||||
}
|
||||
|
||||
cmdFactory := factory.New("test")
|
||||
|
||||
hc, err := cmdFactory.HttpClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
publicGoodOpts := Options{
|
||||
APIClient: api.NewLiveClient(hc, logger),
|
||||
ArtifactPath: artifactPath,
|
||||
BundlePath: bundlePath,
|
||||
DigestAlgorithm: "sha512",
|
||||
Logger: logger,
|
||||
OCIClient: oci.NewLiveClient(),
|
||||
OIDCIssuer: GitHubOIDCIssuer,
|
||||
Owner: "sigstore",
|
||||
SANRegex: "^https://github.com/sigstore/",
|
||||
SigstoreVerifier: verification.NewLiveSigstoreVerifier(sigstoreConfig),
|
||||
}
|
||||
|
||||
t.Run("with valid owner", func(t *testing.T) {
|
||||
err := runVerify(&publicGoodOpts)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("with valid repo", func(t *testing.T) {
|
||||
opts := publicGoodOpts
|
||||
opts.Repo = "sigstore/sigstore-js"
|
||||
|
||||
err := runVerify(&opts)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("with valid owner and invalid repo", func(t *testing.T) {
|
||||
opts := publicGoodOpts
|
||||
opts.Repo = "sigstore/fakerepo"
|
||||
|
||||
err := runVerify(&opts)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "verifying with issuer \"sigstore.dev\": failed to verify certificate identity: no matching certificate identity found")
|
||||
})
|
||||
|
||||
t.Run("with invalid owner", func(t *testing.T) {
|
||||
opts := publicGoodOpts
|
||||
opts.Owner = "fakeowner"
|
||||
|
||||
err := runVerify(&opts)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "verifying with issuer \"sigstore.dev\": failed to verify certificate identity: no matching certificate identity found")
|
||||
})
|
||||
|
||||
t.Run("with invalid owner and invalid repo", func(t *testing.T) {
|
||||
opts := publicGoodOpts
|
||||
opts.Repo = "fakeowner/fakerepo"
|
||||
|
||||
err := runVerify(&opts)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "verifying with issuer \"sigstore.dev\": failed to verify certificate identity: no matching certificate identity found")
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue