Skip to content

Commit

Permalink
feat: Update SLSA verifier to support a global signing key for GCB V1…
Browse files Browse the repository at this point in the history
… which… (#509)

* Update SLSA verifier to support a global signing key for GCB V1 which creates the signature in a DSSE-conformant PAE format

- new public key for "global PAE signing key"
- test data and unit tests

Signed-off-by: Kevin Halk <khalk@google.com>

* Update SLSA verifier to support a global signing key for GCB V1 which creates the signature in a DSSE-conformant PAE format

- new public key for "global PAE signing key"
- test data and unit tests

Signed-off-by: Kevin Halk <khalk@google.com>

* Update SLSA verifier to support a global signing key for GCB V1 which creates the signature in a DSSE-conformant PAE format

- new public key for "global PAE signing key"
- test data and unit tests

Signed-off-by: Kevin Halk <khalk@google.com>

* Update SLSA verifier to support a global signing key for GCB V1 which creates the signature in a DSSE-conformant PAE format

- new public key for "global PAE signing key"
- test data and unit tests

Signed-off-by: Kevin Halk <khalk@google.com>

* Update SLSA verifier to support a global signing key for GCB V1 which creates the signature in a DSSE-conformant PAE format

- new public key for "global PAE signing key"
- test data and unit tests

Signed-off-by: Kevin Halk <khalk@google.com>

* Update SLSA verifier to support a global signing key for GCB V1 which creates the signature in a DSSE-conformant PAE format

- new public key for "global PAE signing key"
- test data and unit tests

Signed-off-by: Kevin Halk <khalk@google.com>

* Update SLSA verifier to support a global signing key for GCB V1 which creates the signature in a DSSE-conformant PAE format

- new public key for "global PAE signing key"
- test data and unit tests

Signed-off-by: Kevin Halk <khalk@google.com>

---------

Signed-off-by: Kevin Halk <khalk@google.com>
  • Loading branch information
khalkie committed Mar 6, 2023
1 parent 9f57e6a commit 47495c7
Show file tree
Hide file tree
Showing 7 changed files with 452 additions and 18 deletions.
51 changes: 50 additions & 1 deletion verifiers/internal/gcb/keys/keys.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
package keys

import (
"crypto"
"crypto/ecdsa"
"crypto/sha256"
"crypto/x509"
"embed"
"encoding/pem"
"fmt"
"io/fs"
"path"

dsselib "github.com/secure-systems-lab/go-securesystemslib/dsse"
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
)

//go:embed materials/*
var publicKeys embed.FS

const GlobalPAEKeyID = "projects/verified-builder/locations/global/keyRings/attestor/cryptoKeys/provenanceSigner/cryptoKeyVersions/1"
const GlobalPAEPublicKeyName = "global-pae"

type PublicKey struct {
value []byte
pubKey *ecdsa.PublicKey
region string
// TODO: key type and size
}

func PublicKeyNew(region string) (*PublicKey, error) {
func NewPublicKey(region string) (*PublicKey, error) {
content, err := fs.ReadFile(publicKeys, path.Join("materials", region+".key"))
if err != nil {
return nil, fmt.Errorf("%w: cannot read key materials", err)
Expand Down Expand Up @@ -61,3 +67,46 @@ func (p *PublicKey) VerifySignature(digest [32]byte, sig []byte) error {

return nil
}

type GlobalPAEKey struct {
publicKey *PublicKey
Verifier *dsselib.EnvelopeVerifier
}

func NewGlobalPAEKey() (*GlobalPAEKey, error) {
publicKey, err := NewPublicKey(GlobalPAEPublicKeyName)
if err != nil {
return nil, fmt.Errorf("unable to create public key for Global PAE key: %w", err)
}

globalPaeKey := &GlobalPAEKey{publicKey: publicKey}
envVerifier, err := dsselib.NewEnvelopeVerifier(globalPaeKey)
if err != nil {
return nil, err
}
globalPaeKey.Verifier = envVerifier
return globalPaeKey, nil
}

func (v *GlobalPAEKey) VerifyPAESignature(envelope *dsselib.Envelope) error {
_, err := v.Verifier.Verify(envelope)
return err
}

// Verify implements dsse.Verifier.Verify. It verifies
// a signature formatted in DSSE-conformant PAE.
func (v *GlobalPAEKey) Verify(data, sig []byte) error {
// Verify the signature.
digest := sha256.Sum256(data)
return v.publicKey.VerifySignature(digest, sig)
}

// KeyID implements dsse.Verifier.KeyID.
func (v *GlobalPAEKey) KeyID() (string, error) {
return GlobalPAEKeyID, nil
}

// Public implements dsse.Verifier.Public.
func (v *GlobalPAEKey) Public() crypto.PublicKey {
return v.publicKey
}
4 changes: 4 additions & 0 deletions verifiers/internal/gcb/keys/materials/global-pae.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdMcJUyKbmarf6dydhfmAjgmK6c42
oCCNRR1se3Bi3VO65KcGk6qyci6/bsu2s4u+dLKWrsUQomEw4v3FtVctoA==
-----END PUBLIC KEY-----
49 changes: 34 additions & 15 deletions verifiers/internal/gcb/provenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ var GCBBuilderIDs = []string{
"https://cloudbuild.googleapis.com/GoogleHostedWorker@v0.3",
}

var regionalKeyRegex = regexp.MustCompile(`^projects\/verified-builder\/locations\/(.*)\/keyRings\/attestor\/cryptoKeys\/builtByGCB\/cryptoKeyVersions\/1$`)

type v01IntotoStatement struct {
intoto.StatementHeader
Predicate ProvenancePredicate `json:"predicate"`
Expand Down Expand Up @@ -416,20 +418,35 @@ func (p *Provenance) verifySignatures(prov *provenance) error {
}

payloadHash := sha256.Sum256(payload)

// Verify the signatures.
if len(prov.Envelope.Signatures) == 0 {
return fmt.Errorf("%w: no signatures found in envelope", serrors.ErrorNoValidSignature)
}

var errs []error
regex := regexp.MustCompile(`^projects\/verified-builder\/locations\/(.*)\/keyRings\/attestor\/cryptoKeys\/builtByGCB\/cryptoKeyVersions\/1$`)

for _, sig := range prov.Envelope.Signatures {
match := regex.FindStringSubmatch(sig.KeyID)
if len(match) == 2 {
// Create a public key instance for this region.
region := match[1]
pubKey, err := keys.PublicKeyNew(region)
var region string
if sig.KeyID == keys.GlobalPAEKeyID {
// If the signature is signed with the global PAE key, use a DSSE verifier
// to verify the DSSE/PAE-encoded signature.
region = keys.GlobalPAEPublicKeyName
globalPaeKey, err := keys.NewGlobalPAEKey()
if err != nil {
errs = append(errs, err)
continue
}

err = globalPaeKey.VerifyPAESignature(&prov.Envelope)
if err != nil {
errs = append(errs, err)
continue
}
} else if match := regionalKeyRegex.FindStringSubmatch(sig.KeyID); len(match) == 2 {
// If the signature is signed with a regional key, verify the legacy
// signing which is over the envelope (not PAE-encoded).
region = match[1]
pubKey, err := keys.NewPublicKey(region)
if err != nil {
errs = append(errs, err)
continue
Expand All @@ -448,16 +465,18 @@ func (p *Provenance) verifySignatures(prov *provenance) error {
errs = append(errs, err)
continue
}
} else {
continue
}

var statement v01IntotoStatement
if err := json.Unmarshal(payload, &statement); err != nil {
return fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error())
}
p.verifiedIntotoStatement = &statement
p.verifiedProvenance = prov
fmt.Fprintf(os.Stderr, "Verification succeeded with region key '%s'\n", region)
return nil
var statement v01IntotoStatement
if err := json.Unmarshal(payload, &statement); err != nil {
return fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error())
}
p.verifiedIntotoStatement = &statement
p.verifiedProvenance = prov
fmt.Fprintf(os.Stderr, "Verification succeeded with region key '%s'\n", region)
return nil
}

return fmt.Errorf("%w: %v", serrors.ErrorNoValidSignature, errs)
Expand Down
20 changes: 18 additions & 2 deletions verifiers/internal/gcb/provenance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/slsa-framework/slsa-verifier/v2/verifiers/utils"
)

// This function sets the statement of the proveannce, as if
// This function sets the statement of the provenance, as if
// it had been verified. This is necessary because individual functions
// expect this statement to be populated; and this is done only
// after the signature is verified.
Expand Down Expand Up @@ -506,6 +506,10 @@ func Test_VerifySignature(t *testing.T) {
name: "valid gcb provenance",
path: "./testdata/gcloud-container-github.json",
},
{
name: "global gcb signing key",
path: "./testdata/gcloud-container-global-pae-signing-key-successful.json",
},
{
name: "invalid signature",
path: "./testdata/gcloud-container-invalid-signature.json",
Expand All @@ -516,6 +520,11 @@ func Test_VerifySignature(t *testing.T) {
path: "./testdata/gcloud-container-invalid-signature-payloadtype.json",
expected: serrors.ErrorNoValidSignature,
},
{
name: "invalid signature - global PAE key",
path: "./testdata/gcloud-container-invalid-signature-global-pae-key.json",
expected: serrors.ErrorNoValidSignature,
},
{
name: "invalid signature empty",
path: "./testdata/gcloud-container-empty-signature.json",
Expand Down Expand Up @@ -559,6 +568,10 @@ func Test_VerifySignature(t *testing.T) {
name: "signature multiple 3rd valid",
path: "./testdata/gcloud-container-multiple-signatures-3rdvalid.json",
},
{
name: "signature multiple global pae valid",
path: "./testdata/gcloud-container-multiple-signatures-global-pae-valid.json",
},
}
for _, tt := range tests {
tt := tt // Re-initializing variable so it is not changed while executing the closure below
Expand All @@ -578,7 +591,6 @@ func Test_VerifySignature(t *testing.T) {
if err := setStatement(prov); err != nil {
panic(fmt.Errorf("setStatement: %w", err))
}

err = prov.VerifySignature()
if !cmp.Equal(err, tt.expected, cmpopts.EquateErrors()) {
t.Errorf(cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
Expand Down Expand Up @@ -799,6 +811,10 @@ func Test_VerifyTextProvenance(t *testing.T) {
name: "valid gcb provenance",
path: "./testdata/gcloud-container-github.json",
},
{
name: "valid gcb provenance with global signing key",
path: "./testdata/gcloud-container-global-pae-signing-key-successful.json",
},
{
name: "mismatch everything",
path: "./testdata/gcloud-container-github.json",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"image_summary": {
"digest": "sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4",
"fully_qualified_digest": "us-central1-docker.pkg.dev/argo-local-khalk/khalk-docker-ar/tagged-world-trigger-964a2eba-62f0-4a53-87d3-4e6dddcc70b3@sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4",
"registry": "us-central1-docker.pkg.dev",
"repository": "khalk-docker-ar"
},
"provenance_summary": {
"provenance": [
{
"build": {
"intotoStatement": {
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.1",
"slsaProvenance": {
"builder": {
"id": "https://cloudbuild.googleapis.com/GoogleHostedWorker@v0.3"
},
"materials": [
{
"digest": {
"sha1": "75c21a6224914056801d5be2316d89de3ff24811"
},
"uri": "git+https://github.com/khalkie/gcb-repo-staging"
}
],
"metadata": {
"buildFinishedOn": "2023-02-28T15:23:37.764882Z",
"buildInvocationId": "964a2eba-62f0-4a53-87d3-4e6dddcc70b3",
"buildStartedOn": "2023-02-28T15:23:26.521812356Z"
},
"recipe": {
"arguments": {
"@type": "type.googleapis.com/google.devtools.cloudbuild.v1.Build",
"id": "964a2eba-62f0-4a53-87d3-4e6dddcc70b3",
"name": "projects/265426041527/locations/us-west1/builds/964a2eba-62f0-4a53-87d3-4e6dddcc70b3",
"options": {
"dynamicSubstitutions": true,
"logging": "LEGACY",
"pool": {},
"requestedVerifyOption": "VERIFIED",
"substitutionOption": "ALLOW_LOOSE"
},
"sourceProvenance": {},
"steps": [
{
"args": [
"tag",
"hello-world",
"us-central1-docker.pkg.dev/argo-local-khalk/khalk-docker-ar/tagged-world-trigger-964a2eba-62f0-4a53-87d3-4e6dddcc70b3"
],
"name": "gcr.io/cloud-builders/docker",
"pullTiming": {
"endTime": "2023-02-28T15:23:34.662245150Z",
"startTime": "2023-02-28T15:23:34.654151260Z"
},
"status": "SUCCESS",
"timing": {
"endTime": "2023-02-28T15:23:35.584468354Z",
"startTime": "2023-02-28T15:23:34.654151260Z"
}
}
],
"substitutions": {
"BRANCH_NAME": "main",
"COMMIT_SHA": "75c21a6224914056801d5be2316d89de3ff24811",
"REF_NAME": "main",
"REPO_NAME": "gcb-repo-staging",
"REVISION_ID": "75c21a6224914056801d5be2316d89de3ff24811",
"SHORT_SHA": "75c21a6",
"TRIGGER_BUILD_CONFIG_PATH": "cloudbuild.yaml",
"TRIGGER_NAME": "github-trigger-staging"
}
},
"entryPoint": "cloudbuild.yaml",
"type": "https://cloudbuild.googleapis.com/CloudBuildYaml@v0.1"
}
},
"subject": [
{
"digest": {
"sha256": "f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4"
},
"name": "https://us-central1-docker.pkg.dev/argo-local-khalk/khalk-docker-ar/tagged-world-trigger-964a2eba-62f0-4a53-87d3-4e6dddcc70b3"
},
{
"digest": {
"sha256": "f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4"
},
"name": "https://us-central1-docker.pkg.dev/argo-local-khalk/khalk-docker-ar/tagged-world-trigger-964a2eba-62f0-4a53-87d3-4e6dddcc70b3:latest"
}
]
}
},
"createTime": "2023-02-28T15:23:39.650659Z",
"envelope": {
"payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZSI6eyJidWlsZGVyIjp7ImlkIjoiaHR0cHM6Ly9jbG91ZGJ1aWxkLmdvb2dsZWFwaXMuY29tL0dvb2dsZUhvc3RlZFdvcmtlckB2MC4zIn0sIm1hdGVyaWFscyI6W3siZGlnZXN0Ijp7InNoYTEiOiI3NWMyMWE2MjI0OTE0MDU2ODAxZDViZTIzMTZkODlkZTNmZjI0ODExIn0sInVyaSI6ImdpdCtodHRwczovL2dpdGh1Yi5jb20va2hhbGtpZS9nY2ItcmVwby1zdGFnaW5nIn1dLCJtZXRhZGF0YSI6eyJidWlsZEZpbmlzaGVkT24iOiIyMDIzLTAyLTI4VDE1OjIzOjM3Ljc2NDg4MloiLCJidWlsZEludm9jYXRpb25JZCI6Ijk2NGEyZWJhLTYyZjAtNGE1My04N2QzLTRlNmRkZGNjNzBiMyIsImJ1aWxkU3RhcnRlZE9uIjoiMjAyMy0wMi0yOFQxNToyMzoyNi41MjE4MTIzNTZaIn0sInJlY2lwZSI6eyJhcmd1bWVudHMiOnsiQHR5cGUiOiJ0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5kZXZ0b29scy5jbG91ZGJ1aWxkLnYxLkJ1aWxkIiwiaWQiOiI5NjRhMmViYS02MmYwLTRhNTMtODdkMy00ZTZkZGRjYzcwYjMiLCJuYW1lIjoicHJvamVjdHMvMjY1NDI2MDQxNTI3L2xvY2F0aW9ucy91cy13ZXN0MS9idWlsZHMvOTY0YTJlYmEtNjJmMC00YTUzLTg3ZDMtNGU2ZGRkY2M3MGIzIiwib3B0aW9ucyI6eyJkeW5hbWljU3Vic3RpdHV0aW9ucyI6dHJ1ZSwibG9nZ2luZyI6IkxFR0FDWSIsInBvb2wiOnt9LCJyZXF1ZXN0ZWRWZXJpZnlPcHRpb24iOiJWRVJJRklFRCIsInN1YnN0aXR1dGlvbk9wdGlvbiI6IkFMTE9XX0xPT1NFIn0sInNvdXJjZVByb3ZlbmFuY2UiOnt9LCJzdGVwcyI6W3siYXJncyI6WyJ0YWciLCJoZWxsby13b3JsZCIsInVzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L2FyZ28tbG9jYWwta2hhbGsva2hhbGstZG9ja2VyLWFyL3RhZ2dlZC13b3JsZC10cmlnZ2VyLTk2NGEyZWJhLTYyZjAtNGE1My04N2QzLTRlNmRkZGNjNzBiMyJdLCJuYW1lIjoiZ2NyLmlvL2Nsb3VkLWJ1aWxkZXJzL2RvY2tlciIsInB1bGxUaW1pbmciOnsiZW5kVGltZSI6IjIwMjMtMDItMjhUMTU6MjM6MzQuNjYyMjQ1MTUwWiIsInN0YXJ0VGltZSI6IjIwMjMtMDItMjhUMTU6MjM6MzQuNjU0MTUxMjYwWiJ9LCJzdGF0dXMiOiJTVUNDRVNTIiwidGltaW5nIjp7ImVuZFRpbWUiOiIyMDIzLTAyLTI4VDE1OjIzOjM1LjU4NDQ2ODM1NFoiLCJzdGFydFRpbWUiOiIyMDIzLTAyLTI4VDE1OjIzOjM0LjY1NDE1MTI2MFoifX1dLCJzdWJzdGl0dXRpb25zIjp7IkJSQU5DSF9OQU1FIjoibWFpbiIsIkNPTU1JVF9TSEEiOiI3NWMyMWE2MjI0OTE0MDU2ODAxZDViZTIzMTZkODlkZTNmZjI0ODExIiwiUkVGX05BTUUiOiJtYWluIiwiUkVQT19OQU1FIjoiZ2NiLXJlcG8tc3RhZ2luZyIsIlJFVklTSU9OX0lEIjoiNzVjMjFhNjIyNDkxNDA1NjgwMWQ1YmUyMzE2ZDg5ZGUzZmYyNDgxMSIsIlNIT1JUX1NIQSI6Ijc1YzIxYTYiLCJUUklHR0VSX0JVSUxEX0NPTkZJR19QQVRIIjoiY2xvdWRidWlsZC55YW1sIiwiVFJJR0dFUl9OQU1FIjoiZ2l0aHViLXRyaWdnZXItc3RhZ2luZyJ9fSwiZW50cnlQb2ludCI6ImNsb3VkYnVpbGQueWFtbCIsInR5cGUiOiJodHRwczovL2Nsb3VkYnVpbGQuZ29vZ2xlYXBpcy5jb20vQ2xvdWRCdWlsZFlhbWxAdjAuMSJ9fSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4xIiwic2xzYVByb3ZlbmFuY2UiOnsiYnVpbGRlciI6eyJpZCI6Imh0dHBzOi8vY2xvdWRidWlsZC5nb29nbGVhcGlzLmNvbS9Hb29nbGVIb3N0ZWRXb3JrZXJAdjAuMyJ9LCJtYXRlcmlhbHMiOlt7ImRpZ2VzdCI6eyJzaGExIjoiNzVjMjFhNjIyNDkxNDA1NjgwMWQ1YmUyMzE2ZDg5ZGUzZmYyNDgxMSJ9LCJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2toYWxraWUvZ2NiLXJlcG8tc3RhZ2luZyJ9XSwibWV0YWRhdGEiOnsiYnVpbGRGaW5pc2hlZE9uIjoiMjAyMy0wMi0yOFQxNToyMzozNy43NjQ4ODJaIiwiYnVpbGRJbnZvY2F0aW9uSWQiOiI5NjRhMmViYS02MmYwLTRhNTMtODdkMy00ZTZkZGRjYzcwYjMiLCJidWlsZFN0YXJ0ZWRPbiI6IjIwMjMtMDItMjhUMTU6MjM6MjYuNTIxODEyMzU2WiJ9LCJyZWNpcGUiOnsiYXJndW1lbnRzIjp7IkB0eXBlIjoidHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuZGV2dG9vbHMuY2xvdWRidWlsZC52MS5CdWlsZCIsImlkIjoiOTY0YTJlYmEtNjJmMC00YTUzLTg3ZDMtNGU2ZGRkY2M3MGIzIiwibmFtZSI6InByb2plY3RzLzI2NTQyNjA0MTUyNy9sb2NhdGlvbnMvdXMtd2VzdDEvYnVpbGRzLzk2NGEyZWJhLTYyZjAtNGE1My04N2QzLTRlNmRkZGNjNzBiMyIsIm9wdGlvbnMiOnsiZHluYW1pY1N1YnN0aXR1dGlvbnMiOnRydWUsImxvZ2dpbmciOiJMRUdBQ1kiLCJwb29sIjp7fSwicmVxdWVzdGVkVmVyaWZ5T3B0aW9uIjoiVkVSSUZJRUQiLCJzdWJzdGl0dXRpb25PcHRpb24iOiJBTExPV19MT09TRSJ9LCJzb3VyY2VQcm92ZW5hbmNlIjp7fSwic3RlcHMiOlt7ImFyZ3MiOlsidGFnIiwiaGVsbG8td29ybGQiLCJ1cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9hcmdvLWxvY2FsLWtoYWxrL2toYWxrLWRvY2tlci1hci90YWdnZWQtd29ybGQtdHJpZ2dlci05NjRhMmViYS02MmYwLTRhNTMtODdkMy00ZTZkZGRjYzcwYjMiXSwibmFtZSI6Imdjci5pby9jbG91ZC1idWlsZGVycy9kb2NrZXIiLCJwdWxsVGltaW5nIjp7ImVuZFRpbWUiOiIyMDIzLTAyLTI4VDE1OjIzOjM0LjY2MjI0NTE1MFoiLCJzdGFydFRpbWUiOiIyMDIzLTAyLTI4VDE1OjIzOjM0LjY1NDE1MTI2MFoifSwic3RhdHVzIjoiU1VDQ0VTUyIsInRpbWluZyI6eyJlbmRUaW1lIjoiMjAyMy0wMi0yOFQxNToyMzozNS41ODQ0NjgzNTRaIiwic3RhcnRUaW1lIjoiMjAyMy0wMi0yOFQxNToyMzozNC42NTQxNTEyNjBaIn19XSwic3Vic3RpdHV0aW9ucyI6eyJCUkFOQ0hfTkFNRSI6Im1haW4iLCJDT01NSVRfU0hBIjoiNzVjMjFhNjIyNDkxNDA1NjgwMWQ1YmUyMzE2ZDg5ZGUzZmYyNDgxMSIsIlJFRl9OQU1FIjoibWFpbiIsIlJFUE9fTkFNRSI6ImdjYi1yZXBvLXN0YWdpbmciLCJSRVZJU0lPTl9JRCI6Ijc1YzIxYTYyMjQ5MTQwNTY4MDFkNWJlMjMxNmQ4OWRlM2ZmMjQ4MTEiLCJTSE9SVF9TSEEiOiI3NWMyMWE2IiwiVFJJR0dFUl9CVUlMRF9DT05GSUdfUEFUSCI6ImNsb3VkYnVpbGQueWFtbCIsIlRSSUdHRVJfTkFNRSI6ImdpdGh1Yi10cmlnZ2VyLXN0YWdpbmcifX0sImVudHJ5UG9pbnQiOiJjbG91ZGJ1aWxkLnlhbWwiLCJ0eXBlIjoiaHR0cHM6Ly9jbG91ZGJ1aWxkLmdvb2dsZWFwaXMuY29tL0Nsb3VkQnVpbGRZYW1sQHYwLjEifX0sInN1YmplY3QiOlt7ImRpZ2VzdCI6eyJzaGEyNTYiOiJmNTRhNThiYzFhYWM1ZWExYTI1ZDc5NmFlMTU1ZGMyMjhiM2YwZTExZDA0NmFlMjc2YjM5YzRiZjJmMTNkOGM0In0sIm5hbWUiOiJodHRwczovL3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L2FyZ28tbG9jYWwta2hhbGsva2hhbGstZG9ja2VyLWFyL3RhZ2dlZC13b3JsZC10cmlnZ2VyLTk2NGEyZWJhLTYyZjAtNGE1My04N2QzLTRlNmRkZGNjNzBiMyJ9LHsiZGlnZXN0Ijp7InNoYTI1NiI6ImY1NGE1OGJjMWFhYzVlYTFhMjVkNzk2YWUxNTVkYzIyOGIzZjBlMTFkMDQ2YWUyNzZiMzljNGJmMmYxM2Q4YzQifSwibmFtZSI6Imh0dHBzOi8vdXMtY2VudHJhbDEtZG9ja2VyLnBrZy5kZXYvYXJnby1sb2NhbC1raGFsay9raGFsay1kb2NrZXItYXIvdGFnZ2VkLXdvcmxkLXRyaWdnZXItOTY0YTJlYmEtNjJmMC00YTUzLTg3ZDMtNGU2ZGRkY2M3MGIzOmxhdGVzdCJ9XX0=",
"payloadType": "application/vnd.in-toto+json",
"signatures": [
{
"keyid": "projects/verified-builder/locations/global/keyRings/attestor/cryptoKeys/provenanceSigner/cryptoKeyVersions/1",
"sig": "MEUCIQCJQRkaJuajYy_KKV71VYS13QLdp57pAdQMVXucy3Ev-wIgBCcaPtO16_WWhRrPWVpxrTxtypNVLAqIVeywNYk2-Xk="
}
]
},
"kind": "BUILD",
"name": "projects/argo-local-khalk/occurrences/26a014ac-3779-4a0b-98da-2d804f257f3d",
"noteName": "projects/argo-qa/notes/intoto_964a2eba-62f0-4a53-87d3-4e6dddcc70b3",
"resourceUri": "https://us-central1-docker.pkg.dev/argo-local-khalk/khalk-docker-ar/tagged-world-trigger-964a2eba-62f0-4a53-87d3-4e6dddcc70b3@sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4",
"updateTime": "2023-02-28T15:23:39.650659Z"
}
]
}
}
Loading

0 comments on commit 47495c7

Please sign in to comment.