diff --git a/cmd/witness/cmd/keyloader.go b/cmd/witness/cmd/keyloader.go new file mode 100644 index 00000000..a2a3664d --- /dev/null +++ b/cmd/witness/cmd/keyloader.go @@ -0,0 +1,66 @@ +// Copyright 2022 The Witness Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "context" + "fmt" + + "github.com/testifysec/witness/cmd/witness/options" + "github.com/testifysec/witness/pkg/cryptoutil" + "github.com/testifysec/witness/pkg/signer/file" + "github.com/testifysec/witness/pkg/signer/fulcio" + "github.com/testifysec/witness/pkg/signer/spiffe" +) + +func loadSigners(ctx context.Context, ko options.KeyOptions) ([]cryptoutil.Signer, []error) { + signers := []cryptoutil.Signer{} + errors := []error{} + + //Load key from fulcio + if ko.FulcioURL != "" { + fulcioSigner, err := fulcio.Signer(ctx, ko.FulcioURL, ko.OIDCClientID, ko.OIDCIssuer) + if err != nil { + err := fmt.Errorf("failed to create signer from Fulcio: %w", err) + errors = append(errors, err) + } else { + signers = append(signers, fulcioSigner) + } + } + + //Load key from file + if ko.KeyPath != "" { + fileSigner, err := file.Signer(ctx, ko.KeyPath, ko.CertPath, ko.IntermediatePaths) + if err != nil { + err := fmt.Errorf("failed to create signer from file: %w", err) + errors = append(errors, err) + } else { + signers = append(signers, fileSigner) + } + } + + //Load key from spire agent + if ko.SpiffePath != "" { + spiffeSigner, err := spiffe.Signer(ctx, ko.SpiffePath) + if err != nil { + err := fmt.Errorf("failed to create signer from spiffe: %w", err) + errors = append(errors, err) + } else { + signers = append(signers, spiffeSigner) + } + } + + return signers, errors +} diff --git a/cmd/witness/cmd/root.go b/cmd/witness/cmd/root.go index 2c28c49e..d668b6f7 100644 --- a/cmd/witness/cmd/root.go +++ b/cmd/witness/cmd/root.go @@ -15,16 +15,12 @@ package cmd import ( - "context" "fmt" "os" "github.com/spf13/cobra" "github.com/testifysec/witness/cmd/witness/options" - "github.com/testifysec/witness/pkg/cryptoutil" "github.com/testifysec/witness/pkg/log" - "github.com/testifysec/witness/pkg/signer/file" - "github.com/testifysec/witness/pkg/signer/spiffe" ) var ( @@ -67,31 +63,6 @@ func preRoot(cmd *cobra.Command, ro *options.RootOptions) { } } -func loadSigners(ctx context.Context, ko options.KeyOptions) ([]cryptoutil.Signer, []error) { - signers := []cryptoutil.Signer{} - errors := []error{} - - if ko.SpiffePath != "" { - s, err := spiffe.Signer(ctx, ko.SpiffePath) - if err != nil { - errors = append(errors, fmt.Errorf("failed to create signer: %v", err)) - } else { - signers = append(signers, s) - } - } - - if ko.KeyPath != "" { - s, err := file.Signer(ctx, ko.KeyPath, ko.CertPath, ko.IntermediatePaths) - if err != nil { - errors = append(errors, fmt.Errorf("failed to create signer: %v", err)) - } else { - signers = append(signers, s) - } - } - - return signers, errors -} - func loadOutfile(outFilePath string) (*os.File, error) { var err error out := os.Stdout diff --git a/cmd/witness/cmd/run.go b/cmd/witness/cmd/run.go index 1c8dad17..965b2a14 100644 --- a/cmd/witness/cmd/run.go +++ b/cmd/witness/cmd/run.go @@ -46,6 +46,7 @@ func RunCmd() *cobra.Command { func runRun(ro options.RunOptions, args []string) error { ctx := context.Background() + signers, errors := loadSigners(ctx, ro.KeyOptions) if len(errors) > 0 { for _, err := range errors { diff --git a/cmd/witness/cmd/sign.go b/cmd/witness/cmd/sign.go index e319b06f..e8f58c2d 100644 --- a/cmd/witness/cmd/sign.go +++ b/cmd/witness/cmd/sign.go @@ -47,6 +47,12 @@ func SignCmd() *cobra.Command { //we need to abstract where keys are coming from, etc func runSign(so options.SignOptions) error { ctx := context.Background() + + if so.KeyOptions.FulcioURL != "" { + err := fmt.Errorf("fulcio url is not supported for signing") + return err + } + signers, errors := loadSigners(ctx, so.KeyOptions) if len(errors) > 0 { for _, err := range errors { diff --git a/cmd/witness/cmd/verify.go b/cmd/witness/cmd/verify.go index 2bdebe5c..e7d7df7e 100644 --- a/cmd/witness/cmd/verify.go +++ b/cmd/witness/cmd/verify.go @@ -55,15 +55,24 @@ const ( //todo: this logic should be broken out and moved to pkg/ //we need to abstract where keys are coming from, etc func runVerify(vo options.VerifyOptions, args []string) error { - keyFile, err := os.Open(vo.KeyPath) - if err != nil { - return fmt.Errorf("failed to open key file: %v", err) + if vo.KeyPath == "" && len(vo.CAPaths) == 0 { + return fmt.Errorf("must suply public key or ca paths") } - defer keyFile.Close() - verifier, err := cryptoutil.NewVerifierFromReader(keyFile) - if err != nil { - return fmt.Errorf("failed to load key: %v", err) + var verifier cryptoutil.Verifier + + if vo.KeyPath != "" { + keyFile, err := os.Open(vo.KeyPath) + if err != nil { + return fmt.Errorf("failed to open key file: %w", err) + } + defer keyFile.Close() + + verifier, err = cryptoutil.NewVerifierFromReader(keyFile) + if err != nil { + return fmt.Errorf("failed to create verifier: %w", err) + } + } inFile, err := os.Open(vo.PolicyFilePath) diff --git a/cmd/witness/cmd/verify_test.go b/cmd/witness/cmd/verify_test.go index 58926807..1c1a8b87 100644 --- a/cmd/witness/cmd/verify_test.go +++ b/cmd/witness/cmd/verify_test.go @@ -17,17 +17,110 @@ package cmd import ( "bytes" "encoding/json" + "io/ioutil" "os" + "path/filepath" "testing" "time" + "github.com/stretchr/testify/require" "github.com/testifysec/witness/cmd/witness/options" witness "github.com/testifysec/witness/pkg" "github.com/testifysec/witness/pkg/attestation/commandrun" + "github.com/testifysec/witness/pkg/cryptoutil" "github.com/testifysec/witness/pkg/dsse" "github.com/testifysec/witness/pkg/policy" ) +func Test_RunVerifyCA(t *testing.T) { + ca, intermediates, leafcert, leafkey := fullChain(t) + + ko := options.KeyOptions{ + KeyPath: leafkey.Name(), + IntermediatePaths: []string{ + intermediates[0].Name(), + }, + CertPath: leafcert.Name(), + } + + caBytes, err := ioutil.ReadFile(ca.Name()) + require.NoError(t, err) + + policy := makepolicyCA(t, caBytes) + signedPolicy, pub := signPolicyRSA(t, policy) + + workingDir := t.TempDir() + attestationDir := t.TempDir() + + err = os.WriteFile(filepath.Join(workingDir, "signed-policy.json"), signedPolicy, 0644) + if err != nil { + t.Error(err) + } + + err = os.WriteFile(filepath.Join(workingDir, "policy-pub.pem"), pub, 0644) + if err != nil { + t.Error(err) + } + + step1Args := []string{ + "bash", + "-c", + "echo 'test01' > test.txt", + } + + s1RunOptions := options.RunOptions{ + KeyOptions: ko, + WorkingDir: workingDir, + Attestations: []string{}, + OutFilePath: filepath.Join(attestationDir, "step01.json"), + StepName: "step01", + RekorServer: "", + Tracing: false, + } + + err = runRun(s1RunOptions, step1Args) + if err != nil { + t.Error(err) + } + + step2Args := []string{ + "bash", + "-c", + "echo 'test02' >> test.txt", + } + + s2RunOptions := options.RunOptions{ + KeyOptions: ko, + WorkingDir: workingDir, + Attestations: []string{}, + OutFilePath: filepath.Join(attestationDir, "step02.json"), + StepName: "step02", + RekorServer: "", + Tracing: false, + } + + err = runRun(s2RunOptions, step2Args) + if err != nil { + t.Error(err) + } + + vo := options.VerifyOptions{ + KeyPath: filepath.Join(workingDir, "policy-pub.pem"), + AttestationFilePaths: []string{filepath.Join(attestationDir, "step01.json"), filepath.Join(attestationDir, "step02.json")}, + PolicyFilePath: filepath.Join(workingDir, "signed-policy.json"), + ArtifactFilePath: filepath.Join(workingDir, "test.txt"), + RekorServer: "", + + EmailContstraints: []string{}, + } + + err = runVerify(vo, []string{}) + if err != nil { + t.Error(err) + } + +} + func Test_loadEnvelopesFromDisk(t *testing.T) { testPayload := []byte("test") @@ -49,13 +142,13 @@ func Test_loadEnvelopesFromDisk(t *testing.T) { t.Error(err) } - err = os.WriteFile(workingDir+"envelope.txt", jsonEnvelope, 0644) + err = os.WriteFile(filepath.Join(workingDir, "envelope.txt"), jsonEnvelope, 0644) if err != nil { t.Error(err) } - envelopes, err := loadEnvelopesFromDisk([]string{workingDir + "envelope.txt"}) + envelopes, err := loadEnvelopesFromDisk([]string{filepath.Join(workingDir, "envelope.txt")}) if err != nil { t.Error(err) } @@ -75,38 +168,32 @@ func Test_loadEnvelopesFromDisk(t *testing.T) { if len(envelopes[0].Envelope.Signatures) != 0 { t.Errorf("expected 0 signatures, got %d", len(envelopes[0].Envelope.Signatures)) } - - err = os.RemoveAll("/tmp/witness") - if err != nil { - t.Error(err) - } - } func Test_RunVerifyKeyPair(t *testing.T) { policy, funcPriv := makepolicyRSAPub(t) - signedPolicy, pub := signPolicy(t, policy) + signedPolicy, pub := signPolicyRSA(t, policy) workingDir := t.TempDir() attestationDir := t.TempDir() - err := os.WriteFile(workingDir+"signed-policy.json", signedPolicy, 0644) + err := os.WriteFile(filepath.Join(workingDir, "signed-policy.json"), signedPolicy, 0644) if err != nil { t.Error(err) } - err = os.WriteFile(workingDir+"policy-pub.pem", pub, 0644) + err = os.WriteFile(filepath.Join(workingDir, "policy-pub.pem"), pub, 0644) if err != nil { t.Error(err) } - err = os.WriteFile(workingDir+"func-priv.pem", funcPriv, 0644) + err = os.WriteFile(filepath.Join(workingDir, "func-priv.pem"), funcPriv, 0644) if err != nil { t.Error(err) } keyOptions := options.KeyOptions{ - KeyPath: workingDir + "func-priv.pem", + KeyPath: filepath.Join(workingDir, "func-priv.pem"), } step1Args := []string{ @@ -119,7 +206,7 @@ func Test_RunVerifyKeyPair(t *testing.T) { KeyOptions: keyOptions, WorkingDir: workingDir, Attestations: []string{}, - OutFilePath: attestationDir + "step01.json", + OutFilePath: filepath.Join(attestationDir, "step01.json"), StepName: "step01", RekorServer: "", Tracing: false, @@ -140,7 +227,7 @@ func Test_RunVerifyKeyPair(t *testing.T) { KeyOptions: keyOptions, WorkingDir: workingDir, Attestations: []string{}, - OutFilePath: attestationDir + "step02.json", + OutFilePath: filepath.Join(attestationDir, "step02.json"), StepName: "step02", RekorServer: "", Tracing: false, @@ -152,10 +239,10 @@ func Test_RunVerifyKeyPair(t *testing.T) { } vo := options.VerifyOptions{ - KeyPath: workingDir + "policy-pub.pem", - AttestationFilePaths: []string{attestationDir + "step01.json", attestationDir + "step02.json"}, - PolicyFilePath: workingDir + "signed-policy.json", - ArtifactFilePath: workingDir + "test.txt", + KeyPath: filepath.Join(workingDir, "policy-pub.pem"), + AttestationFilePaths: []string{filepath.Join(attestationDir, "step01.json"), filepath.Join(attestationDir, "step02.json")}, + PolicyFilePath: filepath.Join(workingDir, "signed-policy.json"), + ArtifactFilePath: filepath.Join(workingDir, "test.txt"), RekorServer: "", } @@ -166,7 +253,7 @@ func Test_RunVerifyKeyPair(t *testing.T) { } -func signPolicy(t *testing.T, p []byte) (signedPolicy []byte, pub []byte) { +func signPolicyRSA(t *testing.T, p []byte) (signedPolicy []byte, pub []byte) { sign, _, pub, _, err := createTestRSAKey() if err != nil { t.Error(err) @@ -185,6 +272,40 @@ func signPolicy(t *testing.T, p []byte) (signedPolicy []byte, pub []byte) { return writer.Bytes(), pub } +func makepolicyCA(t *testing.T, ca []byte) []byte { + + r := bytes.NewReader(ca) + + verifier, err := cryptoutil.NewVerifierFromReader(r) + require.NoError(t, err) + + keyID, err := verifier.KeyID() + require.NoError(t, err) + + functionary := policy.Functionary{ + Type: "root", + CertConstraint: policy.CertConstraint{ + CommonName: "*", + DNSNames: []string{"*"}, + Emails: []string{"*"}, + Organizations: []string{"*"}, + URIs: []string{"*"}, + Roots: []string{keyID}, + }, + } + + root := policy.Root{ + Certificate: ca, + } + + roots := map[string]policy.Root{} + + roots[keyID] = root + + policy := makepolicy(t, functionary, policy.PublicKey{}, roots) + return policy +} + func makepolicyRSAPub(t *testing.T) ([]byte, []byte) { _, ver, pub, fpriv, err := createTestRSAKey() if err != nil { @@ -206,13 +327,11 @@ func makepolicyRSAPub(t *testing.T) ([]byte, []byte) { Key: pub, } - root := policy.Root{} - - p := makepolicy(t, functionary, pk, root) + p := makepolicy(t, functionary, pk, nil) return p, fpriv } -func makepolicy(t *testing.T, functionary policy.Functionary, publicKey policy.PublicKey, root policy.Root) []byte { +func makepolicy(t *testing.T, functionary policy.Functionary, publicKey policy.PublicKey, roots map[string]policy.Root) []byte { step01 := policy.Step{ Name: "step01", Functionaries: []policy.Functionary{functionary}, @@ -233,15 +352,19 @@ func makepolicy(t *testing.T, functionary policy.Functionary, publicKey policy.P } if functionary.CertConstraint.Roots != nil { - keyID := functionary.CertConstraint.Roots[0] - p.Roots[keyID] = root + p.Roots = roots } p.Steps = make(map[string]policy.Step) p.Steps[step01.Name] = step01 p.Steps[step02.Name] = step02 - p.PublicKeys[publicKey.KeyID] = publicKey + if publicKey.KeyID != "" { + + p.PublicKeys[publicKey.KeyID] = publicKey + + } + pb, err := json.MarshalIndent(p, "", " ") if err != nil { t.Error(err) diff --git a/cmd/witness/options/key.go b/cmd/witness/options/key.go index c8d9256e..96e7a896 100644 --- a/cmd/witness/options/key.go +++ b/cmd/witness/options/key.go @@ -21,6 +21,9 @@ type KeyOptions struct { CertPath string IntermediatePaths []string SpiffePath string + FulcioURL string + OIDCIssuer string + OIDCClientID string } func (ko *KeyOptions) AddFlags(cmd *cobra.Command) { @@ -28,4 +31,7 @@ func (ko *KeyOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&ko.CertPath, "certificate", "", "Path to the signing key's certificate") cmd.Flags().StringSliceVarP(&ko.IntermediatePaths, "intermediates", "i", []string{}, "Intermediates that link trust back to a root in the policy") cmd.Flags().StringVar(&ko.SpiffePath, "spiffe-socket", "", "Path to the SPIFFE Workload API socket") + cmd.Flags().StringVar(&ko.FulcioURL, "fulcio", "", "Fulcio address to sign with") + cmd.Flags().StringVar(&ko.OIDCIssuer, "fulcio-oidc-issuer", "", "OIDC issuer to use for authentication") + cmd.Flags().StringVar(&ko.OIDCClientID, "fulcio-oidc-client-id", "", "OIDC client ID to use for authentication") } diff --git a/cmd/witness/options/verify.go b/cmd/witness/options/verify.go index dc5cc17c..c4d4304d 100644 --- a/cmd/witness/options/verify.go +++ b/cmd/witness/options/verify.go @@ -22,6 +22,8 @@ type VerifyOptions struct { PolicyFilePath string ArtifactFilePath string RekorServer string + CAPaths []string + EmailContstraints []string } func (vo *VerifyOptions) AddFlags(cmd *cobra.Command) { @@ -30,4 +32,5 @@ func (vo *VerifyOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVarP(&vo.PolicyFilePath, "policy", "p", "", "Path to the policy to verify") cmd.Flags().StringVarP(&vo.ArtifactFilePath, "artifactfile", "f", "", "Path to the artifact to verify") cmd.Flags().StringVarP(&vo.RekorServer, "rekor-server", "r", "", "Rekor server to fetch attestations from") + cmd.Flags().StringSliceVarP(&vo.CAPaths, "policy-ca", "", []string{}, "Paths to CA certificates to use for verifying the policy") } diff --git a/docs/witness_run.md b/docs/witness_run.md index 9b61019f..f1911160 100644 --- a/docs/witness_run.md +++ b/docs/witness_run.md @@ -9,17 +9,20 @@ witness run [cmd] [flags] ### Options ``` - -a, --attestations strings Attestations to record (default [environment,git]) - --certificate string Path to the signing key's certificate - -h, --help help for run - -i, --intermediates strings Intermediates that link trust back to a root in the policy - -k, --key string Path to the signing key - -o, --outfile string File to write signed data. Defaults to stdout - -r, --rekor-server string Rekor server to store attestations - --spiffe-socket string Path to the SPIFFE Workload API socket - -s, --step string Name of the step being run - --trace enable tracing for the command - -d, --workingdir string Directory that commands will be run from + -a, --attestations strings Attestations to record (default [environment,git]) + --certificate string Path to the signing key's certificate + --fulcio string Fulcio address to sign with + --fulcio-oidc-client-id string OIDC client ID to use for authentication + --fulcio-oidc-issuer string OIDC issuer to use for authentication + -h, --help help for run + -i, --intermediates strings Intermediates that link trust back to a root in the policy + -k, --key string Path to the signing key + -o, --outfile string File to write signed data. Defaults to stdout + -r, --rekor-server string Rekor server to store attestations + --spiffe-socket string Path to the SPIFFE Workload API socket + -s, --step string Name of the step being run + --trace enable tracing for the command + -d, --workingdir string Directory that commands will be run from ``` ### Options inherited from parent commands diff --git a/docs/witness_sign.md b/docs/witness_sign.md index b01748ad..064677c9 100644 --- a/docs/witness_sign.md +++ b/docs/witness_sign.md @@ -13,14 +13,17 @@ witness sign [file] [flags] ### Options ``` - --certificate string Path to the signing key's certificate - -t, --datatype string The URI reference to the type of data being signed. Defaults to the Witness policy type (default "https://witness.testifysec.com/policy/v0.1") - -h, --help help for sign - -f, --infile string Witness policy file to sign - -i, --intermediates strings Intermediates that link trust back to a root in the policy - -k, --key string Path to the signing key - -o, --outfile string File to write signed data. Defaults to stdout - --spiffe-socket string Path to the SPIFFE Workload API socket + --certificate string Path to the signing key's certificate + -t, --datatype string The URI reference to the type of data being signed. Defaults to the Witness policy type (default "https://witness.testifysec.com/policy/v0.1") + --fulcio string Fulcio address to sign with + --fulcio-oidc-client-id string OIDC client ID to use for authentication + --fulcio-oidc-issuer string OIDC issuer to use for authentication + -h, --help help for sign + -f, --infile string Witness policy file to sign + -i, --intermediates strings Intermediates that link trust back to a root in the policy + -k, --key string Path to the signing key + -o, --outfile string File to write signed data. Defaults to stdout + --spiffe-socket string Path to the SPIFFE Workload API socket ``` ### Options inherited from parent commands diff --git a/docs/witness_verify.md b/docs/witness_verify.md index 4cbe5da1..92025364 100644 --- a/docs/witness_verify.md +++ b/docs/witness_verify.md @@ -17,6 +17,7 @@ witness verify [flags] -a, --attestations strings Attestation files to test against the policy -h, --help help for verify -p, --policy string Path to the policy to verify + --policy-ca strings Paths to CA certificates to use for verifying the policy -k, --publickey string Path to the policy signer's public key -r, --rekor-server string Rekor server to fetch attestations from ``` diff --git a/go.mod b/go.mod index 077c6813..2d487c74 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/go-git/go-git/v5 v5.4.2 github.com/go-openapi/runtime v0.23.1 - github.com/open-policy-agent/opa v0.37.0 + github.com/open-policy-agent/opa v0.38.0 github.com/owenrumney/go-sarif v1.1.1 github.com/sigstore/rekor v0.4.1-0.20220114213500-23f583409af3 github.com/sirupsen/logrus v1.8.1 @@ -16,22 +16,27 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.10.1 github.com/spiffe/go-spiffe/v2 v2.0.0-beta.12 - github.com/stretchr/testify v1.7.0 - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 + github.com/stretchr/testify v1.7.1 + golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 google.golang.org/grpc v1.44.0 gopkg.in/square/go-jose.v2 v2.6.0 ) require ( github.com/CycloneDX/cyclonedx-go v0.4.0 // indirect + github.com/PaesslerAG/gval v1.0.0 // indirect + github.com/PaesslerAG/jsonpath v0.1.1 // indirect github.com/acobaugh/osrelease v0.1.0 // indirect github.com/anchore/go-rpmdb v0.0.0-20210914181456-a9c52348da63 // indirect github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b // indirect github.com/anchore/packageurl-go v0.0.0-20210922164639-b3fa992ebd29 // indirect github.com/andybalholm/brotli v1.0.4 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/bmatcuk/doublestar/v4 v4.0.2 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/containerd v1.5.10 // indirect github.com/containerd/stargz-snapshotter/estargz v0.10.1 // indirect + github.com/coreos/go-oidc/v3 v3.1.0 // indirect github.com/docker/cli v20.10.12+incompatible // indirect github.com/docker/distribution v2.8.0+incompatible // indirect github.com/docker/docker v20.10.12+incompatible // indirect @@ -49,11 +54,13 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/jinzhu/copier v0.3.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.14.2 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mholt/archiver/v3 v3.5.1 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect @@ -62,8 +69,14 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 // indirect github.com/pierrec/lz4/v4 v4.1.2 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/scylladb/go-set v1.0.2 // indirect + github.com/segmentio/ksuid v1.0.4 // indirect + github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/spdx/tools-golang v0.2.0 // indirect github.com/ulikunitz/xz v0.5.10 // indirect github.com/vbatts/tar-split v0.11.2 // indirect @@ -72,8 +85,10 @@ require ( github.com/wagoodman/go-progress v0.0.0-20200731105512-1020f39e6240 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/zclconf/go-cty v1.10.0 // indirect + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/appengine v1.6.7 // indirect ) require ( @@ -84,7 +99,7 @@ require ( github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.43.0 + github.com/aws/aws-sdk-go v1.43.24 github.com/blang/semver v3.5.1+incompatible // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b // indirect @@ -118,7 +133,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/leodido/go-urn v1.2.1 // indirect - github.com/magiconair/properties v1.8.5 // indirect + github.com/magiconair/properties v1.8.6 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect @@ -133,7 +148,8 @@ require ( github.com/secure-systems-lab/go-securesystemslib v0.3.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/shibumi/go-pathspec v1.3.0 // indirect - github.com/sigstore/sigstore v1.1.1-0.20220217212907-e48ca03a5ba7 // indirect + github.com/sigstore/fulcio v0.2.0 + github.com/sigstore/sigstore v1.2.0 github.com/spf13/afero v1.8.0 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -153,8 +169,8 @@ require ( golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c // indirect - google.golang.org/protobuf v1.27.1 // indirect + google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf // indirect + google.golang.org/protobuf v1.28.0 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index fc354801..98a0f0b3 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,9 @@ cloud.google.com/go/iam v0.1.1 h1:4CapQyNFjiksks1/x7jsvsygFPhihslYk5GptIrlX68= cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw= cloud.google.com/go/kms v1.0.0/go.mod h1:nhUehi+w7zht2XrUfvTRNpxrfayBHqP4lu2NSywui/0= cloud.google.com/go/kms v1.1.0/go.mod h1:WdbppnCDMDpOvoYBMn1+gNmOeEoZYqAv+HeuKARGCXI= -cloud.google.com/go/kms v1.3.0 h1:hWHaFmfTjtWVgSfX/rzE1qmZa/1AFr/6xQXhnufjyZQ= cloud.google.com/go/kms v1.3.0/go.mod h1:EIdZ6hpR15zmiaKC8YKYoXplDFnL+Z6f5VCGHJMDhLs= +cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/monitoring v0.1.0/go.mod h1:Hpm3XfzJv+UTiXzCG5Ffp0wijzHTC7Cv4eR7o3x/fEE= cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -71,6 +72,7 @@ cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjp cloud.google.com/go/pubsub v1.17.1/go.mod h1:4qDxMr1WsM9+aQAz36ltDwCIM+R0QdlseyFjBuNvnss= cloud.google.com/go/secretmanager v1.0.0/go.mod h1:+Qkm5qxIJ5mk74xxIXA+87fseaY1JLYBcFPQoc/GQxg= cloud.google.com/go/security v1.1.1/go.mod h1:QZd0wTwNJNKnl0H4/wAFD10TSX8kI4nk8V6ie6fyc9w= +cloud.google.com/go/security v1.3.0/go.mod h1:pQsnLAXfMzuWVJdctBs8BV3tGd3Jr0SMYu6KK3QXYAs= cloud.google.com/go/spanner v1.17.0/go.mod h1:+17t2ixFwRG4lWRwE+5kipDR9Ef07Jkmc8z0IbMDKUs= cloud.google.com/go/spanner v1.18.0/go.mod h1:LvAjUXPeJRGNuGpikMULjhLj/t9cRvdc+fxRoLiugXA= cloud.google.com/go/spanner v1.25.0/go.mod h1:kQUft3x355hzzaeFbObjsvkzZDgpDkesp3v75WBnI8w= @@ -116,8 +118,10 @@ github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v59.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v60.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v60.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v61.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v61.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v61.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v62.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= github.com/Azure/azure-service-bus-go v0.11.5/go.mod h1:MI6ge2CuQWBVq+ly456MY7XqNLJip5LO1iSFodbNLbU= github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= @@ -204,8 +208,10 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/PaesslerAG/gval v1.0.0 h1:GEKnRwkWDdf9dOmKcNrar9EA1bz1z9DqPIO1+iLzhd8= github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= +github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= @@ -224,6 +230,7 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= +github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= @@ -307,8 +314,10 @@ github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK github.com/aws/aws-sdk-go v1.42.8/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.42.22/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.42.25/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs= -github.com/aws/aws-sdk-go v1.43.0 h1:y4UrPbxU/mIL08qksVPE/nwH9IXuC1udjOaNyhEe+pI= +github.com/aws/aws-sdk-go v1.42.38/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc= github.com/aws/aws-sdk-go v1.43.0/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc= +github.com/aws/aws-sdk-go v1.43.24 h1:7c2PniJ0wpmWsIA6OtYBw6wS7DF0IjbhvPq+0ZQYNXw= +github.com/aws/aws-sdk-go v1.43.24/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.7.1/go.mod h1:L5LuPC1ZgDr2xQS7AmIec/Jlc7O/Y1u2KxJyNVab250= github.com/aws/aws-sdk-go-v2 v1.11.0/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= @@ -364,6 +373,7 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= @@ -390,8 +400,9 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bytecodealliance/wasmtime-go v0.31.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= -github.com/bytecodealliance/wasmtime-go v0.33.1 h1:TFep11LiqCy1B6QUIAtqH3KZTbZcKasm89/AF9sqLnA= github.com/bytecodealliance/wasmtime-go v0.33.1/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= +github.com/bytecodealliance/wasmtime-go v0.34.0 h1:PaWS0DUusaXaU3aNoSYjag6WmuxjyPYBHgkrC4EXips= +github.com/bytecodealliance/wasmtime-go v0.34.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= @@ -547,7 +558,9 @@ github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbrRw= github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -734,7 +747,7 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-ini/ini v1.66.3/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-ini/ini v1.66.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= @@ -747,9 +760,8 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -878,6 +890,8 @@ github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSr github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk= github.com/go-rod/rod v0.101.8/go.mod h1:N/zlT53CfSpq74nb6rOR0K8UF0SPUPBmzBnArrms+mY= github.com/go-rod/rod v0.102.1/go.mod h1:RXSLAlPodTFOmZnwaAQJIcOJ1i835r0uuTGPLO09t/M= +github.com/go-rod/rod v0.104.1 h1:CmFVu210HxSFOrmqX7/yLYIOF3pNm1SN9it+pQbi4ls= +github.com/go-rod/rod v0.104.1/go.mod h1:SVRIBdiq0sXXDdQxISmWuY8g1kLIUT+Pgk4VZSbOM1s= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -1183,6 +1197,7 @@ github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.1-0.20190430135223-99e2f22d1c94 h1:LaH4JWe6Q7ICdxL5raxQjSRw7Pj8uTtAENrjejIYZIg= @@ -1199,6 +1214,7 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/vault/api v1.3.0/go.mod h1:EabNQLI0VWbWoGlA+oBLC8PXmR9D60aUVgQGvangFWQ= github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFywzhptMsTIUw= +github.com/hashicorp/vault/api v1.4.1/go.mod h1:LkMdrZnWNrFaQyYYazWVn7KshilfDidgVBq6YiTq/bM= github.com/hashicorp/vault/sdk v0.3.0/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0= github.com/hashicorp/vault/sdk v0.4.1/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= @@ -1338,8 +1354,9 @@ github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXq github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -1383,6 +1400,7 @@ github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1/go.mod h1:DK1Cjkc0E49ShgRVs5jy5ASrM15svSnem3K/hiSGD8o= github.com/mediocregopher/radix/v4 v4.0.0/go.mod h1:ajchozX/6ELmydxWeWM6xCFHVpZ4+67LXHOTOVR0nCE= @@ -1401,6 +1419,7 @@ github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0 github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -1508,8 +1527,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/open-policy-agent/opa v0.35.0/go.mod h1:xEmekKlk6/c+so5HF9wtPnGPXDfBuBsrMGhSHOHEF+U= -github.com/open-policy-agent/opa v0.37.0 h1:OUXB+RAcxQpmXeNW2BN1wYzQQvVCPF1T9zv+QXGr9Wg= -github.com/open-policy-agent/opa v0.37.0/go.mod h1:xX3NUCZuXK8f0CNhFQvhm4495mZLptf94pIkWRLaFqo= +github.com/open-policy-agent/opa v0.38.0 h1:XuGM6yZmHCPO4o1JJGs8pKuoC/vMFkr4pjBVhFLrOk8= +github.com/open-policy-agent/opa v0.38.0/go.mod h1:z0+Gw2+Re8cEf4/GjHr/wAL1diGy8BkhICIiCUb8y6A= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1575,6 +1594,7 @@ github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1603,6 +1623,7 @@ github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1610,6 +1631,7 @@ github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= @@ -1625,6 +1647,7 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9 github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1640,6 +1663,7 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.1/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= @@ -1694,6 +1718,7 @@ github.com/secure-systems-lab/go-securesystemslib v0.2.0/go.mod h1:eIjBmIP8LD2ML github.com/secure-systems-lab/go-securesystemslib v0.3.0/go.mod h1:o8hhjkbNl2gOamKUA/eNW3xUrntHT9L4W89W1nfj43U= github.com/secure-systems-lab/go-securesystemslib v0.3.1 h1:LJuyMziazadwmQRRu1M7GMUo5S1oH1+YxU9FjuSFU8k= github.com/secure-systems-lab/go-securesystemslib v0.3.1/go.mod h1:o8hhjkbNl2gOamKUA/eNW3xUrntHT9L4W89W1nfj43U= +github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -1705,10 +1730,14 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sigstore/cosign v1.6.0/go.mod h1:Ocd28z0Pwtd6+A8s/Vb4SbhwuWOqVdeYAW4yCGF4Ndg= github.com/sigstore/fulcio v0.1.2-0.20220114150912-86a2036f9bc7/go.mod h1:ANQivY/lfOp9hN92S813LEthkm/kit96hzeIF3SNoZA= +github.com/sigstore/fulcio v0.2.0 h1:bT6oDNFe0MJ55lp9InymuBOd/5DA+gkxAP8k7HcUXIg= +github.com/sigstore/fulcio v0.2.0/go.mod h1:w2ncMx6ADlg7yjMQ+dcjnIc5MviY0LKLUgNo/azUp0g= github.com/sigstore/sigstore v1.0.2-0.20211210190220-04746d994282/go.mod h1:SuM+QIHtnnR9eGsURRLv5JfxM6KeaU0XKA1O7FmLs4Q= github.com/sigstore/sigstore v1.1.0/go.mod h1:gDpcHw4VwpoL5C6N1Ud1YtBsc+ikRDwDelDlWRyYoE8= -github.com/sigstore/sigstore v1.1.1-0.20220217212907-e48ca03a5ba7 h1:YIyoYwE9ggfBS+LgryGxZEhHQLS21V78jwdAM6fLkIY= +github.com/sigstore/sigstore v1.1.1-0.20220124143820-3cebf5c58675/go.mod h1:9cE3xS/1vYlN+Emn2WXDwjh0LYhXLJLv6mOCQpAHtSk= github.com/sigstore/sigstore v1.1.1-0.20220217212907-e48ca03a5ba7/go.mod h1:fPeKQqm6gcEp4Dp6nLp2LMCo3m+U0WfhzIqguCbhY9k= +github.com/sigstore/sigstore v1.2.0 h1:AMtf6txwOm5WHruZwmzqeWAKX7Cp2vO1O4eHI2+LZBg= +github.com/sigstore/sigstore v1.2.0/go.mod h1:BFkCXUqJrUApmvOA3rfDFTrN5+wwKQV2RgbJnVzOSiY= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1719,6 +1748,7 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -1796,8 +1826,9 @@ github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1809,6 +1840,7 @@ github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ github.com/tent/canonical-json-go v0.0.0-20130607151641-96e4ba3a7613/go.mod h1:g6AnIpDSYMcphz193otpSIzN+11Rs+AAIIC6rm1enug= github.com/testifysec/rekor v0.4.0-dsse-intermediates-2 h1:Kpf8sBke+KXvlxgsLuwFgXh3ogG5GN1bhOyMQGB0miU= github.com/testifysec/rekor v0.4.0-dsse-intermediates-2/go.mod h1:u9clLqaVjqV9pExVL1XkM37dGyMCOX/LMocS9nsnWDY= +github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/theupdateframework/go-tuf v0.0.0-20211203210025-7ded50136bf9/go.mod h1:n2n6wwC9BEnYS/C/APAtNln0eM5zYAYOkOTx6VEG/mA= github.com/theupdateframework/go-tuf v0.0.0-20220127213825-87caa18db2a6/go.mod h1:I0Gs4Tev4hYQ5wiNqN8VJ7qS0gw7KOZNQuckC624RmE= @@ -1900,10 +1932,14 @@ github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b h1:vV github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mod h1:HptNXiXVDcJjXe9SqMd0v2FsL9f8dz4GnXgltU6q/co= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/ysmood/goob v0.3.0/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs= +github.com/ysmood/goob v0.3.1 h1:qMp5364BGS1DLJVrAqUxTF6KOFt0YDot8GC70u/0jbI= github.com/ysmood/goob v0.3.1/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs= github.com/ysmood/got v0.15.1/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY= +github.com/ysmood/got v0.16.2/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY= github.com/ysmood/gotrace v0.2.2/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM= +github.com/ysmood/gson v0.6.4 h1:Yb6tosv6bk59HqjZu2/7o4BFherpYEMkDkXmlhgryZ4= github.com/ysmood/gson v0.6.4/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= +github.com/ysmood/leakless v0.7.0 h1:XCGdaPExyoreoQd+H5qgxM3ReNbSPFsEXpSKwbXbwQw= github.com/ysmood/leakless v0.7.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1979,27 +2015,29 @@ go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUz go.opentelemetry.io/contrib v1.3.0/go.mod h1:FlyPNX9s4U6MCsWEc5YAK4KzKNHFDsjrDUZijJiXvy8= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.28.0/go.mod h1:Ihno+mNBfZlT0Qot3XyRTdZ/9U/Cg2Pfgj75DTdIfq4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0/go.mod h1:tLYsuf2v8fZreBVwp9gVMhefZlLFZaUiNVSq8QxXRII= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= +go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk= +go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= -go.opentelemetry.io/otel/internal/metric v0.26.0/go.mod h1:CbBP6AxKynRs3QCbhklyLUtpfzbqCLiafV9oY2Zj1Jk= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1/go.mod h1:o5RW5o2pKpJLD5dNTCmjF1DorYwMeFJmb/rKr5sLaa8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1/go.mod h1:c6E4V3/U+miqjs/8l950wggHGL1qzlp0Ypj9xoGrPqo= +go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/metric v0.26.0/go.mod h1:c6YL0fhRo4YVoNs6GoByzUgBp36hBL523rECoZA5UWg= +go.opentelemetry.io/otel/metric v0.27.0/go.mod h1:raXDJ7uP2/Jc0nVZWQjJtzoyssOYWu/+pjZqRzfvZ7g= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= +go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE= go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= +go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE= +go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ= go.step.sm/crypto v0.14.0/go.mod h1:3G0yQr5lQqfEG0CMYz8apC/qMtjLRQlzflL2AxkcN+g= +go.step.sm/crypto v0.15.2/go.mod h1:3G0yQr5lQqfEG0CMYz8apC/qMtjLRQlzflL2AxkcN+g= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -2369,6 +2407,7 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2392,8 +2431,9 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2679,8 +2719,9 @@ google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c h1:TU4rFa5APdKTq0s6B7WTsH6Xmx0Knj86s6Biz56mErE= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf h1:SVYXkUz2yZS9FWb2Gm8ivSlbNQzL2Z/NpPKE3RG2jWk= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -2736,8 +2777,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/cryptoutil/x509.go b/pkg/cryptoutil/x509.go index 4db92a06..4bf2217c 100644 --- a/pkg/cryptoutil/x509.go +++ b/pkg/cryptoutil/x509.go @@ -55,6 +55,7 @@ func (v *X509Verifier) Verify(body io.Reader, sig []byte) error { CurrentTime: v.trustedTime, Roots: rootPool, Intermediates: intermediatePool, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, }); err != nil { return err } @@ -69,6 +70,7 @@ func (v *X509Verifier) BelongsToRoot(root *x509.Certificate) error { Roots: rootPool, Intermediates: intermediatePool, CurrentTime: v.trustedTime, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, }) return err diff --git a/pkg/dsse/dsse.go b/pkg/dsse/dsse.go index 6fa1f384..ab3263ea 100644 --- a/pkg/dsse/dsse.go +++ b/pkg/dsse/dsse.go @@ -179,11 +179,14 @@ func (e Envelope) Verify(opts ...VerificationOption) ([]cryptoutil.Verifier, err } for _, verifier := range options.verifiers { - if err := verifier.Verify(bytes.NewReader(pae), sig.Signature); err != nil { - return nil, err - } else { - passedVerifiers = append(passedVerifiers, verifier) - matchingSigFound = true + if verifier != nil { + + if err := verifier.Verify(bytes.NewReader(pae), sig.Signature); err != nil { + return nil, err + } else { + passedVerifiers = append(passedVerifiers, verifier) + matchingSigFound = true + } } } } diff --git a/pkg/signer/fulcio/fulcio.go b/pkg/signer/fulcio/fulcio.go new file mode 100644 index 00000000..51327b3a --- /dev/null +++ b/pkg/signer/fulcio/fulcio.go @@ -0,0 +1,147 @@ +// Copyright 2022 The Witness Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fulcio + +import ( + "bytes" + "context" + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" + "log" + "net/url" + + "github.com/sigstore/fulcio/pkg/api" + "github.com/sigstore/sigstore/pkg/oauthflow" + "github.com/sigstore/sigstore/pkg/signature" + sigo "github.com/sigstore/sigstore/pkg/signature/options" + "github.com/testifysec/witness/pkg/cryptoutil" +) + +func Signer(ctx context.Context, funcioURL string, oidcIssuer string, oidcClientID string) (cryptoutil.Signer, error) { + fClient, err := newClient(funcioURL) + if err != nil { + return nil, err + } + + key, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return nil, err + } + + fulcioSigner, err := signature.LoadSigner(key, crypto.SHA256) + if err != nil { + return nil, err + } + + certResp, err := getCert(fulcioSigner.(*signature.RSAPKCS1v15Signer), fClient, oidcIssuer, oidcClientID) + if err != nil { + return nil, err + } + + block, _ := pem.Decode(certResp.CertPEM) + if block == nil { + return nil, fmt.Errorf("failed to parse certificate PEM") + } + + if block.Type != "CERTIFICATE" { + return nil, fmt.Errorf("failed to parse certificate PEM") + } + + leaf, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, err + } + + intermediates := []*x509.Certificate{} + roots := []*x509.Certificate{} + + rest := certResp.ChainPEM + + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + return nil, fmt.Errorf("failed to parse certificate PEM") + } + + if block.Type != "CERTIFICATE" { + return nil, fmt.Errorf("failed to parse certificate PEM") + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, err + } + + switch cert.IsCA { + case true: + roots = append(roots, cert) + default: + intermediates = append(intermediates, cert) + } + + } + + ss := cryptoutil.NewRSASigner(key, crypto.SHA256) + if err != nil { + return nil, err + } + + witnessSigner, err := cryptoutil.NewX509Signer(ss, leaf, intermediates, roots) + if err != nil { + return nil, err + } + return witnessSigner, nil +} + +func getCert(signer *signature.RSAPKCS1v15Signer, fc api.Client, oidcIssuer string, oidcClientID string) (*api.CertificateResponse, error) { + tok, err := oauthflow.OIDConnect(oidcIssuer, oidcClientID, "", oauthflow.DefaultIDTokenGetter) + if err != nil { + return nil, err + } + + // Sign the email address as part of the request + b := bytes.NewBuffer([]byte(tok.Subject)) + proof, err := signer.SignMessage(b, sigo.WithCryptoSignerOpts(crypto.SHA256)) + if err != nil { + log.Fatal(err) + } + + pubBytes, err := x509.MarshalPKIXPublicKey(signer.Public()) + if err != nil { + return nil, err + } + cr := api.CertificateRequest{ + PublicKey: api.Key{ + Algorithm: "rsa4096", + Content: pubBytes, + }, + SignedEmailAddress: proof, + } + return fc.SigningCert(cr, tok.RawString) +} + +func newClient(fulcioURL string) (api.Client, error) { + fulcioServer, err := url.Parse(fulcioURL) + if err != nil { + return nil, err + } + fClient := api.NewClient(fulcioServer, api.WithUserAgent("witness")) + return fClient, nil +}