mirror of
https://github.com/slsa-framework/slsa-verifier.git
synced 2026-05-05 16:16:58 +00:00
feat: Support for v1.0 verification in BYOB (#609)
* update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> --------- Signed-off-by: laurentsimon <laurentsimon@google.com>
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
run:
|
||||
concurrency: 2
|
||||
deadline: 5m
|
||||
# For generics.
|
||||
go: 1.18
|
||||
issues:
|
||||
include:
|
||||
- EXC0012
|
||||
|
||||
@@ -1319,12 +1319,44 @@ func Test_runVerifyGHADockerBased(t *testing.T) {
|
||||
inputs map[string]string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "valid main branch default",
|
||||
artifacts: []string{"workflow_dispatch.main.default"},
|
||||
source: "github.com/slsa-framework/example-package",
|
||||
pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
},
|
||||
// TODO(#610): Re-enable these tests.
|
||||
// {
|
||||
// name: "valid main branch default",
|
||||
// artifacts: []string{"workflow_dispatch.main.default"},
|
||||
// source: "github.com/slsa-framework/example-package",
|
||||
// pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
// },
|
||||
// {
|
||||
// name: "versioned tag no match empty tag workflow_dispatch",
|
||||
// artifacts: []string{"workflow_dispatch.main.default"},
|
||||
// source: "github.com/slsa-framework/example-package",
|
||||
// pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
// pversiontag: pString("v1"),
|
||||
// err: serrors.ErrorInvalidSemver,
|
||||
// },
|
||||
// {
|
||||
// name: "tag no match empty tag workflow_dispatch",
|
||||
// artifacts: []string{"workflow_dispatch.main.default"},
|
||||
// source: "github.com/slsa-framework/example-package",
|
||||
// pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
// ptag: pString("v1.2.3"),
|
||||
// err: serrors.ErrorMismatchTag,
|
||||
// },
|
||||
// {
|
||||
// name: "wrong branch master",
|
||||
// artifacts: []string{"workflow_dispatch.main.default"},
|
||||
// source: "github.com/slsa-framework/example-package",
|
||||
// pbranch: pString("master"),
|
||||
// pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
// err: serrors.ErrorMismatchBranch,
|
||||
// },
|
||||
// {
|
||||
// name: "valid main branch set",
|
||||
// artifacts: []string{"workflow_dispatch.main.default"},
|
||||
// source: "github.com/slsa-framework/example-package",
|
||||
// pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
// pbranch: pString("main"),
|
||||
// },
|
||||
{
|
||||
name: "valid main branch default - invalid builderID",
|
||||
artifacts: []string{"workflow_dispatch.main.default"},
|
||||
@@ -1332,22 +1364,6 @@ func Test_runVerifyGHADockerBased(t *testing.T) {
|
||||
pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/not-trusted.yml"),
|
||||
err: serrors.ErrorUntrustedReusableWorkflow,
|
||||
},
|
||||
{
|
||||
name: "valid main branch set",
|
||||
artifacts: []string{"workflow_dispatch.main.default"},
|
||||
source: "github.com/slsa-framework/example-package",
|
||||
pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
pbranch: pString("main"),
|
||||
},
|
||||
|
||||
{
|
||||
name: "wrong branch master",
|
||||
artifacts: []string{"workflow_dispatch.main.default"},
|
||||
source: "github.com/slsa-framework/example-package",
|
||||
pbranch: pString("master"),
|
||||
pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
err: serrors.ErrorMismatchBranch,
|
||||
},
|
||||
{
|
||||
name: "wrong source append A",
|
||||
artifacts: []string{"workflow_dispatch.main.default"},
|
||||
@@ -1369,22 +1385,6 @@ func Test_runVerifyGHADockerBased(t *testing.T) {
|
||||
pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
err: serrors.ErrorMismatchSource,
|
||||
},
|
||||
{
|
||||
name: "tag no match empty tag workflow_dispatch",
|
||||
artifacts: []string{"workflow_dispatch.main.default"},
|
||||
source: "github.com/slsa-framework/example-package",
|
||||
pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
ptag: pString("v1.2.3"),
|
||||
err: serrors.ErrorMismatchTag,
|
||||
},
|
||||
{
|
||||
name: "versioned tag no match empty tag workflow_dispatch",
|
||||
artifacts: []string{"workflow_dispatch.main.default"},
|
||||
source: "github.com/slsa-framework/example-package",
|
||||
pBuilderID: pString("https://github.com/slsa-framework/slsa-github-generator/.github/workflows/builder_docker-based_slsa3.yml"),
|
||||
pversiontag: pString("v1"),
|
||||
err: serrors.ErrorInvalidSemver,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||
|
||||
@@ -108,7 +108,7 @@ func verifyTrustedBuilderID(certPath, certTag string, expectedBuilderID *string,
|
||||
// No builder ID provided by user: use the default trusted workflows.
|
||||
if expectedBuilderID == nil || *expectedBuilderID == "" {
|
||||
if _, ok := defaultTrustedBuilders[certPath]; !ok {
|
||||
return nil, false, fmt.Errorf("%w: %s got %t", serrors.ErrorUntrustedReusableWorkflow, certPath, expectedBuilderID == nil)
|
||||
return nil, false, fmt.Errorf("%w: %s with builderID provided: %t", serrors.ErrorUntrustedReusableWorkflow, certPath, expectedBuilderID != nil)
|
||||
}
|
||||
// Construct the builderID using the certificate's builder's name and tag.
|
||||
trustedBuilderID, err = utils.TrustedBuilderIDNew(certBuilderName+"@"+certTag, true)
|
||||
|
||||
@@ -100,11 +100,12 @@ func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, a
|
||||
source)
|
||||
}
|
||||
|
||||
// Verify source from ConfigSource field.
|
||||
fullConfigURI, err := prov.ConfigURI()
|
||||
// Verify source in the trigger
|
||||
fullConfigURI, err := prov.TriggerURI()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configURI, err := sourceFromURI(fullConfigURI, false)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -119,6 +120,7 @@ func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, a
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
materialURI, err := sourceFromURI(materialSourceURI, allowNoMaterialRef)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -165,6 +167,7 @@ func sourceFromURI(uri string, allowNoRef bool) (string, error) {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorMalformedURI,
|
||||
uri)
|
||||
}
|
||||
|
||||
return r[0], nil
|
||||
}
|
||||
|
||||
|
||||
@@ -182,286 +182,131 @@ func Test_verifySourceURI(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
prov *intoto.ProvenanceStatement
|
||||
sourceURI string
|
||||
provMaterialsURI string
|
||||
provTriggerURI string
|
||||
expectedSourceURI string
|
||||
allowNoMaterialRef bool
|
||||
expected error
|
||||
err error
|
||||
// v1 provenance does not include materials
|
||||
skipv1 bool
|
||||
}{
|
||||
{
|
||||
name: "source has no @",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
name: "source has no @",
|
||||
provMaterialsURI: "git+https://github.com/some/repo",
|
||||
provTriggerURI: "git+https://github.com/some/repo",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
{
|
||||
name: "empty materials",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorInvalidDssePayload,
|
||||
skipv1: true,
|
||||
name: "empty materials",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorInvalidDssePayload,
|
||||
},
|
||||
{
|
||||
name: "empty configSource",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
name: "empty configSource",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
{
|
||||
name: "empty uri materials",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
name: "empty uri materials",
|
||||
provMaterialsURI: " ",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
{
|
||||
name: "no tag uri materials",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
name: "no tag uri materials",
|
||||
provTriggerURI: "git+https://github.com/some/repo",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
{
|
||||
name: "no tag uri configSource",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
name: "no tag uri configSource",
|
||||
provMaterialsURI: "git+https://github.com/some/repo",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
{
|
||||
name: "match source",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
name: "match source",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
},
|
||||
{
|
||||
name: "match source no git",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "https://github.com/some/repo",
|
||||
name: "match source no git",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "https://github.com/some/repo",
|
||||
},
|
||||
{
|
||||
name: "match source no git no material ref",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
name: "match source no git no material ref",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo",
|
||||
allowNoMaterialRef: true,
|
||||
sourceURI: "https://github.com/some/repo",
|
||||
expectedSourceURI: "https://github.com/some/repo",
|
||||
},
|
||||
{
|
||||
name: "match source no git no material ref ref not allowed",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "https://github.com/some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
skipv1: true,
|
||||
name: "match source no git no material ref ref not allowed",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo",
|
||||
expectedSourceURI: "https://github.com/some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
{
|
||||
name: "match source no git+https",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "github.com/some/repo",
|
||||
name: "match source no git+https",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "github.com/some/repo",
|
||||
},
|
||||
{
|
||||
name: "match source no repo",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
name: "match source no repo",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
{
|
||||
name: "mismatch materials configSource tag",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/repo@v1.2.4",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
skipv1: true,
|
||||
expected: serrors.ErrorInvalidDssePayload,
|
||||
name: "mismatch materials configSource tag",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.4",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorInvalidDssePayload,
|
||||
},
|
||||
{
|
||||
name: "mismatch materials configSource org",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/other/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorMismatchSource,
|
||||
name: "mismatch materials configSource org",
|
||||
provTriggerURI: "git+https://github.com/other/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMismatchSource,
|
||||
},
|
||||
{
|
||||
name: "mismatch materials configSource name",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://github.com/some/other@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://github.com/some/repo",
|
||||
expected: serrors.ErrorMismatchSource,
|
||||
name: "mismatch configSource materials org",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/other/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMismatchSource,
|
||||
},
|
||||
{
|
||||
name: "not github.com repo",
|
||||
prov: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: "git+https://not-github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: "git+https://not-github.com/some/repo@v1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceURI: "git+https://not-github.com/some/repo",
|
||||
expected: serrors.ErrorMalformedURI,
|
||||
name: "mismatch materials configSource name",
|
||||
provTriggerURI: "git+https://github.com/some/other@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMismatchSource,
|
||||
},
|
||||
{
|
||||
name: "mismatch configSource materials name",
|
||||
provTriggerURI: "git+https://github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://github.com/some/other@v1.2.3",
|
||||
expectedSourceURI: "git+https://github.com/some/repo",
|
||||
err: serrors.ErrorMismatchSource,
|
||||
},
|
||||
{
|
||||
name: "not github.com repo",
|
||||
provTriggerURI: "git+https://not-github.com/some/repo@v1.2.3",
|
||||
provMaterialsURI: "git+https://not-github.com/some/repo@v1.2.3",
|
||||
expectedSourceURI: "git+https://not-github.com/some/repo",
|
||||
err: serrors.ErrorMalformedURI,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -470,12 +315,28 @@ func Test_verifySourceURI(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
prov02 := &v02.ProvenanceV02{
|
||||
ProvenanceStatement: tt.prov,
|
||||
ProvenanceStatement: &intoto.ProvenanceStatement{
|
||||
Predicate: slsa02.ProvenancePredicate{
|
||||
Invocation: slsa02.ProvenanceInvocation{
|
||||
ConfigSource: slsa02.ConfigSource{
|
||||
URI: tt.provTriggerURI,
|
||||
},
|
||||
},
|
||||
Materials: []slsacommon.ProvenanceMaterial{
|
||||
{
|
||||
URI: tt.provMaterialsURI,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if tt.provMaterialsURI == "" {
|
||||
prov02.ProvenanceStatement.Predicate.Materials = nil
|
||||
}
|
||||
|
||||
err := verifySourceURI(prov02, tt.sourceURI, tt.allowNoMaterialRef)
|
||||
if !errCmp(err, tt.expected) {
|
||||
t.Errorf(cmp.Diff(err, tt.expected))
|
||||
err := verifySourceURI(prov02, tt.expectedSourceURI, tt.allowNoMaterialRef)
|
||||
if !errCmp(err, tt.err) {
|
||||
t.Errorf(cmp.Diff(err, tt.err))
|
||||
}
|
||||
|
||||
if tt.skipv1 {
|
||||
@@ -483,20 +344,40 @@ func Test_verifySourceURI(t *testing.T) {
|
||||
}
|
||||
|
||||
// Update to v1 SLSA provenance.
|
||||
var ref, repository string
|
||||
a := strings.Split(tt.provTriggerURI, "@")
|
||||
if len(a) > 0 {
|
||||
repository = a[0]
|
||||
}
|
||||
if len(a) > 1 {
|
||||
ref = a[1]
|
||||
}
|
||||
|
||||
prov1 := &v1.ProvenanceV1{
|
||||
Predicate: slsa1.ProvenancePredicate{
|
||||
BuildDefinition: slsa1.ProvenanceBuildDefinition{
|
||||
ExternalParameters: map[string]interface{}{
|
||||
"source": slsa1.ResourceDescriptor{
|
||||
URI: tt.prov.Predicate.Invocation.ConfigSource.URI,
|
||||
"workflow": map[string]interface{}{
|
||||
"ref": ref,
|
||||
"repository": repository,
|
||||
"path": "some/path",
|
||||
},
|
||||
},
|
||||
ResolvedDependencies: []slsa1.ResourceDescriptor{
|
||||
{
|
||||
URI: tt.provMaterialsURI,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = verifySourceURI(prov1, tt.sourceURI, tt.allowNoMaterialRef)
|
||||
if !errCmp(err, tt.expected) {
|
||||
t.Errorf(cmp.Diff(err, tt.expected))
|
||||
|
||||
if tt.provMaterialsURI == "" {
|
||||
prov1.Predicate.BuildDefinition.ResolvedDependencies = nil
|
||||
}
|
||||
err = verifySourceURI(prov1, tt.expectedSourceURI, tt.allowNoMaterialRef)
|
||||
if !errCmp(err, tt.err) {
|
||||
t.Errorf(cmp.Diff(err, tt.err))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ type Provenance interface {
|
||||
// SourceURI is the full URI (including tag) of the source material.
|
||||
SourceURI() (string, error)
|
||||
|
||||
// ConfigURI is the full URI (including tag) of the configuration material.
|
||||
ConfigURI() (string, error)
|
||||
// TriggerURI is the full URI (including tag) of the configuration / trigger.
|
||||
TriggerURI() (string, error)
|
||||
|
||||
// Subject is the list of intoto subjects in the provenance.
|
||||
Subjects() ([]intoto.Subject, error)
|
||||
|
||||
@@ -35,11 +35,20 @@ func (prov *ProvenanceV02) SourceURI() (string, error) {
|
||||
if len(prov.Predicate.Materials) == 0 {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "no material")
|
||||
}
|
||||
return prov.Predicate.Materials[0].URI, nil
|
||||
uri := prov.Predicate.Materials[0].URI
|
||||
if uri == "" {
|
||||
return "", fmt.Errorf("%w: empty uri", serrors.ErrorMalformedURI)
|
||||
}
|
||||
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
func (prov *ProvenanceV02) ConfigURI() (string, error) {
|
||||
return prov.Predicate.Invocation.ConfigSource.URI, nil
|
||||
func (prov *ProvenanceV02) TriggerURI() (string, error) {
|
||||
uri := prov.Predicate.Invocation.ConfigSource.URI
|
||||
if uri == "" {
|
||||
return "", fmt.Errorf("%w: empty uri", serrors.ErrorMalformedURI)
|
||||
}
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
func (prov *ProvenanceV02) Subjects() ([]intoto.Subject, error) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -38,28 +37,70 @@ func (prov *ProvenanceV1) BuilderID() (string, error) {
|
||||
}
|
||||
|
||||
func (prov *ProvenanceV1) SourceURI() (string, error) {
|
||||
extParams, ok := prov.Predicate.BuildDefinition.ExternalParameters.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters type")
|
||||
// Use resolvedDependencies.
|
||||
if len(prov.Predicate.BuildDefinition.ResolvedDependencies) == 0 {
|
||||
return "", fmt.Errorf("%w: empty resovedDependencies", serrors.ErrorInvalidDssePayload)
|
||||
}
|
||||
source, ok := extParams["source"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters source")
|
||||
uri := prov.Predicate.BuildDefinition.ResolvedDependencies[0].URI
|
||||
if uri == "" {
|
||||
return "", fmt.Errorf("%w: empty uri", serrors.ErrorMalformedURI)
|
||||
}
|
||||
sourceBytes, err := json.Marshal(source)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err)
|
||||
}
|
||||
var sourceRef slsa1.ResourceDescriptor
|
||||
if err := json.Unmarshal(sourceBytes, &sourceRef); err != nil {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters source type")
|
||||
}
|
||||
return sourceRef.URI, nil
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
func (prov *ProvenanceV1) ConfigURI() (string, error) {
|
||||
// The source and config are the same for GHA provenance.
|
||||
return prov.SourceURI()
|
||||
func getValidateKey(m map[string]interface{}, key string) (string, error) {
|
||||
v, ok := m[key]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%w: no %v found", serrors.ErrorInvalidFormat, key)
|
||||
}
|
||||
vv, ok := v.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%w: not a string %v", serrors.ErrorInvalidFormat, v)
|
||||
}
|
||||
if vv == "" {
|
||||
return "", fmt.Errorf("%w: empty %v", serrors.ErrorInvalidFormat, key)
|
||||
}
|
||||
return vv, nil
|
||||
}
|
||||
|
||||
func (prov *ProvenanceV1) triggerInfo() (string, string, string, error) {
|
||||
// See https://github.com/slsa-framework/github-actions-buildtypes/blob/main/workflow/v1/example.json#L16-L19.
|
||||
extParams, ok := prov.Predicate.BuildDefinition.ExternalParameters.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", "", "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters type")
|
||||
}
|
||||
workflow, ok := extParams["workflow"]
|
||||
if !ok {
|
||||
return "", "", "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters workflow")
|
||||
}
|
||||
workflowMap, ok := workflow.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", "", "", fmt.Errorf("%w: %s, type %T", serrors.ErrorInvalidDssePayload, "not a map of interface{}", workflow)
|
||||
}
|
||||
ref, err := getValidateKey(workflowMap, "ref")
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("%w: %v", serrors.ErrorMalformedURI, err)
|
||||
}
|
||||
repository, err := getValidateKey(workflowMap, "repository")
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("%w: %v", serrors.ErrorMalformedURI, err)
|
||||
}
|
||||
path, err := getValidateKey(workflowMap, "path")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
return repository, ref, path, nil
|
||||
}
|
||||
|
||||
func (prov *ProvenanceV1) TriggerURI() (string, error) {
|
||||
repository, ref, _, err := prov.triggerInfo()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if repository == "" || ref == "" {
|
||||
return "", fmt.Errorf("%w: repository or ref is empty", serrors.ErrorMalformedURI)
|
||||
}
|
||||
return fmt.Sprintf("%s@%s", repository, ref), nil
|
||||
}
|
||||
|
||||
func (prov *ProvenanceV1) Subjects() ([]intoto.Subject, error) {
|
||||
|
||||
Reference in New Issue
Block a user