diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e0871f93..a9618d0b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: directory: "/" # Location of package manifests schedule: interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/code-scan-cron.yml b/.github/workflows/code-scan-cron.yml index 56969c11..9a35b7fe 100644 --- a/.github/workflows/code-scan-cron.yml +++ b/.github/workflows/code-scan-cron.yml @@ -5,5 +5,3 @@ on: jobs: code-scan: uses: smallstep/workflows/.github/workflows/code-scan.yml@main - secrets: - GITLEAKS_LICENSE_KEY: ${{ secrets.GITLEAKS_LICENSE_KEY }} diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 471eedab..8ca265e0 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v1.1.1 + uses: dependabot/fetch-metadata@v1.6.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Enable auto-merge for Dependabot PRs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 37fe2c2e..ab821066 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,19 +30,19 @@ jobs: echo ${{ github.ref }} | grep "\-rc.*" OUT=$? if [ $OUT -eq 0 ]; then IS_PRERELEASE=true; else IS_PRERELEASE=false; fi - echo "IS_PRERELEASE=${IS_PRERELEASE}" >> ${GITHUB_OUTPUT} + echo "IS_PRERELEASE=${IS_PRERELEASE}" >> "${GITHUB_OUTPUT}" - name: Extract Tag Names id: extract-tag run: | VERSION=${GITHUB_REF#refs/tags/v} - echo "VERSION=${VERSION}" >> ${GITHUB_OUTPUT} - echo "DOCKER_TAGS=${{ env.DOCKER_IMAGE }}:${VERSION}" >> ${GITHUB_ENV} - echo "DOCKER_TAGS_HSM=${{ env.DOCKER_IMAGE }}:${VERSION}-hsm" >> ${GITHUB_ENV} + echo "VERSION=${VERSION}" >> "${GITHUB_OUTPUT}" + echo "DOCKER_TAGS=${{ env.DOCKER_IMAGE }}:${VERSION}" >> "${GITHUB_ENV}" + echo "DOCKER_TAGS_HSM=${{ env.DOCKER_IMAGE }}:${VERSION}-hsm" >> "${GITHUB_ENV}" - name: Add Latest Tag if: steps.is_prerelease.outputs.IS_PRERELEASE == 'false' run: | - echo "DOCKER_TAGS=${{ env.DOCKER_TAGS }},${{ env.DOCKER_IMAGE }}:latest" >> ${GITHUB_ENV} - echo "DOCKER_TAGS_HSM=${{ env.DOCKER_TAGS_HSM }},${{ env.DOCKER_IMAGE }}:hsm" >> ${GITHUB_ENV} + echo "DOCKER_TAGS=${{ env.DOCKER_TAGS }},${{ env.DOCKER_IMAGE }}:latest" >> "${GITHUB_ENV}" + echo "DOCKER_TAGS_HSM=${{ env.DOCKER_TAGS_HSM }},${{ env.DOCKER_IMAGE }}:hsm" >> "${GITHUB_ENV}" - name: Create Release id: create_release uses: actions/create-release@v1 diff --git a/.gitleaksignore b/.gitleaksignore deleted file mode 100644 index 71318c8a..00000000 --- a/.gitleaksignore +++ /dev/null @@ -1,18 +0,0 @@ -deac15327f5605a1a963e50818760a95cee9d882:docs/kms.md:generic-api-key:85 -deac15327f5605a1a963e50818760a95cee9d882:docs/kms.md:generic-api-key:107 -deac15327f5605a1a963e50818760a95cee9d882:docs/kms.md:generic-api-key:108 -deac15327f5605a1a963e50818760a95cee9d882:docs/kms.md:generic-api-key:129 -deac15327f5605a1a963e50818760a95cee9d882:docs/kms.md:generic-api-key:131 -deac15327f5605a1a963e50818760a95cee9d882:docs/kms.md:generic-api-key:136 -deac15327f5605a1a963e50818760a95cee9d882:docs/kms.md:generic-api-key:138 -7c9ab9814fb676cb3c125c3dac4893271f1b7ae5:README.md:generic-api-key:282 -fb7140444ac8f1fa1245a80e49d17e206f7435f3:docs/provisioners.md:generic-api-key:110 -e4de7f07e82118b3f926716666b620db058fa9f7:docs/revocation.md:generic-api-key:73 -e4de7f07e82118b3f926716666b620db058fa9f7:docs/revocation.md:generic-api-key:113 -e4de7f07e82118b3f926716666b620db058fa9f7:docs/revocation.md:generic-api-key:151 -8b2de42e9cf6ce99f53a5049881e1d6077d5d66e:docs/docker.md:generic-api-key:152 -3939e855264117e81531df777a642ea953d325a7:autocert/init/ca/intermediate_ca_key:private-key:1 -e72f08703753facfa05f2d8c68f9f6a3745824b8:README.md:generic-api-key:244 -e70a5dae7de0b6ca40a0393c09c28872d4cfa071:autocert/README.md:generic-api-key:365 -e70a5dae7de0b6ca40a0393c09c28872d4cfa071:autocert/README.md:generic-api-key:366 -c284a2c0ab1c571a46443104be38c873ef0c7c6d:config.json:generic-api-key:10 diff --git a/.goreleaser.yml b/.goreleaser.yml index e64ee4b5..c00b26e8 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -36,11 +36,9 @@ archives: # Most common use case is to archive as zip on Windows. # Default is empty. name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Version }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" - rlcp: true format_overrides: - goos: windows format: zip - wrap_in_directory: "{{ .ProjectName }}_{{ .Version }}" files: - README.md - LICENSE @@ -49,6 +47,7 @@ archives: << : *ARCHIVE id: unversioned name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" + wrap_in_directory: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" nfpms: @@ -88,7 +87,6 @@ nfpms: source: enabled: true - rlcp: true name_template: '{{ .ProjectName }}_{{ .Version }}' checksum: @@ -166,11 +164,11 @@ release: ``` cosign verify-blob \ - --certificate ~/Downloads/step-ca_darwin_{{ .Version }}_amd64.tar.gz.sig.pem \ - --signature ~/Downloads/step-ca_darwin_{{ .Version }}_amd64.tar.gz.sig \ - --certificate-identity-regexp "https://github\.com/smallstep/certificates/.*" \ + --certificate step-ca_darwin_{{ .Version }}_amd64.tar.gz.sig.pem \ + --signature step-ca_darwin_{{ .Version }}_amd64.tar.gz.sig \ + --certificate-identity-regexp "https://github\.com/smallstep/workflows/.*" \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - ~/Downloads/step-ca_darwin_{{ .Version }}_amd64.tar.gz + step-ca_darwin_{{ .Version }}_amd64.tar.gz ``` The `checksums.txt` file (in the `Assets` section below) contains a checksum for every artifact in the release. @@ -199,6 +197,124 @@ release: # - glob: ./glob/**/to/**/file/**/* # - glob: ./glob/foo/to/bar/file/foobar/override_from_previous +winget: + - + # IDs of the archives to use. + # Empty means all IDs. + ids: [ default ] + + # + # Default: ProjectName + # Templates: allowed + name: step-ca + + # Publisher name. + # + # Templates: allowed + # Required. + publisher: Smallstep + + # Your app's description. + # + # Templates: allowed + # Required. + short_description: "A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management." + + # License name. + # + # Templates: allowed + # Required. + license: "Apache-2.0" + + # Publisher URL. + # + # Templates: allowed + publisher_url: "https://smallstep.com" + + # Publisher support URL. + # + # Templates: allowed + publisher_support_url: "https://github.com/smallstep/certificates/discussions" + + # URL which is determined by the given Token (github, gitlab or gitea). + # + # Default depends on the client. + # Templates: allowed + url_template: "https://github.com/smallstep/certificates/releases/download/{{ .Tag }}/{{ .ArtifactName }}" + + # Git author used to commit to the repository. + commit_author: + name: goreleaserbot + email: goreleaser@smallstep.com + + # The project name and current git tag are used in the format string. + # + # Templates: allowed + commit_msg_template: "{{ .PackageIdentifier }}: {{ .Tag }}" + + # Your app's homepage. + homepage: "https://github.com/smallstep/certificates" + + # Your app's long description. + # + # Templates: allowed + description: "" + + # License URL. + # + # Templates: allowed + license_url: "https://github.com/smallstep/certificates/blob/master/LICENSE" + + # Release notes URL. + # + # Templates: allowed + release_notes_url: "https://github.com/smallstep/certificates/releases/tag/{{.Version}}" + + # Create the PR - for testing + skip_upload: auto + + # Tags. + tags: + - certificates + - smallstep + - tls + + # Repository to push the generated files to. + repository: + owner: smallstep + name: winget-pkgs + branch: step + + # Optionally a token can be provided, if it differs from the token + # provided to GoReleaser + # Templates: allowed + #token: "{{ .Env.GITHUB_PERSONAL_AUTH_TOKEN }}" + + # Sets up pull request creation instead of just pushing to the given branch. + # Make sure the 'branch' property is different from base before enabling + # it. + # + # Since: v1.17 + pull_request: + # Whether to enable it or not. + enabled: true + check_boxes: true + # Whether to open the PR as a draft or not. + # + # Default: false + # Since: v1.19 + # draft: true + + # Base can also be another repository, in which case the owner and name + # above will be used as HEAD, allowing cross-repository pull requests. + # + # Since: v1.19 + base: + owner: microsoft + name: winget-pkgs + branch: master + + scoops: - ids: [ default ] @@ -208,9 +324,10 @@ scoops: # Default for gitea is "https://gitea.com///releases/download/{{ .Tag }}/{{ .ArtifactName }}" url_template: "http://github.com/smallstep/certificates/releases/download/{{ .Tag }}/{{ .ArtifactName }}" # Repository to push the app manifest to. - bucket: + repository: owner: smallstep name: scoop-bucket + branch: main # Git author used to commit to the repository. # Defaults are shown. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5265f1d9..4e0a92a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,13 +25,63 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. --- -## [Unreleased] +## [0.25.0] - 2023-09-26 + +### Added + +- Added support for configuring SCEP decrypters in the provisioner (smallstep/certificates#1414) +- Added support for TPM KMS (smallstep/crypto#253) +- Added support for disableSmallstepExtensions provisioner claim + (smallstep/certificates#1484) +- Added script to migrate a badger DB to MySQL or PostgreSQL + (smallstep/certificates#1477) +- Added AWS public certificates for me-central-1 and ap-southeast-3 + (smallstep/certificates#1404) +- Added namespace field to VaultCAS JSON config (smallstep/certificates#1424) +- Added AWS public certificates for me-central-1 and ap-southeast-3 + (smallstep/certificates#1404) +- Added unversioned filenames to Github release assets + (smallstep/certificates#1435) +- Send X5C leaf certificate to webhooks (smallstep/certificates#1485) +- Added support for disableSmallstepExtensions claim (smallstep/certificates#1484) +- Added all AWS Identity Document Certificates (smallstep/certificates#1404, smallstep/certificates#1510) +- Added Winget release automation (smallstep/certificates#1519) +- Added CSR to SCEPCHALLENGE webhook request body (smallstep/certificates#1523) +- Added SCEP issuance notification webhook (smallstep/certificates#1544) +- Added ability to disable color in the log text formatter + (smallstep/certificates(#1559) + +### Changed + +- Changed the Makefile to produce cgo-enabled builds running + `make build GO_ENVS="CGO_ENABLED=1"` (smallstep/certificates#1446) +- Return more detailed errors to ACME clients using device-attest-01 + (smallstep/certificates#1495) +- Change SCEP password type to string (smallstep/certificates#1555) + +### Removed + +- Removed OIDC user regexp check (smallstep/certificates#1481) +- Removed automatic initialization of $STEPPATH (smallstep/certificates#1493) +- Removed db datasource from error msg to prevent leaking of secrets to logs + (smallstep/certificates#1528) ### Fixed - Improved authentication for ACME requests using kid and provisioner name (smallstep/certificates#1386). - +- Fixed indentation of KMS configuration in helm charts + (smallstep/certificates#1405) +- Fixed simultaneous sign or decrypt operation on a YubiKey + (smallstep/certificates#1476, smallstep/crypto#288) +- Fixed adding certificate templates with ASN.1 functions + (smallstep/certificates#1500, smallstep/crypto#302) +- Fixed a problem when the ca.json is truncated if the encoding of the + configuration fails (e.g., new provisioner with bad template data) + (smallstep/cli#994, smallstep/certificates#1501) +- Fixed provisionerOptionsToLinkedCA missing template and templateData + (smallstep/certificates#1520) +- Fix calculation of webhook signature (smallstep/certificates#1546) ## [v0.24.2] - 2023-05-11 diff --git a/README.md b/README.md index 9b454f51..4505a7ef 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ To get up and running quickly, or as an alternative to running your own `step-ca [Documentation](https://smallstep.com/docs) | [Installation](https://smallstep.com/docs/step-ca/installation) | [Getting Started](https://smallstep.com/docs/step-ca/getting-started) | -[Contributor's Guide](./docs/CONTRIBUTING.md) +[Contributor's Guide](./CONTRIBUTING.md) [![GitHub release](https://img.shields.io/github/release/smallstep/certificates.svg)](https://github.com/smallstep/certificates/releases/latest) [![Go Report Card](https://goreportcard.com/badge/github.com/smallstep/certificates)](https://goreportcard.com/report/github.com/smallstep/certificates) diff --git a/acme/api/account.go b/acme/api/account.go index ce8b5799..25d923c7 100644 --- a/acme/api/account.go +++ b/acme/api/account.go @@ -6,7 +6,7 @@ import ( "errors" "net/http" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/smallstep/certificates/acme" "github.com/smallstep/certificates/api/render" diff --git a/acme/api/account_test.go b/acme/api/account_test.go index c4cfaa02..7d799c88 100644 --- a/acme/api/account_test.go +++ b/acme/api/account_test.go @@ -7,12 +7,13 @@ import ( "encoding/json" "fmt" "io" + "net/http" "net/http/httptest" "net/url" "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/pkg/errors" "go.step.sm/crypto/jose" @@ -313,7 +314,7 @@ func TestHandler_GetOrdersByAccountID(t *testing.T) { "fail/nil-account": func(t *testing.T) test { return test{ db: &acme.MockDB{}, - ctx: context.WithValue(context.Background(), accContextKey, nil), + ctx: context.WithValue(context.Background(), accContextKey, http.NoBody), statusCode: 400, err: acme.NewError(acme.ErrorAccountDoesNotExistType, "account does not exist"), } @@ -363,7 +364,7 @@ func TestHandler_GetOrdersByAccountID(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() GetOrdersByAccountID(w, req) @@ -802,7 +803,7 @@ func TestHandler_NewAccount(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil) - req := httptest.NewRequest("GET", "/foo/bar", nil) + req := httptest.NewRequest("GET", "/foo/bar", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() NewAccount(w, req) @@ -1005,7 +1006,7 @@ func TestHandler_GetOrUpdateAccount(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil) - req := httptest.NewRequest("GET", "/foo/bar", nil) + req := httptest.NewRequest("GET", "/foo/bar", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() GetOrUpdateAccount(w, req) diff --git a/acme/api/handler.go b/acme/api/handler.go index 16713cf7..d2940f49 100644 --- a/acme/api/handler.go +++ b/acme/api/handler.go @@ -9,7 +9,7 @@ import ( "net/http" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/smallstep/certificates/acme" "github.com/smallstep/certificates/api" diff --git a/acme/api/handler_test.go b/acme/api/handler_test.go index 7ef7cd68..bd7bb50e 100644 --- a/acme/api/handler_test.go +++ b/acme/api/handler_test.go @@ -15,7 +15,7 @@ import ( "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/google/go-cmp/cmp" "github.com/pkg/errors" @@ -60,7 +60,7 @@ func TestHandler_GetNonce(t *testing.T) { } // Request with chi context - req := httptest.NewRequest("GET", "http://ca.smallstep.com/nonce", nil) + req := httptest.NewRequest("GET", "http://ca.smallstep.com/nonce", http.NoBody) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -175,7 +175,7 @@ func TestHandler_GetDirectory(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewLinkerContext(tc.ctx, acme.NewLinker("test.ca.smallstep.com", "acme")) - req := httptest.NewRequest("GET", "/foo/bar", nil) + req := httptest.NewRequest("GET", "/foo/bar", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() GetDirectory(w, req) @@ -347,7 +347,7 @@ func TestHandler_GetAuthorization(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil) - req := httptest.NewRequest("GET", "/foo/bar", nil) + req := httptest.NewRequest("GET", "/foo/bar", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() GetAuthorization(w, req) @@ -489,7 +489,7 @@ func TestHandler_GetCertificate(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewDatabaseContext(tc.ctx, tc.db) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() GetCertificate(w, req) @@ -747,7 +747,7 @@ func TestHandler_GetChallenge(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() GetChallenge(w, req) diff --git a/acme/api/middleware_test.go b/acme/api/middleware_test.go index f7db647b..90190bc7 100644 --- a/acme/api/middleware_test.go +++ b/acme/api/middleware_test.go @@ -75,7 +75,7 @@ func TestHandler_addNonce(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := newBaseContext(context.Background(), tc.db) - req := httptest.NewRequest("GET", u, nil).WithContext(ctx) + req := httptest.NewRequest("GET", u, http.NoBody).WithContext(ctx) w := httptest.NewRecorder() addNonce(testNext)(w, req) res := w.Result() @@ -127,7 +127,7 @@ func TestHandler_addDirLink(t *testing.T) { for name, run := range tests { tc := run(t) t.Run(name, func(t *testing.T) { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() addDirLink(testNext)(w, req) @@ -230,7 +230,7 @@ func TestHandler_verifyContentType(t *testing.T) { if tc.url != "" { _u = tc.url } - req := httptest.NewRequest("GET", _u, nil) + req := httptest.NewRequest("GET", _u, http.NoBody) req = req.WithContext(tc.ctx) req.Header.Add("Content-Type", tc.contentType) w := httptest.NewRecorder() @@ -298,7 +298,7 @@ func TestHandler_isPostAsGet(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { // h := &Handler{} - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() isPostAsGet(testNext)(w, req) @@ -582,7 +582,7 @@ func TestHandler_verifyAndExtractJWSPayload(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { // h := &Handler{} - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(tc.ctx) w := httptest.NewRecorder() verifyAndExtractJWSPayload(tc.next)(w, req) @@ -829,7 +829,7 @@ func TestHandler_lookupJWK(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := newBaseContext(tc.ctx, tc.db, tc.linker) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() lookupJWK(tc.next)(w, req) @@ -1028,7 +1028,7 @@ func TestHandler_extractJWK(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := newBaseContext(tc.ctx, tc.db) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() extractJWK(tc.next)(w, req) @@ -1403,7 +1403,7 @@ func TestHandler_validateJWS(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := newBaseContext(tc.ctx, tc.db) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() validateJWS(tc.next)(w, req) @@ -1585,7 +1585,7 @@ func TestHandler_extractOrLookupJWK(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { ctx := newBaseContext(tc.ctx, tc.db, tc.linker) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() extractOrLookupJWK(tc.next)(w, req) @@ -1670,7 +1670,7 @@ func TestHandler_checkPrerequisites(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := acme.NewPrerequisitesCheckerContext(tc.ctx, tc.prerequisitesChecker) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() checkPrerequisites(tc.next)(w, req) diff --git a/acme/api/order.go b/acme/api/order.go index 0c81df76..b207f87c 100644 --- a/acme/api/order.go +++ b/acme/api/order.go @@ -10,7 +10,7 @@ import ( "strings" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "go.step.sm/crypto/randutil" "go.step.sm/crypto/x509util" diff --git a/acme/api/order_test.go b/acme/api/order_test.go index 9f03c547..36de975a 100644 --- a/acme/api/order_test.go +++ b/acme/api/order_test.go @@ -8,13 +8,14 @@ import ( "encoding/json" "fmt" "io" + "net/http" "net/http/httptest" "net/url" "reflect" "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/pkg/errors" "go.step.sm/crypto/pemutil" @@ -468,7 +469,7 @@ func TestHandler_GetOrder(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := newBaseContext(tc.ctx, tc.db, acme.NewLinker("test.ca.smallstep.com", "acme")) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() GetOrder(w, req) @@ -1827,7 +1828,7 @@ func TestHandler_NewOrder(t *testing.T) { t.Run(name, func(t *testing.T) { mockMustAuthority(t, tc.ca) ctx := newBaseContext(tc.ctx, tc.db, acme.NewLinker("test.ca.smallstep.com", "acme")) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() NewOrder(w, req) @@ -2124,7 +2125,7 @@ func TestHandler_FinalizeOrder(t *testing.T) { tc := run(t) t.Run(name, func(t *testing.T) { ctx := newBaseContext(tc.ctx, tc.db, acme.NewLinker("test.ca.smallstep.com", "acme")) - req := httptest.NewRequest("GET", u, nil) + req := httptest.NewRequest("GET", u, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() FinalizeOrder(w, req) diff --git a/acme/api/revoke_test.go b/acme/api/revoke_test.go index b1b7f5d6..1c472e6e 100644 --- a/acme/api/revoke_test.go +++ b/acme/api/revoke_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/google/go-cmp/cmp" "github.com/pkg/errors" "golang.org/x/crypto/ocsp" @@ -1072,7 +1072,7 @@ func TestHandler_RevokeCert(t *testing.T) { t.Run(name, func(t *testing.T) { ctx := newBaseContext(tc.ctx, tc.db, acme.NewLinker("test.ca.smallstep.com", "acme")) mockMustAuthority(t, tc.ca) - req := httptest.NewRequest("POST", revokeURL, nil) + req := httptest.NewRequest("POST", revokeURL, http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() RevokeCert(w, req) @@ -1094,7 +1094,7 @@ func TestHandler_RevokeCert(t *testing.T) { assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { assert.True(t, bytes.Equal(bytes.TrimSpace(body), []byte{})) - assert.Equals(t, int64(0), req.ContentLength) + assert.Equals(t, int64(-1), req.ContentLength) assert.Equals(t, []string{fmt.Sprintf("<%s/acme/%s/directory>;rel=\"index\"", baseURL.String(), escProvName)}, res.Header["Link"]) } }) diff --git a/acme/challenge.go b/acme/challenge.go index 9904d690..ccb99103 100644 --- a/acme/challenge.go +++ b/acme/challenge.go @@ -26,7 +26,7 @@ import ( "time" "github.com/fxamacker/cbor/v2" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" "golang.org/x/exp/slices" "github.com/smallstep/go-attestation/attest" @@ -384,7 +384,7 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose prov := MustProvisionerFromContext(ctx) if !prov.IsAttestationFormatEnabled(ctx, provisioner.ACMEAttestationFormat(format)) { if format != "apple" && format != "step" && format != "tpm" { - return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "unsupported attestation object format %q", format).WithAdditionalErrorDetail()) + return storeError(ctx, db, ch, true, NewDetailedError(ErrorBadAttestationStatementType, "unsupported attestation object format %q", format)) } return storeError(ctx, db, ch, true, @@ -409,7 +409,7 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose if len(data.Nonce) != 0 { sum := sha256.Sum256([]byte(ch.Token)) if subtle.ConstantTimeCompare(data.Nonce, sum[:]) != 1 { - return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "challenge token does not match")) + return storeError(ctx, db, ch, true, NewDetailedError(ErrorBadAttestationStatementType, "challenge token does not match")) } } @@ -421,9 +421,9 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose subproblem := NewSubproblemWithIdentifier( ErrorRejectedIdentifierType, Identifier{Type: "permanent-identifier", Value: ch.Value}, - "challenge identifier %q doesn't match any of the attested hardware identifiers %s", ch.Value, []string{data.UDID, data.SerialNumber}, + "challenge identifier %q doesn't match any of the attested hardware identifiers %q", ch.Value, []string{data.UDID, data.SerialNumber}, ) - return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match").WithAdditionalErrorDetail().AddSubproblems(subproblem)) + return storeError(ctx, db, ch, true, NewDetailedError(ErrorBadAttestationStatementType, "permanent identifier does not match").AddSubproblems(subproblem)) } // Update attestation key fingerprint to compare against the CSR @@ -451,7 +451,7 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose Identifier{Type: "permanent-identifier", Value: ch.Value}, "challenge identifier %q doesn't match the attested hardware identifier %q", ch.Value, data.SerialNumber, ) - return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match").WithAdditionalErrorDetail().AddSubproblems(subproblem)) + return storeError(ctx, db, ch, true, NewDetailedError(ErrorBadAttestationStatementType, "permanent identifier does not match").AddSubproblems(subproblem)) } // Update attestation key fingerprint to compare against the CSR @@ -479,15 +479,15 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose subproblem := NewSubproblemWithIdentifier( ErrorRejectedIdentifierType, Identifier{Type: "permanent-identifier", Value: ch.Value}, - "challenge identifier %q doesn't match any of the attested hardware identifiers %s", ch.Value, data.PermanentIdentifiers, + "challenge identifier %q doesn't match any of the attested hardware identifiers %q", ch.Value, data.PermanentIdentifiers, ) - return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match").WithAdditionalErrorDetail().AddSubproblems(subproblem)) + return storeError(ctx, db, ch, true, NewDetailedError(ErrorBadAttestationStatementType, "permanent identifier does not match").AddSubproblems(subproblem)) } // Update attestation key fingerprint to compare against the CSR az.Fingerprint = data.Fingerprint default: - return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "unsupported attestation object format %q", format).WithAdditionalErrorDetail()) + return storeError(ctx, db, ch, true, NewDetailedError(ErrorBadAttestationStatementType, "unsupported attestation object format %q", format)) } // Update and store the challenge. @@ -533,38 +533,38 @@ const ( func doTPMAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, jwk *jose.JSONWebKey, att *attestationObject) (*tpmAttestationData, error) { ver, ok := att.AttStatement["ver"].(string) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "ver not present").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "ver not present") } if ver != "2.0" { - return nil, NewError(ErrorBadAttestationStatementType, "version %q is not supported", ver).WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "version %q is not supported", ver) } x5c, ok := att.AttStatement["x5c"].([]interface{}) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c not present").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c not present") } if len(x5c) == 0 { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is empty").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is empty") } akCertBytes, ok := x5c[0].([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is malformed") } akCert, err := x509.ParseCertificate(akCertBytes) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is malformed") } intermediates := x509.NewCertPool() for _, v := range x5c[1:] { intCertBytes, vok := v.([]byte) if !vok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is malformed") } intCert, err := x509.ParseCertificate(intCertBytes) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is malformed") } intermediates.AddCert(intCert) } @@ -602,19 +602,19 @@ func doTPMAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, }) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is not valid").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is not valid") } // validate additional AK certificate requirements if err := validateAKCertificate(akCert); err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "AK certificate is not valid").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "AK certificate is not valid") } // TODO(hs): implement revocation check; Verify() doesn't perform CRL check nor OCSP lookup. sans, err := x509util.ParseSubjectAlternativeNames(akCert) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "failed parsing AK certificate Subject Alternative Names").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "failed parsing AK certificate Subject Alternative Names") } permanentIdentifiers := make([]string, len(sans.PermanentIdentifiers)) @@ -625,37 +625,37 @@ func doTPMAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, // extract and validate pubArea, sig, certInfo and alg properties from the request body pubArea, ok := att.AttStatement["pubArea"].([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "invalid pubArea in attestation statement").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "invalid pubArea in attestation statement") } if len(pubArea) == 0 { - return nil, NewError(ErrorBadAttestationStatementType, "pubArea is empty").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "pubArea is empty") } sig, ok := att.AttStatement["sig"].([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "invalid sig in attestation statement").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "invalid sig in attestation statement") } if len(sig) == 0 { - return nil, NewError(ErrorBadAttestationStatementType, "sig is empty").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "sig is empty") } certInfo, ok := att.AttStatement["certInfo"].([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "invalid certInfo in attestation statement").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "invalid certInfo in attestation statement") } if len(certInfo) == 0 { - return nil, NewError(ErrorBadAttestationStatementType, "certInfo is empty").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "certInfo is empty") } alg, ok := att.AttStatement["alg"].(int64) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "invalid alg in attestation statement").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "invalid alg in attestation statement") } // only RS256 and ES256 are allowed coseAlg := coseAlgorithmIdentifier(alg) if coseAlg != coseAlgRS256 && coseAlg != coseAlgES256 { - return nil, NewError(ErrorBadAttestationStatementType, "invalid alg %d in attestation statement", alg).WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "invalid alg %d in attestation statement", alg) } // set the hash algorithm to use to SHA256 @@ -673,13 +673,13 @@ func doTPMAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, Hash: hash, } if err = certificationParameters.Verify(verifyOpts); err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "invalid certification parameters").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "invalid certification parameters") } // decode the "certInfo" data. This won't fail, as it's also done as part of Verify(). tpmCertInfo, err := tpm2.DecodeAttestationData(certInfo) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "failed decoding attestation data").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "failed decoding attestation data") } keyAuth, err := KeyAuthorization(ch.Token, jwk) @@ -691,18 +691,18 @@ func doTPMAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, // verify the WebAuthn object contains the expect key authorization digest, which is carried // within the encoded `certInfo` property of the attestation statement. if subtle.ConstantTimeCompare(hashedKeyAuth[:], []byte(tpmCertInfo.ExtraData)) == 0 { - return nil, NewError(ErrorBadAttestationStatementType, "key authorization invalid").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "key authorization invalid") } // decode the (attested) public key and determine its fingerprint. This won't fail, as it's also done as part of Verify(). pub, err := tpm2.DecodePublic(pubArea) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "failed decoding pubArea").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "failed decoding pubArea") } publicKey, err := pub.Key() if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "failed getting public key").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "failed getting public key") } data := &tpmAttestationData{ @@ -862,30 +862,30 @@ func doAppleAttestationFormat(_ context.Context, prov Provisioner, _ *Challenge, x5c, ok := att.AttStatement["x5c"].([]interface{}) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c not present").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c not present") } if len(x5c) == 0 { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is empty").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is empty") } der, ok := x5c[0].([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is malformed") } leaf, err := x509.ParseCertificate(der) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is malformed") } intermediates := x509.NewCertPool() for _, v := range x5c[1:] { der, ok = v.([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is malformed") } cert, err := x509.ParseCertificate(der) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is malformed") } intermediates.AddCert(cert) } @@ -896,7 +896,7 @@ func doAppleAttestationFormat(_ context.Context, prov Provisioner, _ *Challenge, CurrentTime: time.Now().Truncate(time.Second), KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, }); err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is not valid").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is not valid") } data := &appleAttestationData{ @@ -982,28 +982,28 @@ func doStepAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, // Extract x5c and verify certificate x5c, ok := att.AttStatement["x5c"].([]interface{}) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c not present").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c not present") } if len(x5c) == 0 { - return nil, NewError(ErrorRejectedIdentifierType, "x5c is empty").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorRejectedIdentifierType, "x5c is empty") } der, ok := x5c[0].([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is malformed") } leaf, err := x509.ParseCertificate(der) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is malformed") } intermediates := x509.NewCertPool() for _, v := range x5c[1:] { der, ok = v.([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "x5c is malformed") } cert, err := x509.ParseCertificate(der) if err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is malformed") } intermediates.AddCert(cert) } @@ -1013,7 +1013,7 @@ func doStepAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, CurrentTime: time.Now().Truncate(time.Second), KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, }); err != nil { - return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is not valid").WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "x5c is not valid") } // Verify proof of possession of private key validating the key @@ -1023,10 +1023,10 @@ func doStepAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, var sig []byte csig, ok := att.AttStatement["sig"].([]byte) if !ok { - return nil, NewError(ErrorBadAttestationStatementType, "sig not present").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "sig not present") } if err := cbor.Unmarshal(csig, &sig); err != nil { - return nil, NewError(ErrorBadAttestationStatementType, "sig is malformed").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "sig is malformed") } keyAuth, err := KeyAuthorization(ch.Token, jwk) if err != nil { @@ -1036,23 +1036,23 @@ func doStepAttestationFormat(_ context.Context, prov Provisioner, ch *Challenge, switch pub := leaf.PublicKey.(type) { case *ecdsa.PublicKey: if pub.Curve != elliptic.P256() { - return nil, WrapError(ErrorBadAttestationStatementType, err, "unsupported elliptic curve %s", pub.Curve).WithAdditionalErrorDetail() + return nil, WrapDetailedError(ErrorBadAttestationStatementType, err, "unsupported elliptic curve %s", pub.Curve) } sum := sha256.Sum256([]byte(keyAuth)) if !ecdsa.VerifyASN1(pub, sum[:], sig) { - return nil, NewError(ErrorBadAttestationStatementType, "failed to validate signature").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "failed to validate signature") } case *rsa.PublicKey: sum := sha256.Sum256([]byte(keyAuth)) if err := rsa.VerifyPKCS1v15(pub, crypto.SHA256, sum[:], sig); err != nil { - return nil, NewError(ErrorBadAttestationStatementType, "failed to validate signature").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "failed to validate signature") } case ed25519.PublicKey: if !ed25519.Verify(pub, []byte(keyAuth), sig) { - return nil, NewError(ErrorBadAttestationStatementType, "failed to validate signature").WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "failed to validate signature") } default: - return nil, NewError(ErrorBadAttestationStatementType, "unsupported public key type %T", pub).WithAdditionalErrorDetail() + return nil, NewDetailedError(ErrorBadAttestationStatementType, "unsupported public key type %T", pub) } // Parse attestation data: diff --git a/acme/challenge_test.go b/acme/challenge_test.go index 0853943e..c20cf6aa 100644 --- a/acme/challenge_test.go +++ b/acme/challenge_test.go @@ -3444,7 +3444,7 @@ func Test_deviceAttest01Validate(t *testing.T) { }, payload: errorCBORPayload, }, - wantErr: NewErrorISE("error unmarshalling CBOR: cbor: cannot unmarshal positive integer into Go value of type acme.attestationObject"), + wantErr: NewErrorISE("error unmarshalling CBOR: cbor:"), } }, "ok/prov.IsAttestationFormatEnabled": func(t *testing.T) test { @@ -3532,7 +3532,7 @@ func Test_deviceAttest01Validate(t *testing.T) { assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) assert.Equal(t, "12345678", updch.Value) - err := NewError(ErrorBadAttestationStatementType, "x5c not present").WithAdditionalErrorDetail() + err := NewDetailedError(ErrorBadAttestationStatementType, "x5c not present") assert.EqualError(t, updch.Error.Err, err.Err.Error()) assert.Equal(t, err.Type, updch.Error.Type) @@ -3579,7 +3579,7 @@ func Test_deviceAttest01Validate(t *testing.T) { assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) assert.Equal(t, "serial-number", updch.Value) - err := NewError(ErrorBadAttestationStatementType, "challenge token does not match") + err := NewDetailedError(ErrorBadAttestationStatementType, "challenge token does not match") assert.EqualError(t, updch.Error.Err, err.Err.Error()) assert.Equal(t, err.Type, updch.Error.Type) @@ -3628,9 +3628,9 @@ func Test_deviceAttest01Validate(t *testing.T) { subproblem := NewSubproblemWithIdentifier( ErrorRejectedIdentifierType, Identifier{Type: "permanent-identifier", Value: "non-matching-value"}, - `challenge identifier "non-matching-value" doesn't match any of the attested hardware identifiers [udid serial-number]`, + `challenge identifier "non-matching-value" doesn't match any of the attested hardware identifiers ["udid" "serial-number"]`, ) - err := NewError(ErrorBadAttestationStatementType, "permanent identifier does not match").WithAdditionalErrorDetail().AddSubproblems(subproblem) + err := NewDetailedError(ErrorBadAttestationStatementType, "permanent identifier does not match").AddSubproblems(subproblem) assert.EqualError(t, updch.Error.Err, err.Err.Error()) assert.Equal(t, err.Type, updch.Error.Type) @@ -3703,7 +3703,7 @@ func Test_deviceAttest01Validate(t *testing.T) { assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) assert.Equal(t, "12345678", updch.Value) - err := NewError(ErrorBadAttestationStatementType, "x5c not present").WithAdditionalErrorDetail() + err := NewDetailedError(ErrorBadAttestationStatementType, "x5c not present") assert.EqualError(t, updch.Error.Err, err.Err.Error()) assert.Equal(t, err.Type, updch.Error.Type) @@ -3757,8 +3757,7 @@ func Test_deviceAttest01Validate(t *testing.T) { assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) assert.Equal(t, "12345678", updch.Value) - err := NewError(ErrorBadAttestationStatementType, "permanent identifier does not match"). - WithAdditionalErrorDetail(). + err := NewDetailedError(ErrorBadAttestationStatementType, "permanent identifier does not match"). AddSubproblems(NewSubproblemWithIdentifier( ErrorRejectedIdentifierType, Identifier{Type: "permanent-identifier", Value: "12345678"}, @@ -3853,7 +3852,7 @@ func Test_deviceAttest01Validate(t *testing.T) { assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) assert.Equal(t, "12345678", updch.Value) - err := NewError(ErrorBadAttestationStatementType, `unsupported attestation object format "bogus-format"`).WithAdditionalErrorDetail() + err := NewDetailedError(ErrorBadAttestationStatementType, `unsupported attestation object format "bogus-format"`) assert.EqualError(t, updch.Error.Err, err.Err.Error()) assert.Equal(t, err.Type, updch.Error.Type) @@ -4004,8 +4003,9 @@ func Test_deviceAttest01Validate(t *testing.T) { tc := run(t) if err := deviceAttest01Validate(tc.args.ctx, tc.args.ch, tc.args.db, tc.args.jwk, tc.args.payload); err != nil { - assert.Error(t, tc.wantErr) - assert.EqualError(t, err, tc.wantErr.Error()) + if assert.Error(t, tc.wantErr) { + assert.ErrorContains(t, err, tc.wantErr.Error()) + } return } diff --git a/acme/challenge_tpmsimulator_test.go b/acme/challenge_tpmsimulator_test.go index 96381b80..87db8631 100644 --- a/acme/challenge_tpmsimulator_test.go +++ b/acme/challenge_tpmsimulator_test.go @@ -237,7 +237,7 @@ func Test_deviceAttest01ValidateWithTPMSimulator(t *testing.T) { assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) assert.Equal(t, "device.id.12345678", updch.Value) - err := NewError(ErrorBadAttestationStatementType, `version "bogus" is not supported`).WithAdditionalErrorDetail() + err := NewDetailedError(ErrorBadAttestationStatementType, `version "bogus" is not supported`) assert.EqualError(t, updch.Error.Err, err.Err.Error()) assert.Equal(t, err.Type, updch.Error.Type) @@ -282,12 +282,11 @@ func Test_deviceAttest01ValidateWithTPMSimulator(t *testing.T) { assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) assert.Equal(t, "device.id.99999999", updch.Value) - err := NewError(ErrorBadAttestationStatementType, `permanent identifier does not match`). - WithAdditionalErrorDetail(). + err := NewDetailedError(ErrorBadAttestationStatementType, `permanent identifier does not match`). AddSubproblems(NewSubproblemWithIdentifier( ErrorRejectedIdentifierType, Identifier{Type: "permanent-identifier", Value: "device.id.99999999"}, - `challenge identifier "device.id.99999999" doesn't match any of the attested hardware identifiers [device.id.12345678]`, + `challenge identifier "device.id.99999999" doesn't match any of the attested hardware identifiers ["device.id.12345678"]`, )) assert.EqualError(t, updch.Error.Err, err.Err.Error()) diff --git a/acme/errors.go b/acme/errors.go index bd37e7bd..658ec6e0 100644 --- a/acme/errors.go +++ b/acme/errors.go @@ -298,20 +298,14 @@ func NewError(pt ProblemType, msg string, args ...interface{}) *Error { return newError(pt, errors.Errorf(msg, args...)) } -// AddSubproblems adds the Subproblems to Error. It -// returns the Error, allowing for fluent addition. -func (e *Error) AddSubproblems(subproblems ...Subproblem) *Error { - e.Subproblems = append(e.Subproblems, subproblems...) - return e +// NewDetailedError creates a new Error that includes the error +// message in the details, providing more information to the +// ACME client. +func NewDetailedError(pt ProblemType, msg string, args ...interface{}) *Error { + return NewError(pt, msg, args...).withDetail() } -// WithAdditionalErrorDetail adds the underlying error -// to the existing (default) ACME error detail, providing -// more information to the ACME client. -func (e *Error) WithAdditionalErrorDetail() *Error { - // prevent internal server errors from disclosing - // the internal error to the client at all times and - // prevent nil pointers. +func (e *Error) withDetail() *Error { if e == nil || e.Status >= 500 || e.Err == nil { return e } @@ -320,6 +314,13 @@ func (e *Error) WithAdditionalErrorDetail() *Error { return e } +// AddSubproblems adds the Subproblems to Error. It +// returns the Error, allowing for fluent addition. +func (e *Error) AddSubproblems(subproblems ...Subproblem) *Error { + e.Subproblems = append(e.Subproblems, subproblems...) + return e +} + // NewSubproblem creates a new Subproblem. The msg and args // are used to create a new error, which is set as the Detail, allowing // for more detailed error messages to be returned to the ACME client. @@ -383,6 +384,10 @@ func WrapError(typ ProblemType, err error, msg string, args ...interface{}) *Err } } +func WrapDetailedError(typ ProblemType, err error, msg string, args ...interface{}) *Error { + return WrapError(typ, err, msg, args...).withDetail() +} + // WrapErrorISE shortcut to wrap an internal server error type. func WrapErrorISE(err error, msg string, args ...interface{}) *Error { return WrapError(ErrorServerInternalType, err, msg, args...) diff --git a/acme/errors_test.go b/acme/errors_test.go index 98040739..8e586a12 100644 --- a/acme/errors_test.go +++ b/acme/errors_test.go @@ -22,8 +22,7 @@ func TestError_WithAdditionalErrorDetail(t *testing.T) { "detail": "The server experienced an internal error", "type": "urn:ietf:params:acme:error:serverInternal", }) - malformedErr := NewError(ErrorMalformedType, "malformed error") - malformedErr.Err = nil + malformedErr := NewError(ErrorMalformedType, "malformed error") // will result in Err == nil behavior malformedJSON := mustJSON(t, map[string]interface{}{ "detail": "The request message was malformed", "type": "urn:ietf:params:acme:error:malformed", @@ -37,9 +36,9 @@ func TestError_WithAdditionalErrorDetail(t *testing.T) { err *Error want string }{ - {"internal", NewError(ErrorServerInternalType, "").WithAdditionalErrorDetail(), internalJSON}, - {"nil err", malformedErr.WithAdditionalErrorDetail(), malformedJSON}, - {"detailed", NewError(ErrorBadAttestationStatementType, "invalid property").WithAdditionalErrorDetail(), withDetailJSON}, + {"internal", NewDetailedError(ErrorServerInternalType, ""), internalJSON}, + {"nil err", malformedErr, malformedJSON}, + {"detailed", NewDetailedError(ErrorBadAttestationStatementType, "invalid property"), withDetailJSON}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/acme/linker.go b/acme/linker.go index bddc21f1..e59db4ee 100644 --- a/acme/linker.go +++ b/acme/linker.go @@ -8,7 +8,7 @@ import ( "net/url" "strings" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/smallstep/certificates/api/render" "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/provisioner" diff --git a/api/api.go b/api/api.go index c9820351..7cf44a11 100644 --- a/api/api.go +++ b/api/api.go @@ -19,12 +19,13 @@ import ( "strings" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/pkg/errors" "go.step.sm/crypto/sshutil" "golang.org/x/crypto/ssh" "github.com/smallstep/certificates/api/log" + "github.com/smallstep/certificates/api/models" "github.com/smallstep/certificates/api/render" "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/config" @@ -231,6 +232,29 @@ type ProvisionersResponse struct { NextCursor string } +const redacted = "*** REDACTED ***" + +func scepFromProvisioner(p *provisioner.SCEP) *models.SCEP { + return &models.SCEP{ + ID: p.ID, + Type: p.Type, + Name: p.Name, + ForceCN: p.ForceCN, + ChallengePassword: redacted, + Capabilities: p.Capabilities, + IncludeRoot: p.IncludeRoot, + ExcludeIntermediate: p.ExcludeIntermediate, + MinimumPublicKeyLength: p.MinimumPublicKeyLength, + DecrypterCertificate: []byte(redacted), + DecrypterKeyPEM: []byte(redacted), + DecrypterKeyURI: redacted, + DecrypterKeyPassword: redacted, + EncryptionAlgorithmIdentifier: p.EncryptionAlgorithmIdentifier, + Options: p.Options, + Claims: p.Claims, + } +} + // MarshalJSON implements json.Marshaler. It marshals the ProvisionersResponse // into a byte slice. // @@ -238,24 +262,22 @@ type ProvisionersResponse struct { // challenge secret that MUST NOT be leaked in (public) HTTP responses. The // challenge value is thus redacted in HTTP responses. func (p ProvisionersResponse) MarshalJSON() ([]byte, error) { + var responseProvisioners provisioner.List for _, item := range p.Provisioners { scepProv, ok := item.(*provisioner.SCEP) if !ok { + responseProvisioners = append(responseProvisioners, item) continue } - old := scepProv.ChallengePassword - scepProv.ChallengePassword = "*** REDACTED ***" - defer func(p string) { //nolint:gocritic // defer in loop required to restore initial state of provisioners - scepProv.ChallengePassword = p - }(old) + responseProvisioners = append(responseProvisioners, scepFromProvisioner(scepProv)) } var list = struct { Provisioners []provisioner.Interface `json:"provisioners"` NextCursor string `json:"nextCursor"` }{ - Provisioners: []provisioner.Interface(p.Provisioners), + Provisioners: []provisioner.Interface(responseProvisioners), NextCursor: p.NextCursor, } diff --git a/api/api_test.go b/api/api_test.go index 1c90d91b..c57eef31 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -26,7 +26,7 @@ import ( "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/pkg/errors" sassert "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -803,7 +803,7 @@ func Test_CRLGeneration(t *testing.T) { } chiCtx := chi.NewRouteContext() - req := httptest.NewRequest("GET", "http://example.com/crl", nil) + req := httptest.NewRequest("GET", "http://example.com/crl", http.NoBody) req = req.WithContext(context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx)) for _, tt := range tests { @@ -856,7 +856,7 @@ func Test_caHandler_Route(t *testing.T) { } func Test_Health(t *testing.T) { - req := httptest.NewRequest("GET", "http://example.com/health", nil) + req := httptest.NewRequest("GET", "http://example.com/health", http.NoBody) w := httptest.NewRecorder() Health(w, req) @@ -890,7 +890,7 @@ func Test_Root(t *testing.T) { // Request with chi context chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("sha", "efc7d6b475a56fe587650bcdb999a4a308f815ba44db4bf0371ea68a786ccd36") - req := httptest.NewRequest("GET", "http://example.com/root/efc7d6b475a56fe587650bcdb999a4a308f815ba44db4bf0371ea68a786ccd36", nil) + req := httptest.NewRequest("GET", "http://example.com/root/efc7d6b475a56fe587650bcdb999a4a308f815ba44db4bf0371ea68a786ccd36", http.NoBody) req = req.WithContext(context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx)) expected := []byte(`{"ca":"` + strings.ReplaceAll(rootPEM, "\n", `\n`) + `\n"}`) @@ -1105,7 +1105,7 @@ func Test_Renew(t *testing.T) { return nil }, }) - req := httptest.NewRequest("POST", "http://example.com/renew", nil) + req := httptest.NewRequest("POST", "http://example.com/renew", http.NoBody) req.TLS = tt.tls req.Header = tt.header w := httptest.NewRecorder() @@ -1313,7 +1313,7 @@ func Test_ProvisionerKey(t *testing.T) { // Request with chi context chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("kid", "oV1p0MJeGQ7qBlK6B-oyfVdBRjh_e7VSK_YSEEqgW00") - req := httptest.NewRequest("GET", "http://example.com/provisioners/oV1p0MJeGQ7qBlK6B-oyfVdBRjh_e7VSK_YSEEqgW00/encrypted-key", nil) + req := httptest.NewRequest("GET", "http://example.com/provisioners/oV1p0MJeGQ7qBlK6B-oyfVdBRjh_e7VSK_YSEEqgW00/encrypted-key", http.NoBody) req = req.WithContext(context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx)) tests := []struct { @@ -1381,7 +1381,7 @@ func Test_Roots(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockMustAuthority(t, &mockAuthority{ret1: []*x509.Certificate{tt.root}, err: tt.err}) - req := httptest.NewRequest("GET", "http://example.com/roots", nil) + req := httptest.NewRequest("GET", "http://example.com/roots", http.NoBody) req.TLS = tt.tls w := httptest.NewRecorder() Roots(w, req) @@ -1422,7 +1422,7 @@ func Test_caHandler_RootsPEM(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockMustAuthority(t, &mockAuthority{ret1: tt.roots, err: tt.err}) - req := httptest.NewRequest("GET", "https://example.com/roots", nil) + req := httptest.NewRequest("GET", "https://example.com/roots", http.NoBody) w := httptest.NewRecorder() RootsPEM(w, req) res := w.Result() @@ -1467,7 +1467,7 @@ func Test_Federation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockMustAuthority(t, &mockAuthority{ret1: []*x509.Certificate{tt.root}, err: tt.err}) - req := httptest.NewRequest("GET", "http://example.com/federation", nil) + req := httptest.NewRequest("GET", "http://example.com/federation", http.NoBody) req.TLS = tt.tls w := httptest.NewRecorder() Federation(w, req) @@ -1569,7 +1569,6 @@ func mustCertificate(t *testing.T, pub, priv interface{}) *x509.Certificate { } func TestProvisionersResponse_MarshalJSON(t *testing.T) { - k := map[string]any{ "use": "sig", "kty": "EC", @@ -1581,9 +1580,9 @@ func TestProvisionersResponse_MarshalJSON(t *testing.T) { } key := squarejose.JSONWebKey{} b, err := json.Marshal(k) - assert.FatalError(t, err) + require.NoError(t, err) err = json.Unmarshal(b, &key) - assert.FatalError(t, err) + require.NoError(t, err) r := ProvisionersResponse{ Provisioners: provisioner.List{ @@ -1593,6 +1592,12 @@ func TestProvisionersResponse_MarshalJSON(t *testing.T) { ChallengePassword: "not-so-secret", MinimumPublicKeyLength: 2048, EncryptionAlgorithmIdentifier: 2, + IncludeRoot: true, + ExcludeIntermediate: true, + DecrypterCertificate: []byte{1, 2, 3, 4}, + DecrypterKeyPEM: []byte{5, 6, 7, 8}, + DecrypterKeyURI: "softkms:path=/path/to/private.key", + DecrypterKeyPassword: "super-secret-password", }, &provisioner.JWK{ EncryptedKey: "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJlbmMiOiJBMTI4R0NNIiwicDJjIjoxMDAwMDAsInAycyI6IlhOdmYxQjgxSUlLMFA2NUkwcmtGTGcifQ.XaN9zcPQeWt49zchUDm34FECUTHfQTn_.tmNHPQDqR3ebsWfd.9WZr3YVdeOyJh36vvx0VlRtluhvYp4K7jJ1KGDr1qypwZ3ziBVSNbYYQ71du7fTtrnfG1wgGTVR39tWSzBU-zwQ5hdV3rpMAaEbod5zeW6SHd95H3Bvcb43YiiqJFNL5sGZzFb7FqzVmpsZ1efiv6sZaGDHtnCAL6r12UG5EZuqGfM0jGCZitUz2m9TUKXJL5DJ7MOYbFfkCEsUBPDm_TInliSVn2kMJhFa0VOe5wZk5YOuYM3lNYW64HGtbf-llN2Xk-4O9TfeSPizBx9ZqGpeu8pz13efUDT2WL9tWo6-0UE-CrG0bScm8lFTncTkHcu49_a5NaUBkYlBjEiw.thPcx3t1AUcWuEygXIY3Fg", @@ -1609,7 +1614,14 @@ func TestProvisionersResponse_MarshalJSON(t *testing.T) { { "type": "scep", "name": "scep", + "forceCN": false, + "includeRoot": true, + "excludeIntermediate": true, "challenge": "*** REDACTED ***", + "decrypterCertificate": []byte("*** REDACTED ***"), + "decrypterKey": "*** REDACTED ***", + "decrypterKeyPEM": []byte("*** REDACTED ***"), + "decrypterKeyPassword": "*** REDACTED ***", "minimumPublicKeyLength": 2048, "encryptionAlgorithmIdentifier": 2, }, @@ -1646,6 +1658,12 @@ func TestProvisionersResponse_MarshalJSON(t *testing.T) { ChallengePassword: "not-so-secret", MinimumPublicKeyLength: 2048, EncryptionAlgorithmIdentifier: 2, + IncludeRoot: true, + ExcludeIntermediate: true, + DecrypterCertificate: []byte{1, 2, 3, 4}, + DecrypterKeyPEM: []byte{5, 6, 7, 8}, + DecrypterKeyURI: "softkms:path=/path/to/private.key", + DecrypterKeyPassword: "super-secret-password", }, &provisioner.JWK{ EncryptedKey: "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJlbmMiOiJBMTI4R0NNIiwicDJjIjoxMDAwMDAsInAycyI6IlhOdmYxQjgxSUlLMFA2NUkwcmtGTGcifQ.XaN9zcPQeWt49zchUDm34FECUTHfQTn_.tmNHPQDqR3ebsWfd.9WZr3YVdeOyJh36vvx0VlRtluhvYp4K7jJ1KGDr1qypwZ3ziBVSNbYYQ71du7fTtrnfG1wgGTVR39tWSzBU-zwQ5hdV3rpMAaEbod5zeW6SHd95H3Bvcb43YiiqJFNL5sGZzFb7FqzVmpsZ1efiv6sZaGDHtnCAL6r12UG5EZuqGfM0jGCZitUz2m9TUKXJL5DJ7MOYbFfkCEsUBPDm_TInliSVn2kMJhFa0VOe5wZk5YOuYM3lNYW64HGtbf-llN2Xk-4O9TfeSPizBx9ZqGpeu8pz13efUDT2WL9tWo6-0UE-CrG0bScm8lFTncTkHcu49_a5NaUBkYlBjEiw.thPcx3t1AUcWuEygXIY3Fg", diff --git a/api/models/scep.go b/api/models/scep.go new file mode 100644 index 00000000..f4aa1502 --- /dev/null +++ b/api/models/scep.go @@ -0,0 +1,118 @@ +package models + +import ( + "context" + "crypto/x509" + "errors" + + "github.com/smallstep/certificates/authority/provisioner" + "golang.org/x/crypto/ssh" +) + +var errDummyImplementation = errors.New("dummy implementation") + +// SCEP is the SCEP provisioner model used solely in CA API +// responses. All methods for the [provisioner.Interface] interface +// are implemented, but return a dummy error. +// TODO(hs): remove reliance on the interface for the API responses +type SCEP struct { + ID string `json:"-"` + Type string `json:"type"` + Name string `json:"name"` + ForceCN bool `json:"forceCN"` + ChallengePassword string `json:"challenge"` + Capabilities []string `json:"capabilities,omitempty"` + IncludeRoot bool `json:"includeRoot"` + ExcludeIntermediate bool `json:"excludeIntermediate"` + MinimumPublicKeyLength int `json:"minimumPublicKeyLength"` + DecrypterCertificate []byte `json:"decrypterCertificate"` + DecrypterKeyPEM []byte `json:"decrypterKeyPEM"` + DecrypterKeyURI string `json:"decrypterKey"` + DecrypterKeyPassword string `json:"decrypterKeyPassword"` + EncryptionAlgorithmIdentifier int `json:"encryptionAlgorithmIdentifier"` + Options *provisioner.Options `json:"options,omitempty"` + Claims *provisioner.Claims `json:"claims,omitempty"` +} + +// GetID returns the provisioner unique identifier. +func (s *SCEP) GetID() string { + if s.ID != "" { + return s.ID + } + return s.GetIDForToken() +} + +// GetIDForToken returns an identifier that will be used to load the provisioner +// from a token. +func (s *SCEP) GetIDForToken() string { + return "scep/" + s.Name +} + +// GetName returns the name of the provisioner. +func (s *SCEP) GetName() string { + return s.Name +} + +// GetType returns the type of provisioner. +func (s *SCEP) GetType() provisioner.Type { + return provisioner.TypeSCEP +} + +// GetEncryptedKey returns the base provisioner encrypted key if it's defined. +func (s *SCEP) GetEncryptedKey() (string, string, bool) { + return "", "", false +} + +// GetTokenID returns the identifier of the token. +func (s *SCEP) GetTokenID(string) (string, error) { + return "", errDummyImplementation +} + +// Init initializes and validates the fields of a SCEP type. +func (s *SCEP) Init(_ provisioner.Config) (err error) { + return errDummyImplementation +} + +// AuthorizeSign returns an unimplemented error. Provisioners should overwrite +// this method if they will support authorizing tokens for signing x509 Certificates. +func (s *SCEP) AuthorizeSign(context.Context, string) ([]provisioner.SignOption, error) { + return nil, errDummyImplementation +} + +// AuthorizeRevoke returns an unimplemented error. Provisioners should overwrite +// this method if they will support authorizing tokens for revoking x509 Certificates. +func (s *SCEP) AuthorizeRevoke(context.Context, string) error { + return errDummyImplementation +} + +// AuthorizeRenew returns an unimplemented error. Provisioners should overwrite +// this method if they will support authorizing tokens for renewing x509 Certificates. +func (s *SCEP) AuthorizeRenew(context.Context, *x509.Certificate) error { + return errDummyImplementation +} + +// AuthorizeSSHSign returns an unimplemented error. Provisioners should overwrite +// this method if they will support authorizing tokens for signing SSH Certificates. +func (s *SCEP) AuthorizeSSHSign(context.Context, string) ([]provisioner.SignOption, error) { + return nil, errDummyImplementation +} + +// AuthorizeRevoke returns an unimplemented error. Provisioners should overwrite +// this method if they will support authorizing tokens for revoking SSH Certificates. +func (s *SCEP) AuthorizeSSHRevoke(context.Context, string) error { + return errDummyImplementation +} + +// AuthorizeSSHRenew returns an unimplemented error. Provisioners should overwrite +// this method if they will support authorizing tokens for renewing SSH Certificates. +func (s *SCEP) AuthorizeSSHRenew(context.Context, string) (*ssh.Certificate, error) { + return nil, errDummyImplementation +} + +// AuthorizeSSHRekey returns an unimplemented error. Provisioners should overwrite +// this method if they will support authorizing tokens for rekeying SSH Certificates. +func (s *SCEP) AuthorizeSSHRekey(context.Context, string) (*ssh.Certificate, []provisioner.SignOption, error) { + return nil, nil, errDummyImplementation +} + +var _ provisioner.Interface = (*SCEP)(nil) diff --git a/api/ssh.go b/api/ssh.go index fbaa8c5a..9d0bbc14 100644 --- a/api/ssh.go +++ b/api/ssh.go @@ -317,7 +317,7 @@ func SSHSign(w http.ResponseWriter, r *http.Request) { var identityCertificate []Certificate if cr := body.IdentityCSR.CertificateRequest; cr != nil { ctx := authority.NewContextWithSkipTokenReuse(r.Context()) - ctx = provisioner.NewContextWithMethod(ctx, provisioner.SignMethod) + ctx = provisioner.NewContextWithMethod(ctx, provisioner.SignIdentityMethod) signOpts, err := a.Authorize(ctx, body.OTT) if err != nil { render.Error(w, errs.UnauthorizedErr(err)) diff --git a/authority/admin/api/acme_test.go b/authority/admin/api/acme_test.go index 6d478145..4c0af799 100644 --- a/authority/admin/api/acme_test.go +++ b/authority/admin/api/acme_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" @@ -128,7 +128,7 @@ func TestHandler_requireEABEnabled(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - req := httptest.NewRequest("GET", "/foo", nil).WithContext(tc.ctx) + req := httptest.NewRequest("GET", "/foo", http.NoBody).WithContext(tc.ctx) w := httptest.NewRecorder() requireEABEnabled(tc.next)(w, req) res := w.Result() @@ -223,7 +223,7 @@ func TestHandler_CreateExternalAccountKey(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { - req := httptest.NewRequest("POST", "/foo", nil) // chi routing is prepared in test setup + req := httptest.NewRequest("POST", "/foo", http.NoBody) // chi routing is prepared in test setup req = req.WithContext(tc.ctx) w := httptest.NewRecorder() acmeResponder := NewACMEAdminResponder() @@ -276,7 +276,7 @@ func TestHandler_DeleteExternalAccountKey(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { - req := httptest.NewRequest("DELETE", "/foo", nil) // chi routing is prepared in test setup + req := httptest.NewRequest("DELETE", "/foo", http.NoBody) // chi routing is prepared in test setup req = req.WithContext(tc.ctx) w := httptest.NewRecorder() acmeResponder := NewACMEAdminResponder() @@ -311,7 +311,7 @@ func TestHandler_GetExternalAccountKeys(t *testing.T) { "ok": func(t *testing.T) test { chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("provisionerName", "provName") - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) return test{ ctx: ctx, diff --git a/authority/admin/api/admin.go b/authority/admin/api/admin.go index c7adced3..e4d9d9fe 100644 --- a/authority/admin/api/admin.go +++ b/authority/admin/api/admin.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "go.step.sm/linkedca" diff --git a/authority/admin/api/admin_test.go b/authority/admin/api/admin_test.go index 3d4cdd9c..aae22056 100644 --- a/authority/admin/api/admin_test.go +++ b/authority/admin/api/admin_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/types/known/timestamppb" @@ -357,7 +357,7 @@ func TestHandler_GetAdmin(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { mockMustAuthority(t, tc.auth) - req := httptest.NewRequest("GET", "/foo", nil) // chi routing is prepared in test setup + req := httptest.NewRequest("GET", "/foo", http.NoBody) // chi routing is prepared in test setup req = req.WithContext(tc.ctx) w := httptest.NewRecorder() GetAdmin(w, req) @@ -406,7 +406,7 @@ func TestHandler_GetAdmins(t *testing.T) { } var tests = map[string]func(t *testing.T) test{ "fail/parse-cursor": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo?limit=A", nil) + req := httptest.NewRequest("GET", "/foo?limit=A", http.NoBody) return test{ ctx: context.Background(), req: req, @@ -420,7 +420,7 @@ func TestHandler_GetAdmins(t *testing.T) { } }, "fail/auth.GetAdmins": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) auth := &mockAdminAuthority{ MockGetAdmins: func(cursor string, limit int) ([]*linkedca.Admin, string, error) { assert.Equals(t, "", cursor) @@ -442,7 +442,7 @@ func TestHandler_GetAdmins(t *testing.T) { } }, "ok": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) createdAt := time.Now() var deletedAt time.Time adm1 := &linkedca.Admin{ @@ -764,7 +764,7 @@ func TestHandler_DeleteAdmin(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { mockMustAuthority(t, tc.auth) - req := httptest.NewRequest("DELETE", "/foo", nil) // chi routing is prepared in test setup + req := httptest.NewRequest("DELETE", "/foo", http.NoBody) // chi routing is prepared in test setup req = req.WithContext(tc.ctx) w := httptest.NewRecorder() DeleteAdmin(w, req) diff --git a/authority/admin/api/middleware.go b/authority/admin/api/middleware.go index 3c1b040a..fb29219f 100644 --- a/authority/admin/api/middleware.go +++ b/authority/admin/api/middleware.go @@ -4,7 +4,7 @@ import ( "errors" "net/http" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "go.step.sm/linkedca" diff --git a/authority/admin/api/middleware_test.go b/authority/admin/api/middleware_test.go index 4684b047..d166865f 100644 --- a/authority/admin/api/middleware_test.go +++ b/authority/admin/api/middleware_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/types/known/timestamppb" @@ -72,7 +72,7 @@ func TestHandler_requireAPIEnabled(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { mockMustAuthority(t, tc.auth) - req := httptest.NewRequest("GET", "/foo", nil) // chi routing is prepared in test setup + req := httptest.NewRequest("GET", "/foo", http.NoBody) // chi routing is prepared in test setup req = req.WithContext(tc.ctx) w := httptest.NewRecorder() requireAPIEnabled(tc.next)(w, req) @@ -113,7 +113,7 @@ func TestHandler_extractAuthorizeTokenAdmin(t *testing.T) { } var tests = map[string]func(t *testing.T) test{ "fail/missing-authorization-token": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req.Header["Authorization"] = []string{""} return test{ ctx: context.Background(), @@ -128,7 +128,7 @@ func TestHandler_extractAuthorizeTokenAdmin(t *testing.T) { } }, "fail/auth.AuthorizeAdminToken": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req.Header["Authorization"] = []string{"token"} auth := &mockAdminAuthority{ MockAuthorizeAdminToken: func(r *http.Request, token string) (*linkedca.Admin, error) { @@ -153,7 +153,7 @@ func TestHandler_extractAuthorizeTokenAdmin(t *testing.T) { } }, "ok": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req.Header["Authorization"] = []string{"token"} createdAt := time.Now() var deletedAt time.Time @@ -324,7 +324,7 @@ func TestHandler_loadProvisionerByName(t *testing.T) { t.Run(name, func(t *testing.T) { mockMustAuthority(t, tc.auth) ctx := admin.NewContext(tc.ctx, tc.adminDB) - req := httptest.NewRequest("GET", "/foo", nil) // chi routing is prepared in test setup + req := httptest.NewRequest("GET", "/foo", http.NoBody) // chi routing is prepared in test setup req = req.WithContext(ctx) w := httptest.NewRecorder() @@ -399,7 +399,7 @@ func TestHandler_checkAction(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { ctx := admin.NewContext(context.Background(), tc.adminDB) - req := httptest.NewRequest("GET", "/foo", nil).WithContext(ctx) + req := httptest.NewRequest("GET", "/foo", http.NoBody).WithContext(ctx) w := httptest.NewRecorder() checkAction(tc.next, tc.supportedInStandalone)(w, req) res := w.Result() @@ -643,7 +643,7 @@ func TestHandler_loadExternalAccountKey(t *testing.T) { tc := prep(t) t.Run(name, func(t *testing.T) { ctx := acme.NewDatabaseContext(tc.ctx, tc.acmeDB) - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() loadExternalAccountKey(tc.next)(w, req) diff --git a/authority/admin/api/policy_test.go b/authority/admin/api/policy_test.go index 1ec88fb6..159fc0e1 100644 --- a/authority/admin/api/policy_test.go +++ b/authority/admin/api/policy_test.go @@ -241,7 +241,7 @@ func TestPolicyAdminResponder_GetAuthorityPolicy(t *testing.T) { ctx := admin.NewContext(tc.ctx, tc.adminDB) par := NewPolicyAdminResponder() - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() @@ -1164,7 +1164,7 @@ func TestPolicyAdminResponder_GetProvisionerPolicy(t *testing.T) { ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) par := NewPolicyAdminResponder() - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() @@ -1986,7 +1986,7 @@ func TestPolicyAdminResponder_GetACMEAccountPolicy(t *testing.T) { ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) par := NewPolicyAdminResponder() - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) req = req.WithContext(ctx) w := httptest.NewRecorder() diff --git a/authority/admin/api/provisioner.go b/authority/admin/api/provisioner.go index c584361b..d44e9e03 100644 --- a/authority/admin/api/provisioner.go +++ b/authority/admin/api/provisioner.go @@ -4,7 +4,7 @@ import ( "fmt" "net/http" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "go.step.sm/crypto/sshutil" "go.step.sm/crypto/x509util" diff --git a/authority/admin/api/provisioner_test.go b/authority/admin/api/provisioner_test.go index 86f8a31b..9860d824 100644 --- a/authority/admin/api/provisioner_test.go +++ b/authority/admin/api/provisioner_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/encoding/protojson" @@ -37,7 +37,7 @@ func TestHandler_GetProvisioner(t *testing.T) { } var tests = map[string]func(t *testing.T) test{ "fail/auth.LoadProvisionerByID": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo?id=provID", nil) + req := httptest.NewRequest("GET", "/foo?id=provID", http.NoBody) chiCtx := chi.NewRouteContext() ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) auth := &mockAdminAuthority{ @@ -61,7 +61,7 @@ func TestHandler_GetProvisioner(t *testing.T) { } }, "fail/auth.LoadProvisionerByName": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("name", "provName") ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) @@ -86,7 +86,7 @@ func TestHandler_GetProvisioner(t *testing.T) { } }, "fail/db.GetProvisioner": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("name", "provName") ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) @@ -120,7 +120,7 @@ func TestHandler_GetProvisioner(t *testing.T) { } }, "ok": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("name", "provName") ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) @@ -208,7 +208,7 @@ func TestHandler_GetProvisioners(t *testing.T) { } var tests = map[string]func(t *testing.T) test{ "fail/parse-cursor": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo?limit=X", nil) + req := httptest.NewRequest("GET", "/foo?limit=X", http.NoBody) return test{ ctx: context.Background(), statusCode: 400, @@ -222,7 +222,7 @@ func TestHandler_GetProvisioners(t *testing.T) { } }, "fail/auth.GetProvisioners": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) auth := &mockAdminAuthority{ MockGetProvisioners: func(cursor string, limit int) (provisioner.List, string, error) { assert.Equals(t, "", cursor) @@ -244,7 +244,7 @@ func TestHandler_GetProvisioners(t *testing.T) { } }, "ok": func(t *testing.T) test { - req := httptest.NewRequest("GET", "/foo", nil) + req := httptest.NewRequest("GET", "/foo", http.NoBody) provisioners := provisioner.List{ &provisioner.OIDC{ Type: "OIDC", @@ -481,7 +481,7 @@ func TestHandler_DeleteProvisioner(t *testing.T) { } var tests = map[string]func(t *testing.T) test{ "fail/auth.LoadProvisionerByID": func(t *testing.T) test { - req := httptest.NewRequest("DELETE", "/foo?id=provID", nil) + req := httptest.NewRequest("DELETE", "/foo?id=provID", http.NoBody) chiCtx := chi.NewRouteContext() ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) auth := &mockAdminAuthority{ @@ -504,7 +504,7 @@ func TestHandler_DeleteProvisioner(t *testing.T) { } }, "fail/auth.LoadProvisionerByName": func(t *testing.T) test { - req := httptest.NewRequest("DELETE", "/foo", nil) + req := httptest.NewRequest("DELETE", "/foo", http.NoBody) chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("name", "provName") ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) @@ -528,7 +528,7 @@ func TestHandler_DeleteProvisioner(t *testing.T) { } }, "fail/auth.RemoveProvisioner": func(t *testing.T) test { - req := httptest.NewRequest("DELETE", "/foo", nil) + req := httptest.NewRequest("DELETE", "/foo", http.NoBody) chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("name", "provName") ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) @@ -560,7 +560,7 @@ func TestHandler_DeleteProvisioner(t *testing.T) { } }, "ok": func(t *testing.T) test { - req := httptest.NewRequest("DELETE", "/foo", nil) + req := httptest.NewRequest("DELETE", "/foo", http.NoBody) chiCtx := chi.NewRouteContext() chiCtx.URLParams.Add("name", "provName") ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx) diff --git a/authority/admin/api/webhook.go b/authority/admin/api/webhook.go index 3939d55e..f01ddb65 100644 --- a/authority/admin/api/webhook.go +++ b/authority/admin/api/webhook.go @@ -6,7 +6,7 @@ import ( "net/http" "net/url" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/smallstep/certificates/api/read" "github.com/smallstep/certificates/api/render" "github.com/smallstep/certificates/authority/admin" @@ -56,9 +56,7 @@ func validateWebhook(webhook *linkedca.Webhook) error { } // kind - switch webhook.Kind { - case linkedca.Webhook_ENRICHING, linkedca.Webhook_AUTHORIZING, linkedca.Webhook_SCEPCHALLENGE: - default: + if _, ok := linkedca.Webhook_Kind_name[int32(webhook.Kind)]; !ok || webhook.Kind == linkedca.Webhook_NO_KIND { return admin.NewError(admin.ErrorBadRequestType, "webhook kind %q is invalid", webhook.Kind) } diff --git a/authority/admin/api/webhook_test.go b/authority/admin/api/webhook_test.go index 0fb199f0..8f4ee1a2 100644 --- a/authority/admin/api/webhook_test.go +++ b/authority/admin/api/webhook_test.go @@ -6,11 +6,12 @@ import ( "encoding/json" "errors" "io" + "net/http" "net/http/httptest" "strings" "testing" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/admin" "github.com/stretchr/testify/assert" @@ -375,7 +376,7 @@ func TestWebhookAdminResponder_DeleteProvisionerWebhook(t *testing.T) { } ctx = linkedca.NewContextWithProvisioner(ctx, prov) ctx = admin.NewContext(ctx, &admin.MockDB{}) - req := httptest.NewRequest("DELETE", "/foo", nil).WithContext(ctx) + req := httptest.NewRequest("DELETE", "/foo", http.NoBody).WithContext(ctx) war := NewWebhookAdminResponder() diff --git a/authority/authority.go b/authority/authority.go index ae85c018..a4a76293 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto" + "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/hex" @@ -61,7 +62,9 @@ type Authority struct { x509Enforcers []provisioner.CertificateEnforcer // SCEP CA - scepService *scep.Service + scepOptions *scep.Options + validateSCEP bool + scepAuthority *scep.Authority // SSH CA sshHostPassword []byte @@ -122,6 +125,7 @@ func New(cfg *config.Config, opts ...Option) (*Authority, error) { var a = &Authority{ config: cfg, certificates: new(sync.Map), + validateSCEP: true, } // Apply options. @@ -261,6 +265,24 @@ func (a *Authority) ReloadAdminResources(ctx context.Context) error { a.config.AuthorityConfig.Admins = adminList a.admins = adminClxn + switch { + case a.requiresSCEP() && a.GetSCEP() == nil: + // TODO(hs): try to initialize SCEP here too? It's a bit + // problematic if this method is called as part of an update + // via Admin API and a password needs to be provided. + case a.requiresSCEP() && a.GetSCEP() != nil: + // update the SCEP Authority with the currently active SCEP + // provisioner names and revalidate the configuration. + a.scepAuthority.UpdateProvisioners(a.getSCEPProvisionerNames()) + if err := a.scepAuthority.Validate(); err != nil { + log.Printf("failed validating SCEP authority: %v\n", err) + } + case !a.requiresSCEP() && a.GetSCEP() != nil: + // TODO(hs): don't remove the authority if we can't also + // reload it. + //a.scepAuthority = nil + } + return nil } @@ -640,48 +662,83 @@ func (a *Authority) init() error { return err } - // Check if a KMS with decryption capability is required and available - if a.requiresDecrypter() { - if _, ok := a.keyManager.(kmsapi.Decrypter); !ok { - return errors.New("keymanager doesn't provide crypto.Decrypter") + // The SCEP functionality is provided through an instance of + // scep.Authority. It is initialized when the CA is started and + // if it doesn't exist yet. It gets refreshed if it already + // exists. If the SCEP authority is no longer required on reload, + // it gets removed. + // TODO(hs): reloading through SIGHUP doesn't hit these cases. This + // is because an entirely new authority.Authority is created, including + // a new scep.Authority. Look into this to see if we want this to + // keep working like that, or want to reuse a single instance and + // update that. + switch { + case a.requiresSCEP() && a.GetSCEP() == nil: + if a.scepOptions == nil { + options := &scep.Options{ + Roots: a.rootX509Certs, + Intermediates: a.intermediateX509Certs, + SignerCert: a.intermediateX509Certs[0], + } + if options.Signer, err = a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ + SigningKey: a.config.IntermediateKey, + Password: a.password, + }); err != nil { + return err + } + // TODO(hs): instead of creating the decrypter here, pass the + // intermediate key + chain down to the SCEP authority, + // and only instantiate it when required there. Is that possible? + // Also with entering passwords? + // TODO(hs): if moving the logic, try improving the logic for the + // decrypter password too? Right now it needs to be entered multiple + // times; I've observed it to be three times maximum, every time + // the intermediate key is read. + _, isRSA := options.Signer.Public().(*rsa.PublicKey) + if km, ok := a.keyManager.(kmsapi.Decrypter); ok && isRSA { + if decrypter, err := km.CreateDecrypter(&kmsapi.CreateDecrypterRequest{ + DecryptionKey: a.config.IntermediateKey, + Password: a.password, + }); err == nil { + // only pass the decrypter down when it was successfully created, + // meaning it's an RSA key, and `CreateDecrypter` did not fail. + options.Decrypter = decrypter + options.DecrypterCert = options.Intermediates[0] + } + } + + a.scepOptions = options } - } - // TODO: decide if this is a good approach for providing the SCEP functionality - // It currently mirrors the logic for the x509CAService - if a.requiresSCEPService() && a.scepService == nil { - var options scep.Options + // provide the current SCEP provisioner names, so that the provisioners + // can be validated when the CA is started. + a.scepOptions.SCEPProvisionerNames = a.getSCEPProvisionerNames() - // Read intermediate and create X509 signer and decrypter for default CAS. - options.CertificateChain, err = pemutil.ReadCertificateBundle(a.config.IntermediateCert) - if err != nil { - return err - } - options.CertificateChain = append(options.CertificateChain, a.rootX509Certs...) - options.Signer, err = a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ - SigningKey: a.config.IntermediateKey, - Password: a.password, - }) + // create a new SCEP authority + scepAuthority, err := scep.New(a, *a.scepOptions) if err != nil { return err } - if km, ok := a.keyManager.(kmsapi.Decrypter); ok { - options.Decrypter, err = km.CreateDecrypter(&kmsapi.CreateDecrypterRequest{ - DecryptionKey: a.config.IntermediateKey, - Password: a.password, - }) - if err != nil { - return err + if a.validateSCEP { + // validate the SCEP authority + if err := scepAuthority.Validate(); err != nil { + a.initLogf("failed validating SCEP authority: %v", err) } } - a.scepService, err = scep.NewService(ctx, options) - if err != nil { - return err + // set the SCEP authority + a.scepAuthority = scepAuthority + case !a.requiresSCEP() && a.GetSCEP() != nil: + // clear the SCEP authority if it's no longer required + a.scepAuthority = nil + case a.requiresSCEP() && a.GetSCEP() != nil: + // update the SCEP Authority with the currently active SCEP + // provisioner names and revalidate the configuration. + a.scepAuthority.UpdateProvisioners(a.getSCEPProvisionerNames()) + if err := a.scepAuthority.Validate(); err != nil { + log.Printf("failed validating SCEP authority: %v\n", err) } - - // TODO: mimick the x509CAService GetCertificateAuthority here too? } // Load X509 constraints engine. @@ -833,17 +890,9 @@ func (a *Authority) IsRevoked(sn string) (bool, error) { return a.db.IsRevoked(sn) } -// requiresDecrypter returns whether the Authority -// requires a KMS that provides a crypto.Decrypter -// Currently this is only required when SCEP is -// enabled. -func (a *Authority) requiresDecrypter() bool { - return a.requiresSCEPService() -} - -// requiresSCEPService iterates over the configured provisioners -// and determines if one of them is a SCEP provisioner. -func (a *Authority) requiresSCEPService() bool { +// requiresSCEP iterates over the configured provisioners +// and determines if at least one of them is a SCEP provisioner. +func (a *Authority) requiresSCEP() bool { for _, p := range a.config.AuthorityConfig.Provisioners { if p.GetType() == provisioner.TypeSCEP { return true @@ -852,13 +901,21 @@ func (a *Authority) requiresSCEPService() bool { return false } -// GetSCEPService returns the configured SCEP Service. -// -// TODO: this function is intended to exist temporarily in order to make SCEP -// work more easily. It can be made more correct by using the right -// interfaces/abstractions after it works as expected. -func (a *Authority) GetSCEPService() *scep.Service { - return a.scepService +// getSCEPProvisionerNames returns the names of the SCEP provisioners +// that are currently available in the CA. +func (a *Authority) getSCEPProvisionerNames() (names []string) { + for _, p := range a.config.AuthorityConfig.Provisioners { + if p.GetType() == provisioner.TypeSCEP { + names = append(names, p.GetName()) + } + } + + return +} + +// GetSCEP returns the configured SCEP Authority +func (a *Authority) GetSCEP() *scep.Authority { + return a.scepAuthority } func (a *Authority) startCRLGenerator() error { diff --git a/authority/authority_test.go b/authority/authority_test.go index 82a05a3e..45c7cd86 100644 --- a/authority/authority_test.go +++ b/authority/authority_test.go @@ -478,7 +478,7 @@ func testScepAuthority(t *testing.T, opts ...Option) *Authority { return a } -func TestAuthority_GetSCEPService(t *testing.T) { +func TestAuthority_GetSCEP(t *testing.T) { _ = testScepAuthority(t) p := provisioner.List{ &provisioner.SCEP{ @@ -542,7 +542,7 @@ func TestAuthority_GetSCEPService(t *testing.T) { return } if tt.wantService { - if got := a.GetSCEPService(); (got != nil) != tt.wantService { + if got := a.GetSCEP(); (got != nil) != tt.wantService { t.Errorf("Authority.GetSCEPService() = %v, wantService %v", got, tt.wantService) } } diff --git a/authority/authorize.go b/authority/authorize.go index 31855d5b..f14574a8 100644 --- a/authority/authorize.go +++ b/authority/authorize.go @@ -177,7 +177,7 @@ func (a *Authority) AuthorizeAdminToken(r *http.Request, token string) (*linkedc if !adminFound { return nil, admin.NewError(admin.ErrorUnauthorizedType, "adminHandler.authorizeToken; unable to load admin with subject(s) %s and provisioner '%s'", - adminSANs, claims.Issuer) + adminSANs, prov.GetName()) } if strings.HasPrefix(r.URL.Path, "/admin/admins") && (r.Method != "GET") && adm.Type != linkedca.Admin_SUPER_ADMIN { @@ -214,7 +214,7 @@ func (a *Authority) Authorize(ctx context.Context, token string) ([]provisioner. var opts = []interface{}{errs.WithKeyVal("token", token)} switch m := provisioner.MethodFromContext(ctx); m { - case provisioner.SignMethod: + case provisioner.SignMethod, provisioner.SignIdentityMethod: signOpts, err := a.authorizeSign(ctx, token) return signOpts, errs.Wrap(http.StatusInternalServerError, err, "authority.Authorize", opts...) case provisioner.RevokeMethod: diff --git a/authority/config/config.go b/authority/config/config.go index ae284fb9..ba581d8a 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -1,6 +1,7 @@ package config import ( + "bytes" "encoding/json" "fmt" "net" @@ -35,6 +36,9 @@ var ( // DefaultEnableSSHCA enable SSH CA features per provisioner or globally // for all provisioners. DefaultEnableSSHCA = false + // DefaultDisableSmallstepExtensions is the default value for the + // DisableSmallstepExtensions provisioner claim. + DefaultDisableSmallstepExtensions = false // DefaultCRLCacheDuration is the default cache duration for the CRL. DefaultCRLCacheDuration = &provisioner.Duration{Duration: 24 * time.Hour} // DefaultCRLExpiredDuration is the default duration in which expired @@ -43,18 +47,19 @@ var ( // GlobalProvisionerClaims is the default duration that expired certificates // remain in the CRL after expiration. GlobalProvisionerClaims = provisioner.Claims{ - MinTLSDur: &provisioner.Duration{Duration: 5 * time.Minute}, // TLS certs - MaxTLSDur: &provisioner.Duration{Duration: 24 * time.Hour}, - DefaultTLSDur: &provisioner.Duration{Duration: 24 * time.Hour}, - MinUserSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // User SSH certs - MaxUserSSHDur: &provisioner.Duration{Duration: 24 * time.Hour}, - DefaultUserSSHDur: &provisioner.Duration{Duration: 16 * time.Hour}, - MinHostSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // Host SSH certs - MaxHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour}, - DefaultHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour}, - EnableSSHCA: &DefaultEnableSSHCA, - DisableRenewal: &DefaultDisableRenewal, - AllowRenewalAfterExpiry: &DefaultAllowRenewalAfterExpiry, + MinTLSDur: &provisioner.Duration{Duration: 5 * time.Minute}, // TLS certs + MaxTLSDur: &provisioner.Duration{Duration: 24 * time.Hour}, + DefaultTLSDur: &provisioner.Duration{Duration: 24 * time.Hour}, + MinUserSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // User SSH certs + MaxUserSSHDur: &provisioner.Duration{Duration: 24 * time.Hour}, + DefaultUserSSHDur: &provisioner.Duration{Duration: 16 * time.Hour}, + MinHostSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // Host SSH certs + MaxHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour}, + DefaultHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour}, + EnableSSHCA: &DefaultEnableSSHCA, + DisableRenewal: &DefaultDisableRenewal, + AllowRenewalAfterExpiry: &DefaultAllowRenewalAfterExpiry, + DisableSmallstepExtensions: &DefaultDisableSmallstepExtensions, } ) @@ -254,15 +259,16 @@ func (c *Config) Init() { // Save saves the configuration to the given filename. func (c *Config) Save(filename string) error { - f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - return errors.Wrapf(err, "error opening %s", filename) - } - defer f.Close() - - enc := json.NewEncoder(f) + var b bytes.Buffer + enc := json.NewEncoder(&b) enc.SetIndent("", "\t") - return errors.Wrapf(enc.Encode(c), "error writing %s", filename) + if err := enc.Encode(c); err != nil { + return fmt.Errorf("error encoding configuration: %w", err) + } + if err := os.WriteFile(filename, b.Bytes(), 0600); err != nil { + return fmt.Errorf("error writing %q: %w", filename, err) + } + return nil } // Commit saves the current configuration to the same diff --git a/authority/options.go b/authority/options.go index bf443ed6..4fc5a20f 100644 --- a/authority/options.go +++ b/authority/options.go @@ -18,6 +18,7 @@ import ( "github.com/smallstep/certificates/cas" casapi "github.com/smallstep/certificates/cas/apiv1" "github.com/smallstep/certificates/db" + "github.com/smallstep/certificates/scep" ) // Option sets options to the Authority. @@ -205,6 +206,17 @@ func WithX509SignerFunc(fn func() ([]*x509.Certificate, crypto.Signer, error)) O } } +// WithFullSCEPOptions defines the options used for SCEP support. +// +// This feature is EXPERIMENTAL and might change at any time. +func WithFullSCEPOptions(options *scep.Options) Option { + return func(a *Authority) error { + a.scepOptions = options + a.validateSCEP = false + return nil + } +} + // WithSSHUserSigner defines the signer used to sign SSH user certificates. func WithSSHUserSigner(s crypto.Signer) Option { return func(a *Authority) error { diff --git a/authority/provisioner/acme.go b/authority/provisioner/acme.go index d52bbe0a..96f37d58 100644 --- a/authority/provisioner/acme.go +++ b/authority/provisioner/acme.go @@ -257,7 +257,7 @@ func (p *ACME) AuthorizeSign(context.Context, string) ([]SignOption, error) { opts := []SignOption{ p, // modifiers / withOptions - newProvisionerExtensionOption(TypeACME, p.Name, ""), + newProvisionerExtensionOption(TypeACME, p.Name, "").WithControllerOptions(p.ctl), newForceCNOption(p.ForceCN), profileDefaultDuration(p.ctl.Claimer.DefaultTLSCertDuration()), // validators diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index 11b18ebb..e95feedd 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -25,6 +25,8 @@ import ( "github.com/smallstep/certificates/errs" "github.com/smallstep/certificates/webhook" + + _ "embed" ) // awsIssuer is the string used as issuer in the generated tokens. @@ -50,148 +52,10 @@ const awsMetadataTokenHeader = "X-aws-ec2-metadata-token" //nolint:gosec // no c const awsMetadataTokenTTLHeader = "X-aws-ec2-metadata-token-ttl-seconds" //nolint:gosec // no credentials here // awsCertificate is the certificate used to validate the instance identity -// signature. -// -// The first certificate is used in: -// -// ap-northeast-2, ap-south-1, ap-southeast-1, ap-southeast-2 -// eu-central-1, eu-north-1, eu-west-1, eu-west-2, eu-west-3 -// us-east-1, us-east-2, us-west-1, us-west-2 -// ca-central-1, sa-east-1 -// -// The second certificate is used in: -// -// eu-south-1 -// -// The third certificate is used in: -// -// ap-east-1 -// -// The fourth certificate is used in: -// -// af-south-1 -// -// The fifth certificate is used in: -// -// me-south-1 -// -// The sixth certificate is used in: -// -// me-central-1 -// -// The seventh certificate is used in: +// signature. It is embedded in the binary at compile time. // -// ap-southeast-3 -const awsCertificate = `-----BEGIN CERTIFICATE----- -MIIDIjCCAougAwIBAgIJAKnL4UEDMN/FMA0GCSqGSIb3DQEBBQUAMGoxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRgw -FgYDVQQKEw9BbWF6b24uY29tIEluYy4xGjAYBgNVBAMTEWVjMi5hbWF6b25hd3Mu -Y29tMB4XDTE0MDYwNTE0MjgwMloXDTI0MDYwNTE0MjgwMlowajELMAkGA1UEBhMC -VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxGDAWBgNV -BAoTD0FtYXpvbi5jb20gSW5jLjEaMBgGA1UEAxMRZWMyLmFtYXpvbmF3cy5jb20w -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIe9GN//SRK2knbjySG0ho3yqQM3 -e2TDhWO8D2e8+XZqck754gFSo99AbT2RmXClambI7xsYHZFapbELC4H91ycihvrD -jbST1ZjkLQgga0NE1q43eS68ZeTDccScXQSNivSlzJZS8HJZjgqzBlXjZftjtdJL -XeE4hwvo0sD4f3j9AgMBAAGjgc8wgcwwHQYDVR0OBBYEFCXWzAgVyrbwnFncFFIs -77VBdlE4MIGcBgNVHSMEgZQwgZGAFCXWzAgVyrbwnFncFFIs77VBdlE4oW6kbDBq -MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2Vh -dHRsZTEYMBYGA1UEChMPQW1hem9uLmNvbSBJbmMuMRowGAYDVQQDExFlYzIuYW1h -em9uYXdzLmNvbYIJAKnL4UEDMN/FMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADgYEAFYcz1OgEhQBXIwIdsgCOS8vEtiJYF+j9uO6jz7VOmJqO+pRlAbRlvY8T -C1haGgSI/A1uZUKs/Zfnph0oEI0/hu1IIJ/SKBDtN5lvmZ/IzbOPIJWirlsllQIQ -7zvWbGd9c9+Rm3p04oTvhup99la7kZqevJK0QRdD/6NpCKsqP/0= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICNjCCAZ+gAwIBAgIJAOZ3GEIaDcugMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV -BAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0 -dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0xOTEwMjQx -NTE5MDlaGA8yMTk5MDMyOTE1MTkwOVowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgT -EFdhc2hpbmd0b24gU3RhdGUxEDAOBgNVBAcTB1NlYXR0bGUxIDAeBgNVBAoTF0Ft -YXpvbiBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB -gQCjiPgW3vsXRj4JoA16WQDyoPc/eh3QBARaApJEc4nPIGoUolpAXcjFhWplo2O+ -ivgfCsc4AU9OpYdAPha3spLey/bhHPRi1JZHRNqScKP0hzsCNmKhfnZTIEQCFvsp -DRp4zr91/WS06/flJFBYJ6JHhp0KwM81XQG59lV6kkoW7QIDAQABMA0GCSqGSIb3 -DQEBCwUAA4GBAGLLrY3P+HH6C57dYgtJkuGZGT2+rMkk2n81/abzTJvsqRqGRrWv -XRKRXlKdM/dfiuYGokDGxiC0Mg6TYy6wvsR2qRhtXW1OtZkiHWcQCnOttz+8vpew -wx8JGMvowtuKB1iMsbwyRqZkFYLcvH+Opfb/Aayi20/ChQLdI6M2R5VU ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICSzCCAbQCCQDtQvkVxRvK9TANBgkqhkiG9w0BAQsFADBqMQswCQYDVQQGEwJV -UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2VhdHRsZTEYMBYGA1UE -ChMPQW1hem9uLmNvbSBJbmMuMRowGAYDVQQDExFlYzIuYW1hem9uYXdzLmNvbTAe -Fw0xOTAyMDMwMzAwMDZaFw0yOTAyMDIwMzAwMDZaMGoxCzAJBgNVBAYTAlVTMRMw -EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRgwFgYDVQQKEw9B -bWF6b24uY29tIEluYy4xGjAYBgNVBAMTEWVjMi5hbWF6b25hd3MuY29tMIGfMA0G -CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1kkHXYTfc7gY5Q55JJhjTieHAgacaQkiR -Pity9QPDE3b+NXDh4UdP1xdIw73JcIIG3sG9RhWiXVCHh6KkuCTqJfPUknIKk8vs -M3RXflUpBe8Pf+P92pxqPMCz1Fr2NehS3JhhpkCZVGxxwLC5gaG0Lr4rFORubjYY -Rh84dK98VwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAA6xV9f0HMqXjPHuGILDyaNN -dKcvplNFwDTydVg32MNubAGnecoEBtUPtxBsLoVYXCOb+b5/ZMDubPF9tU/vSXuo -TpYM5Bq57gJzDRaBOntQbX9bgHiUxw6XZWaTS/6xjRJDT5p3S1E0mPI3lP/eJv4o -Ezk5zb3eIf10/sqt4756 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICNjCCAZ+gAwIBAgIJAKumfZiRrNvHMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV -BAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0 -dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0xOTExMjcw -NzE0MDVaGA8yMTk5MDUwMjA3MTQwNVowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgT -EFdhc2hpbmd0b24gU3RhdGUxEDAOBgNVBAcTB1NlYXR0bGUxIDAeBgNVBAoTF0Ft -YXpvbiBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB -gQDFd571nUzVtke3rPyRkYfvs3jh0C0EMzzG72boyUNjnfw1+m0TeFraTLKb9T6F -7TuB/ZEN+vmlYqr2+5Va8U8qLbPF0bRH+FdaKjhgWZdYXxGzQzU3ioy5W5ZM1VyB -7iUsxEAlxsybC3ziPYaHI42UiTkQNahmoroNeqVyHNnBpQIDAQABMA0GCSqGSIb3 -DQEBCwUAA4GBAAJLylWyElEgOpW4B1XPyRVD4pAds8Guw2+krgqkY0HxLCdjosuH -RytGDGN+q75aAoXzW5a7SGpxLxk6Hfv0xp3RjDHsoeP0i1d8MD3hAC5ezxS4oukK -s5gbPOnokhKTMPXbTdRn5ZifCbWlx+bYN/mTYKvxho7b5SVg2o1La9aK ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDPDCCAqWgAwIBAgIJAMl6uIV/zqJFMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMSAw -HgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzEaMBgGA1UEAwwRZWMyLmFt -YXpvbmF3cy5jb20wIBcNMTkwNDI2MTQzMjQ3WhgPMjE5ODA5MjkxNDMyNDdaMHIx -CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0 -dGxlMSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzEaMBgGA1UEAwwR -ZWMyLmFtYXpvbmF3cy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALVN -CDTZEnIeoX1SEYqq6k1BV0ZlpY5y3KnoOreCAE589TwS4MX5+8Fzd6AmACmugeBP -Qk7Hm6b2+g/d4tWycyxLaQlcq81DB1GmXehRkZRgGeRge1ePWd1TUA0I8P/QBT7S -gUePm/kANSFU+P7s7u1NNl+vynyi0wUUrw7/wIZTAgMBAAGjgdcwgdQwHQYDVR0O -BBYEFILtMd+T4YgH1cgc+hVsVOV+480FMIGkBgNVHSMEgZwwgZmAFILtMd+T4YgH -1cgc+hVsVOV+480FoXakdDByMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGlu -Z3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEgMB4GA1UECgwXQW1hem9uIFdlYiBTZXJ2 -aWNlcyBMTEMxGjAYBgNVBAMMEWVjMi5hbWF6b25hd3MuY29tggkAyXq4hX/OokUw -DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQBhkNTBIFgWFd+ZhC/LhRUY -4OjEiykmbEp6hlzQ79T0Tfbn5A4NYDI2icBP0+hmf6qSnIhwJF6typyd1yPK5Fqt -NTpxxcXmUKquX+pHmIkK1LKDO8rNE84jqxrxRsfDi6by82fjVYf2pgjJW8R1FAw+ -mL5WQRFexbfB5aXhcMo0AA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICMzCCAZygAwIBAgIGAXjRrnDjMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT -AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl -MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTA0MTQxODM5 -MzNaGA8yMjAwMDQxNDE4MzkzM1owXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh -c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv -biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDc -aTgW/KyA6zyruJQrYy00a6wqLA7eeUzk3bMiTkLsTeDQfrkaZMfBAjGaaOymRo1C -3qzE4rIenmahvUplu9ZmLwL1idWXMRX2RlSvIt+d2SeoKOKQWoc2UOFZMHYxDue7 -zkyk1CIRaBukTeY13/RIrlc6X61zJ5BBtZXlHwayjQIDAQABMA0GCSqGSIb3DQEB -BQUAA4GBABTqTy3R6RXKPW45FA+cgo7YZEj/Cnz5YaoUivRRdX2A83BHuBTvJE2+ -WX00FTEj4hRVjameE1nENoO8Z7fUVloAFDlDo69fhkJeSvn51D1WRrPnoWGgEfr1 -+OfK1bAcKTtfkkkP9r4RdwSjKzO5Zu/B+Wqm3kVEz/QNcz6npmA6 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICMzCCAZygAwIBAgIGAXbVDG2yMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT -AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl -MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTAxMDYwMDE1 -MzBaGA8yMjAwMDEwNjAwMTUzMFowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh -c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv -biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn -CS/Vbt0gQ1ebWcur2hSO7PnJifE4OPxQ7RgSAlc4/spJp1sDP+ZrS0LO1ZJfKhXf -1R9S3AUwLnsc7b+IuVXdY5LK9RKqu64nyXP5dx170zoL8loEyCSuRR2fs+04i2Qs -WBVP+KFNAn7P5L1EHRjkgTO8kjNKviwRV+OkP9ab5wIDAQABMA0GCSqGSIb3DQEB -BQUAA4GBAI4WUy6+DKh0JDSzQEZNyBgNlSoSuC2owtMxCwGB6nBfzzfcekWvs6eo -fLTSGovrReX7MtVgrcJBZjmPIentw5dWUs+87w/g9lNwUnUt0ZHYyh2tuBG6hVJu -UEwDJ/z3wDd6wQviLOTF3MITawt9P8siR1hXqLJNxpjRQFZrgHqi ------END CERTIFICATE-----` +//go:embed aws_certificates.pem +var awsCertificate string // awsSignatureAlgorithm is the signature algorithm used to verify the identity // document signature. @@ -472,7 +336,7 @@ func (p *AWS) Init(config Config) (err error) { // AuthorizeSign validates the given token and returns the sign options that // will be used on certificate creation. -func (p *AWS) AuthorizeSign(_ context.Context, token string) ([]SignOption, error) { +func (p *AWS) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { payload, err := p.authorizeToken(token) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "aws.AuthorizeSign") @@ -499,7 +363,7 @@ func (p *AWS) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro net.ParseIP(doc.PrivateIP), }), emailAddressesValidator(nil), - urisValidator(nil), + newURIsValidator(ctx, nil), ) // Template options @@ -515,7 +379,7 @@ func (p *AWS) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro p, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeAWS, p.Name, doc.AccountID, "InstanceID", doc.InstanceID), + newProvisionerExtensionOption(TypeAWS, p.Name, doc.AccountID, "InstanceID", doc.InstanceID).WithControllerOptions(p.ctl), profileDefaultDuration(p.ctl.Claimer.DefaultTLSCertDuration()), // validators defaultPublicKeyValidator{}, diff --git a/authority/provisioner/aws_certificates.pem b/authority/provisioner/aws_certificates.pem new file mode 100644 index 00000000..d9b5f639 --- /dev/null +++ b/authority/provisioner/aws_certificates.pem @@ -0,0 +1,247 @@ +# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/verify-signature.html + +# default certificate for "other regions" +-----BEGIN CERTIFICATE----- +MIIDIjCCAougAwIBAgIJAKnL4UEDMN/FMA0GCSqGSIb3DQEBBQUAMGoxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRgw +FgYDVQQKEw9BbWF6b24uY29tIEluYy4xGjAYBgNVBAMTEWVjMi5hbWF6b25hd3Mu +Y29tMB4XDTE0MDYwNTE0MjgwMloXDTI0MDYwNTE0MjgwMlowajELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxGDAWBgNV +BAoTD0FtYXpvbi5jb20gSW5jLjEaMBgGA1UEAxMRZWMyLmFtYXpvbmF3cy5jb20w +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIe9GN//SRK2knbjySG0ho3yqQM3 +e2TDhWO8D2e8+XZqck754gFSo99AbT2RmXClambI7xsYHZFapbELC4H91ycihvrD +jbST1ZjkLQgga0NE1q43eS68ZeTDccScXQSNivSlzJZS8HJZjgqzBlXjZftjtdJL +XeE4hwvo0sD4f3j9AgMBAAGjgc8wgcwwHQYDVR0OBBYEFCXWzAgVyrbwnFncFFIs +77VBdlE4MIGcBgNVHSMEgZQwgZGAFCXWzAgVyrbwnFncFFIs77VBdlE4oW6kbDBq +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2Vh +dHRsZTEYMBYGA1UEChMPQW1hem9uLmNvbSBJbmMuMRowGAYDVQQDExFlYzIuYW1h +em9uYXdzLmNvbYIJAKnL4UEDMN/FMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF +BQADgYEAFYcz1OgEhQBXIwIdsgCOS8vEtiJYF+j9uO6jz7VOmJqO+pRlAbRlvY8T +C1haGgSI/A1uZUKs/Zfnph0oEI0/hu1IIJ/SKBDtN5lvmZ/IzbOPIJWirlsllQIQ +7zvWbGd9c9+Rm3p04oTvhup99la7kZqevJK0QRdD/6NpCKsqP/0= +-----END CERTIFICATE----- + +# certificate for eu-south-1 +-----BEGIN CERTIFICATE----- +MIICNjCCAZ+gAwIBAgIJAOZ3GEIaDcugMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV +BAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0 +dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0xOTEwMjQx +NTE5MDlaGA8yMTk5MDMyOTE1MTkwOVowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgT +EFdhc2hpbmd0b24gU3RhdGUxEDAOBgNVBAcTB1NlYXR0bGUxIDAeBgNVBAoTF0Ft +YXpvbiBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCjiPgW3vsXRj4JoA16WQDyoPc/eh3QBARaApJEc4nPIGoUolpAXcjFhWplo2O+ +ivgfCsc4AU9OpYdAPha3spLey/bhHPRi1JZHRNqScKP0hzsCNmKhfnZTIEQCFvsp +DRp4zr91/WS06/flJFBYJ6JHhp0KwM81XQG59lV6kkoW7QIDAQABMA0GCSqGSIb3 +DQEBCwUAA4GBAGLLrY3P+HH6C57dYgtJkuGZGT2+rMkk2n81/abzTJvsqRqGRrWv +XRKRXlKdM/dfiuYGokDGxiC0Mg6TYy6wvsR2qRhtXW1OtZkiHWcQCnOttz+8vpew +wx8JGMvowtuKB1iMsbwyRqZkFYLcvH+Opfb/Aayi20/ChQLdI6M2R5VU +-----END CERTIFICATE----- + +# certificate for ap-east-1 +-----BEGIN CERTIFICATE----- +MIICSzCCAbQCCQDtQvkVxRvK9TANBgkqhkiG9w0BAQsFADBqMQswCQYDVQQGEwJV +UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2VhdHRsZTEYMBYGA1UE +ChMPQW1hem9uLmNvbSBJbmMuMRowGAYDVQQDExFlYzIuYW1hem9uYXdzLmNvbTAe +Fw0xOTAyMDMwMzAwMDZaFw0yOTAyMDIwMzAwMDZaMGoxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRgwFgYDVQQKEw9B +bWF6b24uY29tIEluYy4xGjAYBgNVBAMTEWVjMi5hbWF6b25hd3MuY29tMIGfMA0G +CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1kkHXYTfc7gY5Q55JJhjTieHAgacaQkiR +Pity9QPDE3b+NXDh4UdP1xdIw73JcIIG3sG9RhWiXVCHh6KkuCTqJfPUknIKk8vs +M3RXflUpBe8Pf+P92pxqPMCz1Fr2NehS3JhhpkCZVGxxwLC5gaG0Lr4rFORubjYY +Rh84dK98VwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAA6xV9f0HMqXjPHuGILDyaNN +dKcvplNFwDTydVg32MNubAGnecoEBtUPtxBsLoVYXCOb+b5/ZMDubPF9tU/vSXuo +TpYM5Bq57gJzDRaBOntQbX9bgHiUxw6XZWaTS/6xjRJDT5p3S1E0mPI3lP/eJv4o +Ezk5zb3eIf10/sqt4756 +-----END CERTIFICATE----- + +# certificate for af-south-1 +-----BEGIN CERTIFICATE----- +MIICNjCCAZ+gAwIBAgIJAKumfZiRrNvHMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV +BAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0 +dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0xOTExMjcw +NzE0MDVaGA8yMTk5MDUwMjA3MTQwNVowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgT +EFdhc2hpbmd0b24gU3RhdGUxEDAOBgNVBAcTB1NlYXR0bGUxIDAeBgNVBAoTF0Ft +YXpvbiBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQDFd571nUzVtke3rPyRkYfvs3jh0C0EMzzG72boyUNjnfw1+m0TeFraTLKb9T6F +7TuB/ZEN+vmlYqr2+5Va8U8qLbPF0bRH+FdaKjhgWZdYXxGzQzU3ioy5W5ZM1VyB +7iUsxEAlxsybC3ziPYaHI42UiTkQNahmoroNeqVyHNnBpQIDAQABMA0GCSqGSIb3 +DQEBCwUAA4GBAAJLylWyElEgOpW4B1XPyRVD4pAds8Guw2+krgqkY0HxLCdjosuH +RytGDGN+q75aAoXzW5a7SGpxLxk6Hfv0xp3RjDHsoeP0i1d8MD3hAC5ezxS4oukK +s5gbPOnokhKTMPXbTdRn5ZifCbWlx+bYN/mTYKvxho7b5SVg2o1La9aK +-----END CERTIFICATE----- + +# certificate for me-south-1 +-----BEGIN CERTIFICATE----- +MIIDPDCCAqWgAwIBAgIJAMl6uIV/zqJFMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMSAw +HgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzEaMBgGA1UEAwwRZWMyLmFt +YXpvbmF3cy5jb20wIBcNMTkwNDI2MTQzMjQ3WhgPMjE5ODA5MjkxNDMyNDdaMHIx +CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0 +dGxlMSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzEaMBgGA1UEAwwR +ZWMyLmFtYXpvbmF3cy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALVN +CDTZEnIeoX1SEYqq6k1BV0ZlpY5y3KnoOreCAE589TwS4MX5+8Fzd6AmACmugeBP +Qk7Hm6b2+g/d4tWycyxLaQlcq81DB1GmXehRkZRgGeRge1ePWd1TUA0I8P/QBT7S +gUePm/kANSFU+P7s7u1NNl+vynyi0wUUrw7/wIZTAgMBAAGjgdcwgdQwHQYDVR0O +BBYEFILtMd+T4YgH1cgc+hVsVOV+480FMIGkBgNVHSMEgZwwgZmAFILtMd+T4YgH +1cgc+hVsVOV+480FoXakdDByMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGlu +Z3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEgMB4GA1UECgwXQW1hem9uIFdlYiBTZXJ2 +aWNlcyBMTEMxGjAYBgNVBAMMEWVjMi5hbWF6b25hd3MuY29tggkAyXq4hX/OokUw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQBhkNTBIFgWFd+ZhC/LhRUY +4OjEiykmbEp6hlzQ79T0Tfbn5A4NYDI2icBP0+hmf6qSnIhwJF6typyd1yPK5Fqt +NTpxxcXmUKquX+pHmIkK1LKDO8rNE84jqxrxRsfDi6by82fjVYf2pgjJW8R1FAw+ +mL5WQRFexbfB5aXhcMo0AA== +-----END CERTIFICATE----- + +# certificate for cn-north-1, cn-northwest-1 +-----BEGIN CERTIFICATE----- +MIIDCzCCAnSgAwIBAgIJALSOMbOoU2svMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV +BAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0 +dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0yMzA3MDQw +ODM1MzlaFw0yODA3MDIwODM1MzlaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBX +YXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6 +b24gV2ViIFNlcnZpY2VzIExMQzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +uhhUNlqAZdcWWB/OSDVDGk3OA99EFzOn/mJlmciQ/Xwu2dFJWmSCqEAE6gjufCjQ +q3voxAhC2CF+elKtJW/C0Sz/LYo60PUqd6iXF4h+upB9HkOOGuWHXsHBTsvgkgGA +1CGgel4U0Cdq+23eANr8N8m28UzljjSnTlrYCHtzN4sCAwEAAaOB1DCB0TALBgNV +HQ8EBAMCB4AwHQYDVR0OBBYEFBkZu3wT27NnYgrfH+xJz4HJaNJoMIGOBgNVHSME +gYYwgYOAFBkZu3wT27NnYgrfH+xJz4HJaNJooWCkXjBcMQswCQYDVQQGEwJVUzEZ +MBcGA1UECBMQV2FzaGluZ3RvbiBTdGF0ZTEQMA4GA1UEBxMHU2VhdHRsZTEgMB4G +A1UEChMXQW1hem9uIFdlYiBTZXJ2aWNlcyBMTEOCCQC0jjGzqFNrLzASBgNVHRMB +Af8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBCwUAA4GBAECji43p+oPkYqmzll7e8Hgb +oADS0ph+YUz5P/bUCm61wFjlxaTfwKcuTR3ytj7bFLoW5Bm7Sa+TCl3lOGb2taon +2h+9NirRK6JYk87LMNvbS40HGPFumJL2NzEsGUeK+MRiWu+Oh5/lJGii3qw4YByx +SUDlRyNy1jJFstEZjOhs +-----END CERTIFICATE----- + +# certificate for eu-central-2 +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIGAXjSGFGiMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT +AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl +MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTA0MTQyMDM1 +MTJaGA8yMjAwMDQxNDIwMzUxMlowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh +c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv +biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2 +mdGdps5Rz2jzYcGNsgETTGUthJRrVqSnUWJXTlVaIbkGPLKO6Or7AfWKFp2sgRJ8 +vLsjoBVR5cESVK7cuK1wItjvJyi/opKZAUusJx2hpgU3pUHhlp9ATh/VeVD582jT +d9IY+8t5MDa6Z3fGliByEiXz0LEHdi8MBacLREu1TwIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBAILlpoE3k9o7KdALAxsFJNitVS+g3RMzdbiFM+7MA63Nv5fsf+0xgcjS +NBElvPCDKFvTJl4QQhToy056llO5GvdS9RK+H8xrP2mrqngApoKTApv93vHBixgF +Sn5KrczRO0YSm3OjkqbydU7DFlmkXXR7GYE+5jbHvQHYiT1J5sMu +-----END CERTIFICATE----- + +# certificate for ap-south-2 +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIGAXjwLj9CMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT +AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl +MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTA0MjAxNjQ3 +NDVaGA8yMjAwMDQyMDE2NDc0NVowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh +c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv +biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDT +wHu0ND+sFcobrjvcAYm0PNRD8f4R1jAzvoLt2+qGeOTAyO1Httj6cmsYN3AP1hN5 +iYuppFiYsl2eNPa/CD0Vg0BAfDFlV5rzjpA0j7TJabVh4kj7JvtD+xYMi6wEQA4x +6SPONY4OeZ2+8o/HS8nucpWDVdPRO6ciWUlMhjmDmwIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBAAy6sgTdRkTqELHBeWj69q60xHyUmsWqHAQNXKVc9ApWGG4onzuqlMbG +ETwUZ9mTq2vxlV0KvuetCDNS5u4cJsxe/TGGbYP0yP2qfMl0cCImzRI5W0gn8gog +dervfeT7nH5ih0TWEy/QDWfkQ601L4erm4yh4YQq8vcqAPSkf04N +-----END CERTIFICATE----- + +# certificate for ap-southeast-3 +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIGAXbVDG2yMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT +AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl +MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTAxMDYwMDE1 +MzBaGA8yMjAwMDEwNjAwMTUzMFowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh +c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv +biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn +CS/Vbt0gQ1ebWcur2hSO7PnJifE4OPxQ7RgSAlc4/spJp1sDP+ZrS0LO1ZJfKhXf +1R9S3AUwLnsc7b+IuVXdY5LK9RKqu64nyXP5dx170zoL8loEyCSuRR2fs+04i2Qs +WBVP+KFNAn7P5L1EHRjkgTO8kjNKviwRV+OkP9ab5wIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBAI4WUy6+DKh0JDSzQEZNyBgNlSoSuC2owtMxCwGB6nBfzzfcekWvs6eo +fLTSGovrReX7MtVgrcJBZjmPIentw5dWUs+87w/g9lNwUnUt0ZHYyh2tuBG6hVJu +UEwDJ/z3wDd6wQviLOTF3MITawt9P8siR1hXqLJNxpjRQFZrgHqi +-----END CERTIFICATE----- + +# certificate for ap-southeast-4 +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIGAXjSh40SMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT +AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl +MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTA0MTQyMjM2 +NDJaGA8yMjAwMDQxNDIyMzY0MlowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh +c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv +biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDH +ezwQr2VQpQSTW5TXNefiQrP+qWTGAbGsPeMX4hBMjAJUKys2NIRcRZaLM/BCew2F +IPVjNtlaj6Gwn9ipU4Mlz3zIwAMWi1AvGMSreppt+wV6MRtfOjh0Dvj/veJe88aE +ZJMozNgkJFRS+WFWsckQeL56tf6kY6QTlNo8V/0CsQIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBAF7vpPghH0FRo5gu49EArRNPrIvW1egMdZHrzJNqbztLCtV/wcgkqIww +uXYj+1rhlL+/iMpQWjdVGEqIZSeXn5fLmdx50eegFCwND837r9e8XYTiQS143Sxt +9+Yi6BZ7U7YD8kK9NBWoJxFqUeHdpRCs0O7COjT3gwm7ZxvAmssh +-----END CERTIFICATE----- + +# certificate for eu-south-2 +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIGAXjwLkiaMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT +AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl +MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTA0MjAxNjQ3 +NDhaGA8yMjAwMDQyMDE2NDc0OFowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh +c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv +biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDB +/VvR1+45Aey5zn3vPk6xBm5o9grSDL6D2iAuprQnfVXn8CIbSDbWFhA3fi5ippjK +kh3sl8VyCvCOUXKdOaNrYBrPRkrdHdBuL2Tc84RO+3m/rxIUZ2IK1fDlC6sWAjdd +f6sBrV2w2a78H0H8EwuwiSgttURBjwJ7KPPJCqaqrQIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBAKR+FzqQDzun/iMMzcFucmLMl5BxEblrFXOz7IIuOeiGkndmrqUeDCyk +ztLku45s7hxdNy4ltTuVAaE5aNBdw5J8U1mRvsKvHLy2ThH6hAWKwTqtPAJp7M21 +GDwgDDOkPSz6XVOehg+hBgiphYp84DUbWVYeP8YqLEJSqscKscWC +-----END CERTIFICATE----- + +# certificate for il-central-1 +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIGAX0QQGVLMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT +AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl +MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTExMTExODI2 +MzVaGA8yMjAwMTExMTE4MjYzNVowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh +c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv +biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr +c24u3AgFxnoPgzxR6yFXOamcPuxYXhYKWmapb+S8vOy5hpLoRe4RkOrY0cM3bN07 +GdEMlin5mU0y1t8y3ct4YewvmkgT42kTyMM+t1K4S0xsqjXxxS716uGYh7eWtkxr +Cihj8AbXN/6pa095h+7TZyl2n83keiNUzM2KoqQVMwIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBADwA6VVEIIZD2YL00F12po40xDLzIc9XvqFPS9iFaWi2ho8wLio7wA49 +VYEFZSI9CR3SGB9tL8DUib97mlxmd1AcGShMmMlhSB29vhuhrUNB/FmU7H8s62/j +D6cOR1A1cClIyZUe1yT1ZbPySCs43J+Thr8i8FSRxzDBSZZi5foW +-----END CERTIFICATE----- + +# certificate for me-central-1 +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIGAXjRrnDjMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT +AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl +MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMTA0MTQxODM5 +MzNaGA8yMjAwMDQxNDE4MzkzM1owXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh +c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv +biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDc +aTgW/KyA6zyruJQrYy00a6wqLA7eeUzk3bMiTkLsTeDQfrkaZMfBAjGaaOymRo1C +3qzE4rIenmahvUplu9ZmLwL1idWXMRX2RlSvIt+d2SeoKOKQWoc2UOFZMHYxDue7 +zkyk1CIRaBukTeY13/RIrlc6X61zJ5BBtZXlHwayjQIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBABTqTy3R6RXKPW45FA+cgo7YZEj/Cnz5YaoUivRRdX2A83BHuBTvJE2+ +WX00FTEj4hRVjameE1nENoO8Z7fUVloAFDlDo69fhkJeSvn51D1WRrPnoWGgEfr1 ++OfK1bAcKTtfkkkP9r4RdwSjKzO5Zu/B+Wqm3kVEz/QNcz6npmA6 +-----END CERTIFICATE----- + +# certificate for us-gov-east-1 and us-gov-west-1 +-----BEGIN CERTIFICATE----- +MIIDCzCCAnSgAwIBAgIJAIe9Hnq82O7UMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV +BAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0 +dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0yMTA3MTQx +NDI3NTdaFw0yNDA3MTMxNDI3NTdaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBX +YXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6 +b24gV2ViIFNlcnZpY2VzIExMQzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +qaIcGFFTx/SO1W5G91jHvyQdGP25n1Y91aXCuOOWAUTvSvNGpXrI4AXNrQF+CmIO +C4beBASnHCx082jYudWBBl9Wiza0psYc9flrczSzVLMmN8w/c78F/95NfiQdnUQP +pvgqcMeJo82cgHkLR7XoFWgMrZJqrcUK0gnsQcb6kakCAwEAAaOB1DCB0TALBgNV +HQ8EBAMCB4AwHQYDVR0OBBYEFNWV53gWJz72F5B1ZVY4O/dfFYBPMIGOBgNVHSME +gYYwgYOAFNWV53gWJz72F5B1ZVY4O/dfFYBPoWCkXjBcMQswCQYDVQQGEwJVUzEZ +MBcGA1UECBMQV2FzaGluZ3RvbiBTdGF0ZTEQMA4GA1UEBxMHU2VhdHRsZTEgMB4G +A1UEChMXQW1hem9uIFdlYiBTZXJ2aWNlcyBMTEOCCQCHvR56vNju1DASBgNVHRMB +Af8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBCwUAA4GBACrKjWj460GUPZCGm3/z0dIz +M2BPuH769wcOsqfFZcMKEysSFK91tVtUb1soFwH4/Lb/T0PqNrvtEwD1Nva5k0h2 +xZhNNRmDuhOhW1K9wCcnHGRBwY5t4lYL6hNV6hcrqYwGMjTjcAjBG2yMgznSNFle +Rwi/S3BFXISixNx9cILu +-----END CERTIFICATE----- \ No newline at end of file diff --git a/authority/provisioner/aws_test.go b/authority/provisioner/aws_test.go index 668bc13b..02be1ba9 100644 --- a/authority/provisioner/aws_test.go +++ b/authority/provisioner/aws_test.go @@ -695,8 +695,9 @@ func TestAWS_AuthorizeSign(t *testing.T) { assert.Equals(t, []net.IP(v), []net.IP{net.ParseIP("127.0.0.1")}) case emailAddressesValidator: assert.Equals(t, v, nil) - case urisValidator: - assert.Equals(t, v, nil) + case *urisValidator: + assert.Equals(t, v.uris, nil) + assert.Equals(t, MethodFromContext(v.ctx), SignMethod) case dnsNamesValidator: assert.Equals(t, []string(v), []string{"ip-127-0-0-1.us-west-1.compute.internal"}) case *x509NamePolicyValidator: @@ -873,3 +874,27 @@ func TestAWS_AuthorizeRenew(t *testing.T) { }) } } + +func TestAWS_HardcodedCertificates(t *testing.T) { + certBytes := []byte(awsCertificate) + + var certs []*x509.Certificate + for len(certBytes) > 0 { + var block *pem.Block + block, certBytes = pem.Decode(certBytes) + if block == nil { + break + } + if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { + continue + } + + cert, err := x509.ParseCertificate(block.Bytes) + assert.FatalError(t, err) + + // check that the certificate is not expired + assert.True(t, cert.NotAfter.After(time.Now())) + certs = append(certs, cert) + } + assert.Len(t, 14, certs, "expected 14 certificates in aws_certificates.pem") +} diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index 1c70a132..a9d5d1fa 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -316,7 +316,7 @@ func (p *Azure) authorizeToken(token string) (*azurePayload, string, string, str // AuthorizeSign validates the given token and returns the sign options that // will be used on certificate creation. -func (p *Azure) AuthorizeSign(_ context.Context, token string) ([]SignOption, error) { +func (p *Azure) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { _, name, group, subscription, identityObjectID, err := p.authorizeToken(token) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "azure.AuthorizeSign") @@ -382,7 +382,7 @@ func (p *Azure) AuthorizeSign(_ context.Context, token string) ([]SignOption, er dnsNamesValidator([]string{name}), ipAddressesValidator(nil), emailAddressesValidator(nil), - urisValidator(nil), + newURIsValidator(ctx, nil), ) // Enforce SANs in the template. @@ -398,7 +398,7 @@ func (p *Azure) AuthorizeSign(_ context.Context, token string) ([]SignOption, er p, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeAzure, p.Name, p.TenantID), + newProvisionerExtensionOption(TypeAzure, p.Name, p.TenantID).WithControllerOptions(p.ctl), profileDefaultDuration(p.ctl.Claimer.DefaultTLSCertDuration()), // validators defaultPublicKeyValidator{}, diff --git a/authority/provisioner/azure_test.go b/authority/provisioner/azure_test.go index 51d46c5a..f262ffbc 100644 --- a/authority/provisioner/azure_test.go +++ b/authority/provisioner/azure_test.go @@ -560,8 +560,9 @@ func TestAzure_AuthorizeSign(t *testing.T) { assert.Equals(t, v, nil) case emailAddressesValidator: assert.Equals(t, v, nil) - case urisValidator: - assert.Equals(t, v, nil) + case *urisValidator: + assert.Equals(t, v.uris, nil) + assert.Equals(t, MethodFromContext(v.ctx), SignMethod) case dnsNamesValidator: assert.Equals(t, []string(v), []string{"virtualMachine"}) case *x509NamePolicyValidator: diff --git a/authority/provisioner/claims.go b/authority/provisioner/claims.go index b6a5a81e..dcf679b3 100644 --- a/authority/provisioner/claims.go +++ b/authority/provisioner/claims.go @@ -26,6 +26,9 @@ type Claims struct { // Renewal properties DisableRenewal *bool `json:"disableRenewal,omitempty"` AllowRenewalAfterExpiry *bool `json:"allowRenewalAfterExpiry,omitempty"` + + // Other properties + DisableSmallstepExtensions *bool `json:"disableSmallstepExtensions,omitempty"` } // Claimer is the type that controls claims. It provides an interface around the @@ -47,20 +50,22 @@ func (c *Claimer) Claims() Claims { disableRenewal := c.IsDisableRenewal() allowRenewalAfterExpiry := c.AllowRenewalAfterExpiry() enableSSHCA := c.IsSSHCAEnabled() + disableSmallstepExtensions := c.IsDisableSmallstepExtensions() return Claims{ - MinTLSDur: &Duration{c.MinTLSCertDuration()}, - MaxTLSDur: &Duration{c.MaxTLSCertDuration()}, - DefaultTLSDur: &Duration{c.DefaultTLSCertDuration()}, - MinUserSSHDur: &Duration{c.MinUserSSHCertDuration()}, - MaxUserSSHDur: &Duration{c.MaxUserSSHCertDuration()}, - DefaultUserSSHDur: &Duration{c.DefaultUserSSHCertDuration()}, - MinHostSSHDur: &Duration{c.MinHostSSHCertDuration()}, - MaxHostSSHDur: &Duration{c.MaxHostSSHCertDuration()}, - DefaultHostSSHDur: &Duration{c.DefaultHostSSHCertDuration()}, - EnableSSHCA: &enableSSHCA, - DisableRenewal: &disableRenewal, - AllowRenewalAfterExpiry: &allowRenewalAfterExpiry, + MinTLSDur: &Duration{c.MinTLSCertDuration()}, + MaxTLSDur: &Duration{c.MaxTLSCertDuration()}, + DefaultTLSDur: &Duration{c.DefaultTLSCertDuration()}, + MinUserSSHDur: &Duration{c.MinUserSSHCertDuration()}, + MaxUserSSHDur: &Duration{c.MaxUserSSHCertDuration()}, + DefaultUserSSHDur: &Duration{c.DefaultUserSSHCertDuration()}, + MinHostSSHDur: &Duration{c.MinHostSSHCertDuration()}, + MaxHostSSHDur: &Duration{c.MaxHostSSHCertDuration()}, + DefaultHostSSHDur: &Duration{c.DefaultHostSSHCertDuration()}, + EnableSSHCA: &enableSSHCA, + DisableRenewal: &disableRenewal, + AllowRenewalAfterExpiry: &allowRenewalAfterExpiry, + DisableSmallstepExtensions: &disableSmallstepExtensions, } } @@ -110,6 +115,15 @@ func (c *Claimer) IsDisableRenewal() bool { return *c.claims.DisableRenewal } +// IsDisableSmallstepExtensions returns whether Smallstep extensions, such as +// the provisioner extension, should be excluded from the certificate. +func (c *Claimer) IsDisableSmallstepExtensions() bool { + if c.claims == nil || c.claims.DisableSmallstepExtensions == nil { + return *c.global.DisableSmallstepExtensions + } + return *c.claims.DisableSmallstepExtensions +} + // AllowRenewalAfterExpiry returns if the renewal flow is authorized if the // certificate is expired. If the property is not set within the provisioner // then the global value from the authority configuration will be used. diff --git a/authority/provisioner/gcp.go b/authority/provisioner/gcp.go index 8634fecc..2296b1b0 100644 --- a/authority/provisioner/gcp.go +++ b/authority/provisioner/gcp.go @@ -223,7 +223,7 @@ func (p *GCP) Init(config Config) (err error) { // AuthorizeSign validates the given token and returns the sign options that // will be used on certificate creation. -func (p *GCP) AuthorizeSign(_ context.Context, token string) ([]SignOption, error) { +func (p *GCP) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { claims, err := p.authorizeToken(token) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "gcp.AuthorizeSign") @@ -254,7 +254,7 @@ func (p *GCP) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro }), ipAddressesValidator(nil), emailAddressesValidator(nil), - urisValidator(nil), + newURIsValidator(ctx, nil), ) // Template SANs @@ -270,7 +270,7 @@ func (p *GCP) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro p, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeGCP, p.Name, claims.Subject, "InstanceID", ce.InstanceID, "InstanceName", ce.InstanceName), + newProvisionerExtensionOption(TypeGCP, p.Name, claims.Subject, "InstanceID", ce.InstanceID, "InstanceName", ce.InstanceName).WithControllerOptions(p.ctl), profileDefaultDuration(p.ctl.Claimer.DefaultTLSCertDuration()), // validators defaultPublicKeyValidator{}, diff --git a/authority/provisioner/gcp_test.go b/authority/provisioner/gcp_test.go index 7705b44a..ef791614 100644 --- a/authority/provisioner/gcp_test.go +++ b/authority/provisioner/gcp_test.go @@ -567,8 +567,9 @@ func TestGCP_AuthorizeSign(t *testing.T) { assert.Equals(t, v, nil) case emailAddressesValidator: assert.Equals(t, v, nil) - case urisValidator: - assert.Equals(t, v, nil) + case *urisValidator: + assert.Equals(t, v.uris, nil) + assert.Equals(t, MethodFromContext(v.ctx), SignMethod) case dnsNamesValidator: assert.Equals(t, []string(v), []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}) case *x509NamePolicyValidator: diff --git a/authority/provisioner/jwk.go b/authority/provisioner/jwk.go index 45012d0e..3a7512b8 100644 --- a/authority/provisioner/jwk.go +++ b/authority/provisioner/jwk.go @@ -150,7 +150,7 @@ func (p *JWK) AuthorizeRevoke(_ context.Context, token string) error { } // AuthorizeSign validates the given token. -func (p *JWK) AuthorizeSign(_ context.Context, token string) ([]SignOption, error) { +func (p *JWK) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { claims, err := p.authorizeToken(token, p.ctl.Audiences.Sign) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "jwk.AuthorizeSign") @@ -187,12 +187,12 @@ func (p *JWK) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro self, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeJWK, p.Name, p.Key.KeyID), + newProvisionerExtensionOption(TypeJWK, p.Name, p.Key.KeyID).WithControllerOptions(p.ctl), profileDefaultDuration(p.ctl.Claimer.DefaultTLSCertDuration()), // validators - commonNameValidator(claims.Subject), + commonNameSliceValidator(append([]string{claims.Subject}, claims.SANs...)), defaultPublicKeyValidator{}, - defaultSANsValidator(claims.SANs), + newDefaultSANsValidator(ctx, claims.SANs), newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()), newX509NamePolicyValidator(p.ctl.getPolicy().getX509()), p.ctl.newWebhookController(data, linkedca.Webhook_X509), diff --git a/authority/provisioner/jwk_test.go b/authority/provisioner/jwk_test.go index 19cee4fb..c688e914 100644 --- a/authority/provisioner/jwk_test.go +++ b/authority/provisioner/jwk_test.go @@ -309,14 +309,15 @@ func TestJWK_AuthorizeSign(t *testing.T) { assert.Len(t, 0, v.KeyValuePairs) case profileDefaultDuration: assert.Equals(t, time.Duration(v), tt.prov.ctl.Claimer.DefaultTLSCertDuration()) - case commonNameValidator: - assert.Equals(t, string(v), "subject") + case commonNameSliceValidator: + assert.Equals(t, []string(v), append([]string{"subject"}, tt.sans...)) case defaultPublicKeyValidator: case *validityValidator: assert.Equals(t, v.min, tt.prov.ctl.Claimer.MinTLSCertDuration()) assert.Equals(t, v.max, tt.prov.ctl.Claimer.MaxTLSCertDuration()) - case defaultSANsValidator: - assert.Equals(t, []string(v), tt.sans) + case *defaultSANsValidator: + assert.Equals(t, v.sans, tt.sans) + assert.Equals(t, MethodFromContext(v.ctx), SignMethod) case *x509NamePolicyValidator: assert.Equals(t, nil, v.policyEngine) case *WebhookController: diff --git a/authority/provisioner/k8sSA.go b/authority/provisioner/k8sSA.go index eb7084b3..96267d1c 100644 --- a/authority/provisioner/k8sSA.go +++ b/authority/provisioner/k8sSA.go @@ -238,7 +238,7 @@ func (p *K8sSA) AuthorizeSign(_ context.Context, token string) ([]SignOption, er p, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeK8sSA, p.Name, ""), + newProvisionerExtensionOption(TypeK8sSA, p.Name, "").WithControllerOptions(p.ctl), profileDefaultDuration(p.ctl.Claimer.DefaultTLSCertDuration()), // validators defaultPublicKeyValidator{}, diff --git a/authority/provisioner/method.go b/authority/provisioner/method.go index 01dda2ed..19aa6224 100644 --- a/authority/provisioner/method.go +++ b/authority/provisioner/method.go @@ -14,6 +14,8 @@ type methodKey struct{} const ( // SignMethod is the method used to sign X.509 certificates. SignMethod Method = iota + // SignIdentityMethod is the method used to sign X.509 identity certificates. + SignIdentityMethod // RevokeMethod is the method used to revoke X.509 certificates. RevokeMethod // RenewMethod is the method used to renew X.509 certificates. @@ -33,6 +35,8 @@ func (m Method) String() string { switch m { case SignMethod: return "sign-method" + case SignIdentityMethod: + return "sign-identity-method" case RevokeMethod: return "revoke-method" case RenewMethod: diff --git a/authority/provisioner/nebula.go b/authority/provisioner/nebula.go index 9d418303..66c523dc 100644 --- a/authority/provisioner/nebula.go +++ b/authority/provisioner/nebula.go @@ -150,7 +150,7 @@ func (p *Nebula) AuthorizeSign(_ context.Context, token string) ([]SignOption, e p, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeNebula, p.Name, ""), + newProvisionerExtensionOption(TypeNebula, p.Name, "").WithControllerOptions(p.ctl), profileLimitDuration{ def: p.ctl.Claimer.DefaultTLSCertDuration(), notBefore: crt.Details.NotBefore, @@ -389,7 +389,7 @@ func (v nebulaSANsValidator) Valid(req *x509.CertificateRequest) error { } } if len(req.URIs) > 0 { - if err := urisValidator(uris).Valid(req); err != nil { + if err := newURIsValidator(context.Background(), uris).Valid(req); err != nil { return err } } diff --git a/authority/provisioner/oidc.go b/authority/provisioner/oidc.go index 882d0972..06823e2f 100644 --- a/authority/provisioner/oidc.go +++ b/authority/provisioner/oidc.go @@ -351,7 +351,7 @@ func (o *OIDC) AuthorizeSign(_ context.Context, token string) ([]SignOption, err o, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID), + newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID).WithControllerOptions(o.ctl), profileDefaultDuration(o.ctl.Claimer.DefaultTLSCertDuration()), // validators defaultPublicKeyValidator{}, diff --git a/authority/provisioner/scep.go b/authority/provisioner/scep.go index b0acc8fe..a48d11cc 100644 --- a/authority/provisioner/scep.go +++ b/authority/provisioner/scep.go @@ -2,13 +2,20 @@ package provisioner import ( "context" + "crypto" + "crypto/rsa" "crypto/subtle" + "crypto/x509" + "encoding/pem" "fmt" "net/http" "time" "github.com/pkg/errors" + "go.step.sm/crypto/kms" + kmsapi "go.step.sm/crypto/kms/apiv1" + "go.step.sm/crypto/kms/uri" "go.step.sm/linkedca" "github.com/smallstep/certificates/webhook" @@ -29,9 +36,19 @@ type SCEP struct { // intermediate in the GetCACerts response IncludeRoot bool `json:"includeRoot,omitempty"` + // ExcludeIntermediate makes the provisioner skip the intermediate CA in the + // GetCACerts response + ExcludeIntermediate bool `json:"excludeIntermediate,omitempty"` + // MinimumPublicKeyLength is the minimum length for public keys in CSRs MinimumPublicKeyLength int `json:"minimumPublicKeyLength,omitempty"` + // TODO(hs): also support a separate signer configuration? + DecrypterCertificate []byte `json:"decrypterCertificate,omitempty"` + DecrypterKeyPEM []byte `json:"decrypterKeyPEM,omitempty"` + DecrypterKeyURI string `json:"decrypterKey,omitempty"` + DecrypterKeyPassword string `json:"decrypterKeyPassword,omitempty"` + // Numerical identifier for the ContentEncryptionAlgorithm as defined in github.com/mozilla-services/pkcs7 // at https://github.com/mozilla-services/pkcs7/blob/33d05740a3526e382af6395d3513e73d4e66d1cb/encrypt.go#L63 // Defaults to 0, being DES-CBC @@ -41,6 +58,12 @@ type SCEP struct { ctl *Controller encryptionAlgorithm int challengeValidationController *challengeValidationController + notificationController *notificationController + keyManager kmsapi.KeyManager + decrypter crypto.Decrypter + decrypterCertificate *x509.Certificate + signer crypto.Signer + signerCertificate *x509.Certificate } // GetID returns the provisioner unique identifier. @@ -113,7 +136,8 @@ func newChallengeValidationController(client *http.Client, webhooks []*Webhook) } var ( - ErrSCEPChallengeInvalid = errors.New("webhook server did not allow request") + ErrSCEPChallengeInvalid = errors.New("webhook server did not allow request") + ErrSCEPNotificationFailed = errors.New("scep notification failed") ) // Validate executes zero or more configured webhooks to @@ -122,12 +146,15 @@ var ( // that case, the other webhooks will be skipped. If none of // the webhooks indicates the value of the challenge was accepted, // an error is returned. -func (c *challengeValidationController) Validate(ctx context.Context, challenge, transactionID string) error { +func (c *challengeValidationController) Validate(ctx context.Context, csr *x509.CertificateRequest, provisionerName, challenge, transactionID string) error { for _, wh := range c.webhooks { - req := &webhook.RequestBody{ - SCEPChallenge: challenge, - SCEPTransactionID: transactionID, + req, err := webhook.NewRequestBody(webhook.WithX509CertificateRequest(csr)) + if err != nil { + return fmt.Errorf("failed creating new webhook request: %w", err) } + req.ProvisionerName = provisionerName + req.SCEPChallenge = challenge + req.SCEPTransactionID = transactionID resp, err := wh.DoWithContext(ctx, c.client, req, nil) // TODO(hs): support templated URL? Requires some refactoring if err != nil { return fmt.Errorf("failed executing webhook request: %w", err) @@ -140,6 +167,63 @@ func (c *challengeValidationController) Validate(ctx context.Context, challenge, return ErrSCEPChallengeInvalid } +type notificationController struct { + client *http.Client + webhooks []*Webhook +} + +// newNotificationController creates a new notificationController +// that performs SCEP notifications through webhooks. +func newNotificationController(client *http.Client, webhooks []*Webhook) *notificationController { + scepHooks := []*Webhook{} + for _, wh := range webhooks { + if wh.Kind != linkedca.Webhook_NOTIFYING.String() { + continue + } + if !isCertTypeOK(wh) { + continue + } + scepHooks = append(scepHooks, wh) + } + return ¬ificationController{ + client: client, + webhooks: scepHooks, + } +} + +func (c *notificationController) Success(ctx context.Context, csr *x509.CertificateRequest, cert *x509.Certificate, transactionID string) error { + for _, wh := range c.webhooks { + req, err := webhook.NewRequestBody(webhook.WithX509CertificateRequest(csr), webhook.WithX509Certificate(nil, cert)) // TODO(hs): pass in the x509util.Certifiate too? + if err != nil { + return fmt.Errorf("failed creating new webhook request: %w", err) + } + req.X509Certificate.Raw = cert.Raw // adding the full certificate DER bytes + req.SCEPTransactionID = transactionID + if _, err = wh.DoWithContext(ctx, c.client, req, nil); err != nil { + return fmt.Errorf("failed executing webhook request: %w: %w", ErrSCEPNotificationFailed, err) + } + } + + return nil +} + +func (c *notificationController) Failure(ctx context.Context, csr *x509.CertificateRequest, transactionID string, errorCode int, errorDescription string) error { + for _, wh := range c.webhooks { + req, err := webhook.NewRequestBody(webhook.WithX509CertificateRequest(csr)) + if err != nil { + return fmt.Errorf("failed creating new webhook request: %w", err) + } + req.SCEPTransactionID = transactionID + req.SCEPErrorCode = errorCode + req.SCEPErrorDescription = errorDescription + if _, err = wh.DoWithContext(ctx, c.client, req, nil); err != nil { + return fmt.Errorf("failed executing webhook request: %w: %w", ErrSCEPNotificationFailed, err) + } + } + + return nil +} + // isCertTypeOK returns whether or not the webhook can be used // with the SCEP challenge validation webhook controller. func isCertTypeOK(wh *Webhook) bool { @@ -162,21 +246,139 @@ func (s *SCEP) Init(config Config) (err error) { if s.MinimumPublicKeyLength == 0 { s.MinimumPublicKeyLength = 2048 } - if s.MinimumPublicKeyLength%8 != 0 { return errors.Errorf("%d bits is not exactly divisible by 8", s.MinimumPublicKeyLength) } + // Set the encryption algorithm to use s.encryptionAlgorithm = s.EncryptionAlgorithmIdentifier // TODO(hs): we might want to upgrade the default security to AES-CBC? if s.encryptionAlgorithm < 0 || s.encryptionAlgorithm > 4 { return errors.New("only encryption algorithm identifiers from 0 to 4 are valid") } + // Prepare the SCEP challenge validator s.challengeValidationController = newChallengeValidationController( config.WebhookClient, s.GetOptions().GetWebhooks(), ) + // Prepare the SCEP notification controller + s.notificationController = newNotificationController( + config.WebhookClient, + s.GetOptions().GetWebhooks(), + ) + + // parse the decrypter key PEM contents if available + if decryptionKeyPEM := s.DecrypterKeyPEM; len(decryptionKeyPEM) > 0 { + // try reading the PEM for validation + block, rest := pem.Decode(decryptionKeyPEM) + if len(rest) > 0 { + return errors.New("failed parsing decrypter key: trailing data") + } + if block == nil { + return errors.New("failed parsing decrypter key: no PEM block found") + } + opts := kms.Options{ + Type: kmsapi.SoftKMS, + } + if s.keyManager, err = kms.New(context.Background(), opts); err != nil { + return fmt.Errorf("failed initializing kms: %w", err) + } + kmsDecrypter, ok := s.keyManager.(kmsapi.Decrypter) + if !ok { + return fmt.Errorf("%q is not a kmsapi.Decrypter", opts.Type) + } + if s.decrypter, err = kmsDecrypter.CreateDecrypter(&kmsapi.CreateDecrypterRequest{ + DecryptionKeyPEM: decryptionKeyPEM, + Password: []byte(s.DecrypterKeyPassword), + PasswordPrompter: kmsapi.NonInteractivePasswordPrompter, + }); err != nil { + return fmt.Errorf("failed creating decrypter: %w", err) + } + if s.signer, err = s.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ + SigningKeyPEM: decryptionKeyPEM, // TODO(hs): support distinct signer key in the future? + Password: []byte(s.DecrypterKeyPassword), + PasswordPrompter: kmsapi.NonInteractivePasswordPrompter, + }); err != nil { + return fmt.Errorf("failed creating signer: %w", err) + } + } + + if decryptionKeyURI := s.DecrypterKeyURI; len(decryptionKeyURI) > 0 { + u, err := uri.Parse(s.DecrypterKeyURI) + if err != nil { + return fmt.Errorf("failed parsing decrypter key: %w", err) + } + var kmsType kmsapi.Type + switch { + case u.Scheme != "": + kmsType = kms.Type(u.Scheme) + default: + kmsType = kmsapi.SoftKMS + } + opts := kms.Options{ + Type: kmsType, + URI: s.DecrypterKeyURI, + } + if s.keyManager, err = kms.New(context.Background(), opts); err != nil { + return fmt.Errorf("failed initializing kms: %w", err) + } + kmsDecrypter, ok := s.keyManager.(kmsapi.Decrypter) + if !ok { + return fmt.Errorf("%q is not a kmsapi.Decrypter", opts.Type) + } + if kmsType != "softkms" { // TODO(hs): this should likely become more transparent? + decryptionKeyURI = u.Opaque + } + if s.decrypter, err = kmsDecrypter.CreateDecrypter(&kmsapi.CreateDecrypterRequest{ + DecryptionKey: decryptionKeyURI, + Password: []byte(s.DecrypterKeyPassword), + PasswordPrompter: kmsapi.NonInteractivePasswordPrompter, + }); err != nil { + return fmt.Errorf("failed creating decrypter: %w", err) + } + if s.signer, err = s.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ + SigningKey: decryptionKeyURI, // TODO(hs): support distinct signer key in the future? + Password: []byte(s.DecrypterKeyPassword), + PasswordPrompter: kmsapi.NonInteractivePasswordPrompter, + }); err != nil { + return fmt.Errorf("failed creating signer: %w", err) + } + } + + // parse the decrypter certificate contents if available + if len(s.DecrypterCertificate) > 0 { + block, rest := pem.Decode(s.DecrypterCertificate) + if len(rest) > 0 { + return errors.New("failed parsing decrypter certificate: trailing data") + } + if block == nil { + return errors.New("failed parsing decrypter certificate: no PEM block found") + } + if s.decrypterCertificate, err = x509.ParseCertificate(block.Bytes); err != nil { + return fmt.Errorf("failed parsing decrypter certificate: %w", err) + } + // the decrypter certificate is also the signer certificate + s.signerCertificate = s.decrypterCertificate + } + + // TODO(hs): alternatively, check if the KMS keyManager is a CertificateManager + // and load the certificate corresponding to the decryption key? + + // Final validation for the decrypter. + if s.decrypter != nil { + decrypterPublicKey, ok := s.decrypter.Public().(*rsa.PublicKey) + if !ok { + return fmt.Errorf("only RSA keys are supported") + } + if s.decrypterCertificate == nil { + return fmt.Errorf("provisioner %q does not have a decrypter certificate set", s.Name) + } + if !decrypterPublicKey.Equal(s.decrypterCertificate.PublicKey) { + return errors.New("mismatch between decrypter certificate and decrypter public keys") + } + } + // TODO: add other, SCEP specific, options? s.ctl, err = NewController(s, s.Claims, config, s.Options) @@ -190,7 +392,7 @@ func (s *SCEP) AuthorizeSign(context.Context, string) ([]SignOption, error) { return []SignOption{ s, // modifiers / withOptions - newProvisionerExtensionOption(TypeSCEP, s.Name, ""), + newProvisionerExtensionOption(TypeSCEP, s.Name, "").WithControllerOptions(s.ctl), newForceCNOption(s.ForceCN), profileDefaultDuration(s.ctl.Claimer.DefaultTLSCertDuration()), // validators @@ -214,6 +416,15 @@ func (s *SCEP) ShouldIncludeRootInChain() bool { return s.IncludeRoot } +// ShouldIncludeIntermediateInChain indicates if the +// CA should include the intermediate CA certificate in the +// GetCACerts response. This is true by default, but can be +// overridden through configuration in case SCEP clients +// don't pick the right recipient. +func (s *SCEP) ShouldIncludeIntermediateInChain() bool { + return !s.ExcludeIntermediate +} + // GetContentEncryptionAlgorithm returns the numeric identifier // for the pkcs7 package encryption algorithm to use. func (s *SCEP) GetContentEncryptionAlgorithm() int { @@ -223,13 +434,13 @@ func (s *SCEP) GetContentEncryptionAlgorithm() int { // ValidateChallenge validates the provided challenge. It starts by // selecting the validation method to use, then performs validation // according to that method. -func (s *SCEP) ValidateChallenge(ctx context.Context, challenge, transactionID string) error { +func (s *SCEP) ValidateChallenge(ctx context.Context, csr *x509.CertificateRequest, challenge, transactionID string) error { if s.challengeValidationController == nil { return fmt.Errorf("provisioner %q wasn't initialized", s.Name) } switch s.selectValidationMethod() { case validationMethodWebhook: - return s.challengeValidationController.Validate(ctx, challenge, transactionID) + return s.challengeValidationController.Validate(ctx, csr, s.Name, challenge, transactionID) default: if subtle.ConstantTimeCompare([]byte(s.ChallengePassword), []byte(challenge)) == 0 { return errors.New("invalid challenge password provided") @@ -238,6 +449,20 @@ func (s *SCEP) ValidateChallenge(ctx context.Context, challenge, transactionID s } } +func (s *SCEP) NotifySuccess(ctx context.Context, csr *x509.CertificateRequest, cert *x509.Certificate, transactionID string) error { + if s.notificationController == nil { + return fmt.Errorf("provisioner %q wasn't initialized", s.Name) + } + return s.notificationController.Success(ctx, csr, cert, transactionID) +} + +func (s *SCEP) NotifyFailure(ctx context.Context, csr *x509.CertificateRequest, transactionID string, errorCode int, errorDescription string) error { + if s.notificationController == nil { + return fmt.Errorf("provisioner %q wasn't initialized", s.Name) + } + return s.notificationController.Failure(ctx, csr, transactionID, errorCode, errorDescription) +} + type validationMethod string const ( @@ -259,3 +484,20 @@ func (s *SCEP) selectValidationMethod() validationMethod { } return validationMethodNone } + +// GetDecrypter returns the provisioner specific decrypter, +// used to decrypt SCEP request messages sent by a SCEP client. +// The decrypter consists of a crypto.Decrypter (a private key) +// and a certificate for the public key corresponding to the +// private key. +func (s *SCEP) GetDecrypter() (*x509.Certificate, crypto.Decrypter) { + return s.decrypterCertificate, s.decrypter +} + +// GetSigner returns the provisioner specific signer, used to +// sign SCEP response messages for the client. The signer consists +// of a crypto.Signer and a certificate for the public key +// corresponding to the private key. +func (s *SCEP) GetSigner() (*x509.Certificate, crypto.Signer) { + return s.signerCertificate, s.signer +} diff --git a/authority/provisioner/scep_test.go b/authority/provisioner/scep_test.go index acf047fb..2e9f3419 100644 --- a/authority/provisioner/scep_test.go +++ b/authority/provisioner/scep_test.go @@ -2,6 +2,7 @@ package provisioner import ( "context" + "crypto/x509" "encoding/json" "errors" "net/http" @@ -12,12 +13,19 @@ import ( "github.com/stretchr/testify/require" "go.step.sm/linkedca" + + "github.com/smallstep/certificates/webhook" ) func Test_challengeValidationController_Validate(t *testing.T) { + dummyCSR := &x509.CertificateRequest{ + Raw: []byte{1}, + } type request struct { - Challenge string `json:"scepChallenge"` - TransactionID string `json:"scepTransactionID"` + ProvisionerName string `json:"provisionerName,omitempty"` + Request *webhook.X509CertificateRequest `json:"x509CertificateRequest,omitempty"` + Challenge string `json:"scepChallenge"` + TransactionID string `json:"scepTransactionID"` } type response struct { Allow bool `json:"allow"` @@ -26,6 +34,7 @@ func Test_challengeValidationController_Validate(t *testing.T) { req := &request{} err := json.NewDecoder(r.Body).Decode(req) require.NoError(t, err) + assert.Equal(t, "my-scep-provisioner", req.ProvisionerName) assert.Equal(t, "not-allowed", req.Challenge) assert.Equal(t, "transaction-1", req.TransactionID) b, err := json.Marshal(response{Allow: false}) @@ -37,8 +46,12 @@ func Test_challengeValidationController_Validate(t *testing.T) { req := &request{} err := json.NewDecoder(r.Body).Decode(req) require.NoError(t, err) + assert.Equal(t, "my-scep-provisioner", req.ProvisionerName) assert.Equal(t, "challenge", req.Challenge) assert.Equal(t, "transaction-1", req.TransactionID) + if assert.NotNil(t, req.Request) { + assert.Equal(t, []byte{1}, req.Request.Raw) + } b, err := json.Marshal(response{Allow: true}) require.NoError(t, err) w.WriteHeader(200) @@ -49,8 +62,9 @@ func Test_challengeValidationController_Validate(t *testing.T) { webhooks []*Webhook } type args struct { - challenge string - transactionID string + provisionerName string + challenge string + transactionID string } tests := []struct { name string @@ -62,7 +76,7 @@ func Test_challengeValidationController_Validate(t *testing.T) { { name: "fail/no-webhook", fields: fields{http.DefaultClient, nil}, - args: args{"no-webhook", "transaction-1"}, + args: args{"my-scep-provisioner", "no-webhook", "transaction-1"}, expErr: errors.New("webhook server did not allow request"), }, { @@ -73,7 +87,7 @@ func Test_challengeValidationController_Validate(t *testing.T) { CertType: linkedca.Webhook_SSH.String(), }, }}, - args: args{"wrong-cert-type", "transaction-1"}, + args: args{"my-scep-provisioner", "wrong-cert-type", "transaction-1"}, expErr: errors.New("webhook server did not allow request"), }, { @@ -89,8 +103,9 @@ func Test_challengeValidationController_Validate(t *testing.T) { }, }}, args: args{ - challenge: "wrong-secret-value", - transactionID: "transaction-1", + provisionerName: "my-scep-provisioner", + challenge: "wrong-secret-value", + transactionID: "transaction-1", }, expErr: errors.New("failed executing webhook request: illegal base64 data at input byte 0"), }, @@ -107,8 +122,9 @@ func Test_challengeValidationController_Validate(t *testing.T) { }, }}, args: args{ - challenge: "not-allowed", - transactionID: "transaction-1", + provisionerName: "my-scep-provisioner", + challenge: "not-allowed", + transactionID: "transaction-1", }, server: nokServer, expErr: errors.New("webhook server did not allow request"), @@ -126,8 +142,9 @@ func Test_challengeValidationController_Validate(t *testing.T) { }, }}, args: args{ - challenge: "challenge", - transactionID: "transaction-1", + provisionerName: "my-scep-provisioner", + challenge: "challenge", + transactionID: "transaction-1", }, server: okServer, }, @@ -141,7 +158,7 @@ func Test_challengeValidationController_Validate(t *testing.T) { } ctx := context.Background() - err := c.Validate(ctx, tt.args.challenge, tt.args.transactionID) + err := c.Validate(ctx, dummyCSR, tt.args.provisionerName, tt.args.challenge, tt.args.transactionID) if tt.expErr != nil { assert.EqualError(t, err, tt.expErr.Error()) @@ -221,9 +238,14 @@ func Test_selectValidationMethod(t *testing.T) { } func TestSCEP_ValidateChallenge(t *testing.T) { + dummyCSR := &x509.CertificateRequest{ + Raw: []byte{1}, + } type request struct { - Challenge string `json:"scepChallenge"` - TransactionID string `json:"scepTransactionID"` + ProvisionerName string `json:"provisionerName,omitempty"` + Request *webhook.X509CertificateRequest `json:"x509CertificateRequest,omitempty"` + Challenge string `json:"scepChallenge"` + TransactionID string `json:"scepTransactionID"` } type response struct { Allow bool `json:"allow"` @@ -232,8 +254,12 @@ func TestSCEP_ValidateChallenge(t *testing.T) { req := &request{} err := json.NewDecoder(r.Body).Decode(req) require.NoError(t, err) + assert.Equal(t, "SCEP", req.ProvisionerName) assert.Equal(t, "webhook-challenge", req.Challenge) assert.Equal(t, "webhook-transaction-1", req.TransactionID) + if assert.NotNil(t, req.Request) { + assert.Equal(t, []byte{1}, req.Request.Raw) + } b, err := json.Marshal(response{Allow: true}) require.NoError(t, err) w.WriteHeader(200) @@ -330,7 +356,7 @@ func TestSCEP_ValidateChallenge(t *testing.T) { require.NoError(t, err) ctx := context.Background() - err = tt.p.ValidateChallenge(ctx, tt.args.challenge, tt.args.transactionID) + err = tt.p.ValidateChallenge(ctx, dummyCSR, tt.args.challenge, tt.args.transactionID) if tt.expErr != nil { assert.EqualError(t, err, tt.expErr.Error()) return diff --git a/authority/provisioner/sign_options.go b/authority/provisioner/sign_options.go index c3db239a..fec9b9f6 100644 --- a/authority/provisioner/sign_options.go +++ b/authority/provisioner/sign_options.go @@ -1,6 +1,7 @@ package provisioner import ( + "context" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" @@ -233,16 +234,28 @@ func (v emailAddressesValidator) Valid(req *x509.CertificateRequest) error { } // urisValidator validates the URI SANs of a certificate request. -type urisValidator []*url.URL +type urisValidator struct { + ctx context.Context + uris []*url.URL +} + +func newURIsValidator(ctx context.Context, uris []*url.URL) *urisValidator { + return &urisValidator{ctx, uris} +} // Valid checks that certificate request IP Addresses match those configured in // the bootstrap (token) flow. func (v urisValidator) Valid(req *x509.CertificateRequest) error { + // SignIdentityMethod does not need to validate URIs. + if MethodFromContext(v.ctx) == SignIdentityMethod { + return nil + } + if len(req.URIs) == 0 { return nil } want := make(map[string]bool) - for _, u := range v { + for _, u := range v.uris { want[u.String()] = true } got := make(map[string]bool) @@ -250,26 +263,33 @@ func (v urisValidator) Valid(req *x509.CertificateRequest) error { got[u.String()] = true } if !reflect.DeepEqual(want, got) { - return errs.Forbidden("certificate request does not contain the valid URIs - got %v, want %v", req.URIs, v) + return errs.Forbidden("certificate request does not contain the valid URIs - got %v, want %v", req.URIs, v.uris) } return nil } // defaultsSANsValidator stores a set of SANs to eventually validate 1:1 against // the SANs in an x509 certificate request. -type defaultSANsValidator []string +type defaultSANsValidator struct { + ctx context.Context + sans []string +} + +func newDefaultSANsValidator(ctx context.Context, sans []string) *defaultSANsValidator { + return &defaultSANsValidator{ctx, sans} +} // Valid verifies that the SANs stored in the validator match 1:1 with those // requested in the x509 certificate request. func (v defaultSANsValidator) Valid(req *x509.CertificateRequest) (err error) { - dnsNames, ips, emails, uris := x509util.SplitSANs(v) + dnsNames, ips, emails, uris := x509util.SplitSANs(v.sans) if err = dnsNamesValidator(dnsNames).Valid(req); err != nil { return } else if err = emailAddressesValidator(emails).Valid(req); err != nil { return } else if err = ipAddressesValidator(ips).Valid(req); err != nil { return - } else if err = urisValidator(uris).Valid(req); err != nil { + } else if err = newURIsValidator(v.ctx, uris).Valid(req); err != nil { return } return @@ -430,6 +450,7 @@ func (o *forceCNOption) Modify(cert *x509.Certificate, _ SignOptions) error { type provisionerExtensionOption struct { Extension + Disabled bool } func newProvisionerExtensionOption(typ Type, name, credentialID string, keyValuePairs ...string) *provisionerExtensionOption { @@ -443,7 +464,19 @@ func newProvisionerExtensionOption(typ Type, name, credentialID string, keyValue } } +// WithControllerOptions updates the provisionerExtensionOption with options +// from the controller. Currently only the DisableSmallstepExtensions +// provisioner claim is used. +func (o *provisionerExtensionOption) WithControllerOptions(c *Controller) *provisionerExtensionOption { + o.Disabled = c.Claimer.IsDisableSmallstepExtensions() + return o +} + func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ SignOptions) error { + if o.Disabled { + return nil + } + ext, err := o.ToExtension() if err != nil { return errs.NewError(http.StatusInternalServerError, err, "error creating certificate") diff --git a/authority/provisioner/sign_options_test.go b/authority/provisioner/sign_options_test.go index 01d2a0cd..5a55aa86 100644 --- a/authority/provisioner/sign_options_test.go +++ b/authority/provisioner/sign_options_test.go @@ -1,6 +1,7 @@ package provisioner import ( + "context" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" @@ -227,23 +228,26 @@ func Test_urisValidator_Valid(t *testing.T) { fu, err := url.Parse("https://unexpected.com") assert.FatalError(t, err) + signContext := NewContextWithMethod(context.Background(), SignMethod) + signIdentityContext := NewContextWithMethod(context.Background(), SignIdentityMethod) + type args struct { req *x509.CertificateRequest } tests := []struct { name string - v urisValidator + v *urisValidator args args wantErr bool }{ - {"ok0", []*url.URL{}, args{&x509.CertificateRequest{URIs: []*url.URL{}}}, false}, - {"ok1", []*url.URL{u1}, args{&x509.CertificateRequest{URIs: []*url.URL{u1}}}, false}, - {"ok2", []*url.URL{u1, u2}, args{&x509.CertificateRequest{URIs: []*url.URL{u2, u1}}}, false}, - {"ok3", []*url.URL{u2, u1, u3}, args{&x509.CertificateRequest{URIs: []*url.URL{u3, u2, u1}}}, false}, - {"ok3", []*url.URL{u2, u1, u3}, args{&x509.CertificateRequest{}}, false}, - {"fail1", []*url.URL{u1}, args{&x509.CertificateRequest{URIs: []*url.URL{u2}}}, true}, - {"fail2", []*url.URL{u1}, args{&x509.CertificateRequest{URIs: []*url.URL{u2, u1}}}, true}, - {"fail3", []*url.URL{u1, u2}, args{&x509.CertificateRequest{URIs: []*url.URL{u1, fu}}}, true}, + {"ok0", newURIsValidator(signContext, []*url.URL{}), args{&x509.CertificateRequest{URIs: []*url.URL{}}}, false}, + {"ok1", newURIsValidator(signContext, []*url.URL{u1}), args{&x509.CertificateRequest{URIs: []*url.URL{u1}}}, false}, + {"ok2", newURIsValidator(signContext, []*url.URL{u1, u2}), args{&x509.CertificateRequest{URIs: []*url.URL{u2, u1}}}, false}, + {"ok3", newURIsValidator(signContext, []*url.URL{u2, u1, u3}), args{&x509.CertificateRequest{URIs: []*url.URL{u3, u2, u1}}}, false}, + {"ok4", newURIsValidator(signIdentityContext, []*url.URL{u1, u2}), args{&x509.CertificateRequest{URIs: []*url.URL{u1, fu}}}, false}, + {"fail1", newURIsValidator(signContext, []*url.URL{u1}), args{&x509.CertificateRequest{URIs: []*url.URL{u2}}}, true}, + {"fail2", newURIsValidator(signContext, []*url.URL{u1}), args{&x509.CertificateRequest{URIs: []*url.URL{u2, u1}}}, true}, + {"fail3", newURIsValidator(signContext, []*url.URL{u1, u2}), args{&x509.CertificateRequest{URIs: []*url.URL{u1, fu}}}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -257,13 +261,19 @@ func Test_urisValidator_Valid(t *testing.T) { func Test_defaultSANsValidator_Valid(t *testing.T) { type test struct { csr *x509.CertificateRequest + ctx context.Context expectedSANs []string err error } + + signContext := NewContextWithMethod(context.Background(), SignMethod) + signIdentityContext := NewContextWithMethod(context.Background(), SignIdentityMethod) + tests := map[string]func() test{ "fail/dnsNamesValidator": func() test { return test{ csr: &x509.CertificateRequest{DNSNames: []string{"foo", "bar"}}, + ctx: signContext, expectedSANs: []string{"foo"}, err: errors.New("certificate request does not contain the valid DNS names"), } @@ -271,6 +281,7 @@ func Test_defaultSANsValidator_Valid(t *testing.T) { "fail/emailAddressesValidator": func() test { return test{ csr: &x509.CertificateRequest{EmailAddresses: []string{"max@fx.com", "mariano@fx.com"}}, + ctx: signContext, expectedSANs: []string{"dcow@fx.com"}, err: errors.New("certificate request does not contain the valid email addresses"), } @@ -278,6 +289,7 @@ func Test_defaultSANsValidator_Valid(t *testing.T) { "fail/ipAddressesValidator": func() test { return test{ csr: &x509.CertificateRequest{IPAddresses: []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("127.0.0.1")}}, + ctx: signContext, expectedSANs: []string{"127.0.0.1"}, err: errors.New("certificate request does not contain the valid IP addresses"), } @@ -289,16 +301,29 @@ func Test_defaultSANsValidator_Valid(t *testing.T) { assert.FatalError(t, err) return test{ csr: &x509.CertificateRequest{URIs: []*url.URL{u1, u2}}, + ctx: signContext, expectedSANs: []string{"urn:uuid:ddfe62ba-7e99-4bc1-83b3-8f57fe3e9959"}, err: errors.New("certificate request does not contain the valid URIs"), } }, + "ok/urisBadValidator-SignIdentity": func() test { + u1, err := url.Parse("https://google.com") + assert.FatalError(t, err) + u2, err := url.Parse("urn:uuid:ddfe62ba-7e99-4bc1-83b3-8f57fe3e9959") + assert.FatalError(t, err) + return test{ + csr: &x509.CertificateRequest{URIs: []*url.URL{u1, u2}}, + ctx: signIdentityContext, + expectedSANs: []string{"urn:uuid:ddfe62ba-7e99-4bc1-83b3-8f57fe3e9959"}, + } + }, "ok": func() test { u1, err := url.Parse("https://google.com") assert.FatalError(t, err) u2, err := url.Parse("urn:uuid:ddfe62ba-7e99-4bc1-83b3-8f57fe3e9959") assert.FatalError(t, err) return test{ + ctx: signContext, csr: &x509.CertificateRequest{ DNSNames: []string{"foo", "bar"}, EmailAddresses: []string{"max@fx.com", "mariano@fx.com"}, @@ -312,7 +337,7 @@ func Test_defaultSANsValidator_Valid(t *testing.T) { for name, run := range tests { t.Run(name, func(t *testing.T) { tt := run() - if err := defaultSANsValidator(tt.expectedSANs).Valid(tt.csr); err != nil { + if err := newDefaultSANsValidator(tt.ctx, tt.expectedSANs).Valid(tt.csr); err != nil { if assert.NotNil(t, tt.err, fmt.Sprintf("expected no error, but got err = %s", err.Error())) { assert.True(t, strings.Contains(err.Error(), tt.err.Error()), fmt.Sprintf("want err = %s, but got err = %s", tt.err.Error(), err.Error())) @@ -604,14 +629,24 @@ func Test_newProvisionerExtension_Option(t *testing.T) { t.Fatal(err) } + // Claims with smallstep extensions disabled. + claimer, err := NewClaimer(&Claims{ + DisableSmallstepExtensions: &trueValue, + }, globalProvisionerClaims) + if err != nil { + t.Fatal(err) + } + type test struct { - cert *x509.Certificate - valid func(*x509.Certificate) + modifier *provisionerExtensionOption + cert *x509.Certificate + valid func(*x509.Certificate) } tests := map[string]func() test{ "ok/one-element": func() test { return test{ - cert: new(x509.Certificate), + modifier: newProvisionerExtensionOption(TypeJWK, "name", "credentialId", "key", "value"), + cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { if assert.Len(t, 1, cert.ExtraExtensions) { ext := cert.ExtraExtensions[0] @@ -625,7 +660,8 @@ func Test_newProvisionerExtension_Option(t *testing.T) { }, "ok/replace": func() test { return test{ - cert: &x509.Certificate{ExtraExtensions: []pkix.Extension{{Id: StepOIDProvisioner, Critical: true}, {Id: []int{1, 2, 3}}}}, + modifier: newProvisionerExtensionOption(TypeJWK, "name", "credentialId", "key", "value"), + cert: &x509.Certificate{ExtraExtensions: []pkix.Extension{{Id: StepOIDProvisioner, Critical: true}, {Id: []int{1, 2, 3}}}}, valid: func(cert *x509.Certificate) { if assert.Len(t, 2, cert.ExtraExtensions) { ext := cert.ExtraExtensions[0] @@ -636,11 +672,22 @@ func Test_newProvisionerExtension_Option(t *testing.T) { }, } }, + "ok/disabled": func() test { + return test{ + modifier: newProvisionerExtensionOption(TypeJWK, "name", "credentialId", "key", "value").WithControllerOptions(&Controller{ + Claimer: claimer, + }), + cert: new(x509.Certificate), + valid: func(cert *x509.Certificate) { + assert.Len(t, 0, cert.ExtraExtensions) + }, + } + }, } for name, run := range tests { t.Run(name, func(t *testing.T) { tt := run() - assert.FatalError(t, newProvisionerExtensionOption(TypeJWK, "name", "credentialId", "key", "value").Modify(tt.cert, SignOptions{})) + assert.FatalError(t, tt.modifier.Modify(tt.cert, SignOptions{})) tt.valid(tt.cert) }) } diff --git a/authority/provisioner/utils_test.go b/authority/provisioner/utils_test.go index 55fdfe6f..a599a835 100644 --- a/authority/provisioner/utils_test.go +++ b/authority/provisioner/utils_test.go @@ -24,22 +24,24 @@ import ( ) var ( - defaultDisableRenewal = false - defaultAllowRenewalAfterExpiry = false - defaultEnableSSHCA = true - globalProvisionerClaims = Claims{ - MinTLSDur: &Duration{5 * time.Minute}, - MaxTLSDur: &Duration{24 * time.Hour}, - DefaultTLSDur: &Duration{24 * time.Hour}, - MinUserSSHDur: &Duration{Duration: 5 * time.Minute}, // User SSH certs - MaxUserSSHDur: &Duration{Duration: 24 * time.Hour}, - DefaultUserSSHDur: &Duration{Duration: 16 * time.Hour}, - MinHostSSHDur: &Duration{Duration: 5 * time.Minute}, // Host SSH certs - MaxHostSSHDur: &Duration{Duration: 30 * 24 * time.Hour}, - DefaultHostSSHDur: &Duration{Duration: 30 * 24 * time.Hour}, - EnableSSHCA: &defaultEnableSSHCA, - DisableRenewal: &defaultDisableRenewal, - AllowRenewalAfterExpiry: &defaultAllowRenewalAfterExpiry, + defaultDisableRenewal = false + defaultAllowRenewalAfterExpiry = false + defaultEnableSSHCA = true + defaultDisableSmallstepExtensions = false + globalProvisionerClaims = Claims{ + MinTLSDur: &Duration{5 * time.Minute}, + MaxTLSDur: &Duration{24 * time.Hour}, + DefaultTLSDur: &Duration{24 * time.Hour}, + MinUserSSHDur: &Duration{Duration: 5 * time.Minute}, // User SSH certs + MaxUserSSHDur: &Duration{Duration: 24 * time.Hour}, + DefaultUserSSHDur: &Duration{Duration: 16 * time.Hour}, + MinHostSSHDur: &Duration{Duration: 5 * time.Minute}, // Host SSH certs + MaxHostSSHDur: &Duration{Duration: 30 * 24 * time.Hour}, + DefaultHostSSHDur: &Duration{Duration: 30 * 24 * time.Hour}, + EnableSSHCA: &defaultEnableSSHCA, + DisableRenewal: &defaultDisableRenewal, + AllowRenewalAfterExpiry: &defaultAllowRenewalAfterExpiry, + DisableSmallstepExtensions: &defaultDisableSmallstepExtensions, } testAudiences = Audiences{ Sign: []string{"https://ca.smallstep.com/1.0/sign", "https://ca.smallstep.com/sign"}, diff --git a/authority/provisioner/webhook.go b/authority/provisioner/webhook.go index 407b84d8..4b517bb6 100644 --- a/authority/provisioner/webhook.go +++ b/authority/provisioner/webhook.go @@ -173,7 +173,9 @@ retry: if err != nil { return nil, err } - sig := hmac.New(sha256.New, secret).Sum(reqBytes) + h := hmac.New(sha256.New, secret) + h.Write(reqBytes) + sig := h.Sum(nil) req.Header.Set("X-Smallstep-Signature", hex.EncodeToString(sig)) req.Header.Set("X-Smallstep-Webhook-ID", w.ID) diff --git a/authority/provisioner/webhook_test.go b/authority/provisioner/webhook_test.go index 656d75d8..9a2b62f0 100644 --- a/authority/provisioner/webhook_test.go +++ b/authority/provisioner/webhook_test.go @@ -482,7 +482,9 @@ func TestWebhook_Do(t *testing.T) { secret, err := base64.StdEncoding.DecodeString(tc.webhook.Secret) assert.FatalError(t, err) - mac := hmac.New(sha256.New, secret).Sum(body) + h := hmac.New(sha256.New, secret) + h.Write(body) + mac := h.Sum(nil) assert.True(t, hmac.Equal(sig, mac)) switch { diff --git a/authority/provisioner/x5c.go b/authority/provisioner/x5c.go index be606ae8..9b1f2b08 100644 --- a/authority/provisioner/x5c.go +++ b/authority/provisioner/x5c.go @@ -194,7 +194,7 @@ func (p *X5C) AuthorizeRevoke(_ context.Context, token string) error { } // AuthorizeSign validates the given token. -func (p *X5C) AuthorizeSign(_ context.Context, token string) ([]SignOption, error) { +func (p *X5C) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) { claims, err := p.authorizeToken(token, p.ctl.Audiences.Sign) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "x5c.AuthorizeSign") @@ -237,14 +237,14 @@ func (p *X5C) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro self, templateOptions, // modifiers / withOptions - newProvisionerExtensionOption(TypeX5C, p.Name, ""), + newProvisionerExtensionOption(TypeX5C, p.Name, "").WithControllerOptions(p.ctl), profileLimitDuration{ p.ctl.Claimer.DefaultTLSCertDuration(), x5cLeaf.NotBefore, x5cLeaf.NotAfter, }, // validators commonNameValidator(claims.Subject), - defaultSANsValidator(claims.SANs), + newDefaultSANsValidator(ctx, claims.SANs), defaultPublicKeyValidator{}, newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()), newX509NamePolicyValidator(p.ctl.getPolicy().getX509()), diff --git a/authority/provisioner/x5c_test.go b/authority/provisioner/x5c_test.go index f9a2604b..22545446 100644 --- a/authority/provisioner/x5c_test.go +++ b/authority/provisioner/x5c_test.go @@ -460,7 +460,8 @@ func TestX5C_AuthorizeSign(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { tc := tt(t) - if opts, err := tc.p.AuthorizeSign(context.Background(), tc.token); err != nil { + ctx := NewContextWithMethod(context.Background(), SignIdentityMethod) + if opts, err := tc.p.AuthorizeSign(ctx, tc.token); err != nil { if assert.NotNil(t, tc.err) { var sc render.StatusCodedError if assert.True(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") { @@ -489,8 +490,9 @@ func TestX5C_AuthorizeSign(t *testing.T) { case commonNameValidator: assert.Equals(t, string(v), "foo") case defaultPublicKeyValidator: - case defaultSANsValidator: - assert.Equals(t, []string(v), tc.sans) + case *defaultSANsValidator: + assert.Equals(t, v.sans, tc.sans) + assert.Equals(t, MethodFromContext(v.ctx), SignIdentityMethod) case *validityValidator: assert.Equals(t, v.min, tc.p.ctl.Claimer.MinTLSCertDuration()) assert.Equals(t, v.max, tc.p.ctl.Claimer.MaxTLSCertDuration()) diff --git a/authority/provisioners.go b/authority/provisioners.go index 5d594536..c5105bb6 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -235,7 +235,7 @@ func (a *Authority) StoreProvisioner(ctx context.Context, prov *linkedca.Provisi } if err := certProv.Init(provisionerConfig); err != nil { - return admin.WrapError(admin.ErrorBadRequestType, err, "error validating configuration for provisioner %s", prov.Name) + return admin.WrapError(admin.ErrorBadRequestType, err, "error validating configuration for provisioner %q", prov.Name) } // Store to database -- this will set the ID. @@ -646,8 +646,9 @@ func claimsToCertificates(c *linkedca.Claims) (*provisioner.Claims, error) { } pc := &provisioner.Claims{ - DisableRenewal: &c.DisableRenewal, - AllowRenewalAfterExpiry: &c.AllowRenewalAfterExpiry, + DisableRenewal: &c.DisableRenewal, + AllowRenewalAfterExpiry: &c.AllowRenewalAfterExpiry, + DisableSmallstepExtensions: &c.DisableSmallstepExtensions, } var err error @@ -686,6 +687,7 @@ func claimsToLinkedca(c *provisioner.Claims) *linkedca.Claims { disableRenewal := config.DefaultDisableRenewal allowRenewalAfterExpiry := config.DefaultAllowRenewalAfterExpiry + disableSmallstepExtensions := config.DefaultDisableSmallstepExtensions if c.DisableRenewal != nil { disableRenewal = *c.DisableRenewal @@ -693,10 +695,14 @@ func claimsToLinkedca(c *provisioner.Claims) *linkedca.Claims { if c.AllowRenewalAfterExpiry != nil { allowRenewalAfterExpiry = *c.AllowRenewalAfterExpiry } + if c.DisableSmallstepExtensions != nil { + disableSmallstepExtensions = *c.DisableSmallstepExtensions + } lc := &linkedca.Claims{ - DisableRenewal: disableRenewal, - AllowRenewalAfterExpiry: allowRenewalAfterExpiry, + DisableRenewal: disableRenewal, + AllowRenewalAfterExpiry: allowRenewalAfterExpiry, + DisableSmallstepExtensions: disableSmallstepExtensions, } if c.DefaultTLSDur != nil || c.MinTLSDur != nil || c.MaxTLSDur != nil { @@ -748,13 +754,17 @@ func provisionerOptionsToLinkedca(p *provisioner.Options) (*linkedca.Template, * } if p.X509.Template != "" { - x509Template.Template = []byte(p.SSH.Template) + x509Template.Template = []byte(p.X509.Template) } else if p.X509.TemplateFile != "" { filename := step.Abs(p.X509.TemplateFile) if x509Template.Template, err = os.ReadFile(filename); err != nil { return nil, nil, nil, errors.Wrap(err, "error reading x509 template") } } + + if p.X509.TemplateData != nil { + x509Template.Data = p.X509.TemplateData + } } if p.SSH != nil && p.SSH.HasTemplate() { @@ -771,6 +781,10 @@ func provisionerOptionsToLinkedca(p *provisioner.Options) (*linkedca.Template, * return nil, nil, nil, errors.Wrap(err, "error reading ssh template") } } + + if p.SSH.TemplateData != nil { + sshTemplate.Data = p.SSH.TemplateData + } } var webhooks []*linkedca.Webhook @@ -960,7 +974,7 @@ func ProvisionerToCertificates(p *linkedca.Provisioner) (provisioner.Interface, }, nil case *linkedca.ProvisionerDetails_SCEP: cfg := d.SCEP - return &provisioner.SCEP{ + s := &provisioner.SCEP{ ID: p.Id, Type: p.Type.String(), Name: p.Name, @@ -968,11 +982,19 @@ func ProvisionerToCertificates(p *linkedca.Provisioner) (provisioner.Interface, ChallengePassword: cfg.Challenge, Capabilities: cfg.Capabilities, IncludeRoot: cfg.IncludeRoot, + ExcludeIntermediate: cfg.ExcludeIntermediate, MinimumPublicKeyLength: int(cfg.MinimumPublicKeyLength), EncryptionAlgorithmIdentifier: int(cfg.EncryptionAlgorithmIdentifier), Claims: claims, Options: options, - }, nil + } + if decrypter := cfg.GetDecrypter(); decrypter != nil { + s.DecrypterCertificate = decrypter.Certificate + s.DecrypterKeyPEM = decrypter.Key + s.DecrypterKeyURI = decrypter.KeyUri + s.DecrypterKeyPassword = string(decrypter.KeyPassword) + } + return s, nil case *linkedca.ProvisionerDetails_Nebula: var roots []byte for i, root := range d.Nebula.GetRoots() { @@ -1227,7 +1249,14 @@ func ProvisionerToLinkedca(p provisioner.Interface) (*linkedca.Provisioner, erro Capabilities: p.Capabilities, MinimumPublicKeyLength: int32(p.MinimumPublicKeyLength), IncludeRoot: p.IncludeRoot, + ExcludeIntermediate: p.ExcludeIntermediate, EncryptionAlgorithmIdentifier: int32(p.EncryptionAlgorithmIdentifier), + Decrypter: &linkedca.SCEPDecrypter{ + Certificate: p.DecrypterCertificate, + Key: p.DecrypterKeyPEM, + KeyUri: p.DecrypterKeyURI, + KeyPassword: []byte(p.DecrypterKeyPassword), + }, }, }, }, diff --git a/ca/ca.go b/ca/ca.go index b8f65332..7baf2419 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -15,8 +15,8 @@ import ( "sync" "time" - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" "github.com/pkg/errors" "github.com/smallstep/certificates/acme" acmeAPI "github.com/smallstep/certificates/acme/api" @@ -250,19 +250,14 @@ func (ca *CA) Init(cfg *config.Config) (*CA, error) { var scepAuthority *scep.Authority if ca.shouldServeSCEPEndpoints() { - scepPrefix := "scep" - scepAuthority, err = scep.New(auth, scep.AuthorityOptions{ - Service: auth.GetSCEPService(), - DNS: dns, - Prefix: scepPrefix, - }) - if err != nil { - return nil, errors.Wrap(err, "error creating SCEP authority") - } + // get the SCEP authority configuration. Validation is + // performed within the authority instantiation process. + scepAuthority = auth.GetSCEP() // According to the RFC (https://tools.ietf.org/html/rfc8894#section-7.10), // SCEP operations are performed using HTTP, so that's why the API is mounted // to the insecure mux. + scepPrefix := "scep" insecureMux.Route("/"+scepPrefix, func(r chi.Router) { scepAPI.Route(r) }) @@ -584,10 +579,10 @@ func (ca *CA) getTLSConfig(auth *authority.Authority) (*tls.Config, *tls.Config, // shouldServeSCEPEndpoints returns if the CA should be // configured with endpoints for SCEP. This is assumed to be -// true if a SCEPService exists, which is true in case a -// SCEP provisioner was configured. +// true if a SCEPService exists, which is true in case at +// least one SCEP provisioner was configured. func (ca *CA) shouldServeSCEPEndpoints() bool { - return ca.auth.GetSCEPService() != nil + return ca.auth.GetSCEP() != nil } //nolint:unused // useful for debugging diff --git a/ca/tls_test.go b/ca/tls_test.go index 24b8ef01..dbcc6023 100644 --- a/ca/tls_test.go +++ b/ca/tls_test.go @@ -59,9 +59,13 @@ func generateOTT(subject string) string { return raw } -func startTestServer(tlsConfig *tls.Config, handler http.Handler) *httptest.Server { +func startTestServer(baseContext context.Context, tlsConfig *tls.Config, handler http.Handler) *httptest.Server { srv := httptest.NewUnstartedServer(handler) srv.TLS = tlsConfig + // Base context MUST be set before the start of the server + srv.Config.BaseContext = func(l net.Listener) context.Context { + return baseContext + } srv.StartTLS() // Force the use of GetCertificate on IPs srv.TLS.Certificates = nil @@ -78,11 +82,8 @@ func startCATestServer() *httptest.Server { panic(err) } // Use a httptest.Server instead - srv := startTestServer(ca.srv.TLSConfig, ca.srv.Handler) baseContext := buildContext(ca.auth, nil, nil, nil) - srv.Config.BaseContext = func(net.Listener) context.Context { - return baseContext - } + srv := startTestServer(baseContext, ca.srv.TLSConfig, ca.srv.Handler) return srv } @@ -153,7 +154,7 @@ func TestClient_GetServerTLSConfig_http(t *testing.T) { if err != nil { t.Fatalf("Client.GetServerTLSConfig() error = %v", err) } - srvMTLS := startTestServer(tlsConfig, serverHandler(t, clientDomain)) + srvMTLS := startTestServer(context.Background(), tlsConfig, serverHandler(t, clientDomain)) defer srvMTLS.Close() // Create TLS server @@ -163,7 +164,7 @@ func TestClient_GetServerTLSConfig_http(t *testing.T) { if err != nil { t.Fatalf("Client.GetServerTLSConfig() error = %v", err) } - srvTLS := startTestServer(tlsConfig, serverHandler(t, clientDomain)) + srvTLS := startTestServer(context.Background(), tlsConfig, serverHandler(t, clientDomain)) defer srvTLS.Close() tests := []struct { @@ -258,7 +259,7 @@ func TestClient_GetServerTLSConfig_renew(t *testing.T) { if err != nil { t.Fatalf("Client.GetServerTLSConfig() error = %v", err) } - srvMTLS := startTestServer(tlsConfig, serverHandler(t, clientDomain)) + srvMTLS := startTestServer(context.Background(), tlsConfig, serverHandler(t, clientDomain)) defer srvMTLS.Close() // Start TLS server @@ -268,7 +269,7 @@ func TestClient_GetServerTLSConfig_renew(t *testing.T) { if err != nil { t.Fatalf("Client.GetServerTLSConfig() error = %v", err) } - srvTLS := startTestServer(tlsConfig, serverHandler(t, clientDomain)) + srvTLS := startTestServer(context.Background(), tlsConfig, serverHandler(t, clientDomain)) defer srvTLS.Close() // Transport diff --git a/cas/stepcas/stepcas.go b/cas/stepcas/stepcas.go index 9f94c6ae..51c5f687 100644 --- a/cas/stepcas/stepcas.go +++ b/cas/stepcas/stepcas.go @@ -71,6 +71,8 @@ func (s *StepCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1 switch { case req.CSR == nil: return nil, errors.New("createCertificateRequest `csr` cannot be nil") + case req.Template == nil: + return nil, errors.New("createCertificateRequest `template` cannot be nil") case req.Lifetime == 0: return nil, errors.New("createCertificateRequest `lifetime` cannot be 0") } @@ -87,7 +89,7 @@ func (s *StepCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1 info.ProvisionerName = p.Name } - cert, chain, err := s.createCertificate(req.CSR, req.Lifetime, info) + cert, chain, err := s.createCertificate(req.CSR, req.Template, req.Lifetime, info) if err != nil { return nil, err } @@ -167,18 +169,18 @@ func (s *StepCAS) GetCertificateAuthority(*apiv1.GetCertificateAuthorityRequest) }, nil } -func (s *StepCAS) createCertificate(cr *x509.CertificateRequest, lifetime time.Duration, raInfo *raInfo) (*x509.Certificate, []*x509.Certificate, error) { - sans := make([]string, 0, len(cr.DNSNames)+len(cr.EmailAddresses)+len(cr.IPAddresses)+len(cr.URIs)) - sans = append(sans, cr.DNSNames...) - sans = append(sans, cr.EmailAddresses...) - for _, ip := range cr.IPAddresses { +func (s *StepCAS) createCertificate(cr *x509.CertificateRequest, template *x509.Certificate, lifetime time.Duration, raInfo *raInfo) (*x509.Certificate, []*x509.Certificate, error) { + sans := make([]string, 0, len(template.DNSNames)+len(template.EmailAddresses)+len(template.IPAddresses)+len(template.URIs)) + sans = append(sans, template.DNSNames...) + sans = append(sans, template.EmailAddresses...) + for _, ip := range template.IPAddresses { sans = append(sans, ip.String()) } - for _, u := range cr.URIs { + for _, u := range template.URIs { sans = append(sans, u.String()) } - commonName := cr.Subject.CommonName + commonName := template.Subject.CommonName if commonName == "" && len(sans) > 0 { commonName = sans[0] } diff --git a/cas/stepcas/stepcas_test.go b/cas/stepcas/stepcas_test.go index b9dd9abd..f7746da0 100644 --- a/cas/stepcas/stepcas_test.go +++ b/cas/stepcas/stepcas_test.go @@ -23,6 +23,7 @@ import ( "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/ca" "github.com/smallstep/certificates/cas/apiv1" + "github.com/stretchr/testify/require" "go.step.sm/crypto/jose" "go.step.sm/crypto/pemutil" "go.step.sm/crypto/randutil" @@ -631,6 +632,17 @@ func TestStepCAS_CreateCertificate(t *testing.T) { jwkEnc := testJWKIssuer(t, caURL, testPassword) x5cBad := testX5CIssuer(t, caURL, "bad-password") + testTemplate := &x509.Certificate{ + Subject: testCR.Subject, + DNSNames: testCR.DNSNames, + EmailAddresses: testCR.EmailAddresses, + IPAddresses: testCR.IPAddresses, + URIs: testCR.URIs, + } + + testOtherCR, err := x509util.CreateCertificateRequest("Test Certificate", []string{"test.example.com"}, testKey) + require.NoError(t, err) + type fields struct { iss stepIssuer client *ca.Client @@ -648,6 +660,15 @@ func TestStepCAS_CreateCertificate(t *testing.T) { }{ {"ok", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ CSR: testCR, + Template: testTemplate, + Lifetime: time.Hour, + }}, &apiv1.CreateCertificateResponse{ + Certificate: testCrt, + CertificateChain: []*x509.Certificate{testIssCrt}, + }, false}, + {"ok with different CSR", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ + CSR: testOtherCR, + Template: testTemplate, Lifetime: time.Hour, }}, &apiv1.CreateCertificateResponse{ Certificate: testCrt, @@ -655,6 +676,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) { }, false}, {"ok with password", fields{x5cEnc, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ CSR: testCR, + Template: testTemplate, Lifetime: time.Hour, }}, &apiv1.CreateCertificateResponse{ Certificate: testCrt, @@ -662,6 +684,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) { }, false}, {"ok jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ CSR: testCR, + Template: testTemplate, Lifetime: time.Hour, }}, &apiv1.CreateCertificateResponse{ Certificate: testCrt, @@ -669,6 +692,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) { }, false}, {"ok jwk with password", fields{jwkEnc, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ CSR: testCR, + Template: testTemplate, Lifetime: time.Hour, }}, &apiv1.CreateCertificateResponse{ Certificate: testCrt, @@ -676,6 +700,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) { }, false}, {"ok with provisioner", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ CSR: testCR, + Template: testTemplate, Lifetime: time.Hour, Provisioner: &apiv1.ProvisionerInfo{ID: "provisioner-id", Type: "ACME"}, }}, &apiv1.CreateCertificateResponse{ @@ -684,6 +709,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) { }, false}, {"ok with server cert", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ CSR: testCR, + Template: testTemplate, Lifetime: time.Hour, IsCAServerCert: true, }}, &apiv1.CreateCertificateResponse{ @@ -692,6 +718,12 @@ func TestStepCAS_CreateCertificate(t *testing.T) { }, false}, {"fail CSR", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ CSR: nil, + Template: testTemplate, + Lifetime: time.Hour, + }}, nil, true}, + {"fail Template", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ + CSR: testCR, + Template: nil, Lifetime: time.Hour, }}, nil, true}, {"fail lifetime", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index db0b98e7..289815ef 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -5,7 +5,6 @@ import ( "fmt" "html" "log" - "math/rand" "net/http" "os" "reflect" @@ -52,7 +51,6 @@ var ( func init() { step.Set("Smallstep CA", Version, BuildTime) authority.GlobalVersion.Version = Version - rand.Seed(time.Now().UnixNano()) // Add support for asking passwords pemutil.PromptPassword = func(msg string) ([]byte, error) { return ui.PromptPassword(msg) diff --git a/db/db.go b/db/db.go index b3137a50..03295f22 100644 --- a/db/db.go +++ b/db/db.go @@ -119,7 +119,7 @@ func New(c *Config) (AuthDB, error) { db, err := nosql.New(c.Type, c.DataSource, opts...) if err != nil { - return nil, errors.Wrapf(err, "Error opening database of Type %s with source %s", c.Type, c.DataSource) + return nil, errors.Wrapf(err, "Error opening database of Type %s", c.Type) } tables := [][]byte{ diff --git a/docker/Dockerfile.hsm b/docker/Dockerfile.hsm index c5a54d8c..e033f30e 100644 --- a/docker/Dockerfile.hsm +++ b/docker/Dockerfile.hsm @@ -1,4 +1,4 @@ -FROM golang AS builder +FROM golang:bullseye AS builder WORKDIR /src COPY . . diff --git a/go.mod b/go.mod index 37ac04ec..e2e9e74e 100644 --- a/go.mod +++ b/go.mod @@ -1,65 +1,65 @@ module github.com/smallstep/certificates -go 1.19 +go 1.20 require ( - cloud.google.com/go/longrunning v0.5.1 - cloud.google.com/go/security v1.15.1 + cloud.google.com/go/longrunning v0.5.4 + cloud.google.com/go/security v1.15.4 github.com/Masterminds/sprig/v3 v3.2.3 github.com/dgraph-io/badger v1.6.2 github.com/dgraph-io/badger/v2 v2.2007.4 - github.com/fxamacker/cbor/v2 v2.4.0 - github.com/go-chi/chi v4.1.2+incompatible + github.com/fxamacker/cbor/v2 v2.5.0 + github.com/go-chi/chi/v5 v5.0.10 github.com/golang/mock v1.6.0 - github.com/google/go-cmp v0.5.9 - github.com/google/go-tpm v0.3.3 - github.com/google/uuid v1.3.0 + github.com/google/go-cmp v0.6.0 + github.com/google/go-tpm v0.9.0 + github.com/google/uuid v1.4.0 github.com/googleapis/gax-go/v2 v2.12.0 - github.com/hashicorp/vault/api v1.9.2 - github.com/hashicorp/vault/api/auth/approle v0.4.1 - github.com/hashicorp/vault/api/auth/kubernetes v0.4.1 - github.com/micromdm/scep/v2 v2.1.0 - github.com/newrelic/go-agent/v3 v3.23.1 + github.com/hashicorp/vault/api v1.10.0 + github.com/hashicorp/vault/api/auth/approle v0.5.0 + github.com/hashicorp/vault/api/auth/kubernetes v0.5.0 + github.com/newrelic/go-agent/v3 v3.28.0 github.com/pkg/errors v0.9.1 github.com/rs/xid v1.5.0 github.com/sirupsen/logrus v1.9.3 github.com/slackhq/nebula v1.6.1 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 - github.com/smallstep/go-attestation v0.4.4-0.20230509120429-e17291421738 + github.com/smallstep/go-attestation v0.4.4-0.20230627102604-cf579e53cbd2 github.com/smallstep/nosql v0.6.0 + github.com/smallstep/pkcs7 v0.0.0-20231024181729-3b98ecc1ca81 + github.com/smallstep/scep v0.0.0-20231024192529-aee96d7ad34d github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.14 - go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.8.0 - go.step.sm/crypto v0.33.0 - go.step.sm/linkedca v0.20.0 - golang.org/x/crypto v0.11.0 + go.step.sm/crypto v0.37.0 + go.step.sm/linkedca v0.20.1 + golang.org/x/crypto v0.15.0 golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 - golang.org/x/net v0.12.0 - google.golang.org/api v0.132.0 - google.golang.org/grpc v1.56.2 + golang.org/x/net v0.18.0 + google.golang.org/api v0.151.0 + google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 gopkg.in/square/go-jose.v2 v2.6.0 ) require ( - cloud.google.com/go v0.110.4 // indirect - cloud.google.com/go/compute v1.20.1 // indirect + cloud.google.com/go v0.110.8 // indirect + cloud.google.com/go/compute v1.23.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.0 // indirect - cloud.google.com/go/kms v1.15.0 // indirect + cloud.google.com/go/iam v1.1.3 // indirect + cloud.google.com/go/kms v1.15.5 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/ThalesIgnite/crypto11 v1.2.5 // indirect - github.com/aws/aws-sdk-go v1.44.307 // indirect + github.com/aws/aws-sdk-go v1.47.10 // indirect github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -68,23 +68,24 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect - github.com/go-kit/kit v0.10.0 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-jose/go-jose/v3 v3.0.1 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-piv/piv-go v1.11.0 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/golang-jwt/jwt/v5 v5.0.0 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/certificate-transparency-go v1.1.4 // indirect - github.com/google/go-tpm-tools v0.3.12 // indirect + github.com/google/certificate-transparency-go v1.1.6 // indirect + github.com/google/go-tpm-tools v0.4.2 // indirect github.com/google/go-tspi v0.3.0 // indirect - github.com/google/s2a-go v0.1.4 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -105,10 +106,10 @@ require ( github.com/jackc/pgtype v1.14.0 // indirect github.com/jackc/pgx/v4 v4.18.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.15.11 // indirect + github.com/klauspost/compress v1.16.3 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/manifoldco/promptui v0.9.0 // indirect - github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/miekg/pkcs11 v1.1.1 // indirect @@ -129,22 +130,14 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.etcd.io/bbolt v1.3.7 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect - golang.org/x/time v0.1.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -// replace github.com/smallstep/nosql => ../nosql -// replace go.step.sm/crypto => ../crypto - -// replace go.step.sm/cli-utils => ../cli-utils -// replace go.step.sm/linkedca => ../linkedca - -// use github.com/smallstep/pkcs7 fork with patches applied -replace go.mozilla.org/pkcs7 => github.com/smallstep/pkcs7 v0.0.0-20230302202335-4c094085c948 diff --git a/go.sum b/go.sum index 4223563f..de0e0f4a 100644 --- a/go.sum +++ b/go.sum @@ -1,194 +1,55 @@ -bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.92.2/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.92.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk= -cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= +cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94= -cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= -cloud.google.com/go/kms v1.15.0 h1:xYl5WEaSekKYN5gGRyhjvZKM22GVBBCzegGNVPy+aIs= -cloud.google.com/go/kms v1.15.0/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= -cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/monitoring v0.1.0/go.mod h1:Hpm3XfzJv+UTiXzCG5Ffp0wijzHTC7Cv4eR7o3x/fEE= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= -cloud.google.com/go/security v1.15.1 h1:jR3itwycg/TgGA0uIgTItcVhA55hKWiNJxaNNpQJaZE= -cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= -cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= -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= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/trace v0.1.0/go.mod h1:wxEwsoeRVPbeSkt7ZC9nWCgmoKQRAoySN7XHW2AmI7g= -code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= -contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= -contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= -contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ= -contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= -contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +cloud.google.com/go/iam v1.1.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= +cloud.google.com/go/kms v1.15.5 h1:pj1sRfut2eRbD9pFRjNnPNg/CzJPuQAzUujMIM1vVeM= +cloud.google.com/go/kms v1.15.5/go.mod h1:cU2H5jnp6G2TDpUGZyqTCoy1n16fbubHZjmVXSMtwDI= +cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= +cloud.google.com/go/security v1.15.4 h1:sdnh4Islb1ljaNhpIXlIPgb3eYj70QWgPVDKOUYvzJc= +cloud.google.com/go/security v1.15.4/go.mod h1:oN7C2uIZKhxCLiAAijKUCuHLZbIt/ghYEo8MqwD/Ty4= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= -github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= -github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= -github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= -github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= -github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 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/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= -github.com/apache/beam v2.28.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= -github.com/apache/beam v2.32.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ= -github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= -github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= -github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.44.307 h1:2R0/EPgpZcFSUwZhYImq/srjaOrOfLv5MNRzrFyAM38= -github.com/aws/aws-sdk-go v1.44.307/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -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/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/aws/aws-sdk-go v1.47.10 h1:cvufN7WkD1nlOgpRopsmxKQlFp5X1MfyAw4r7BBORQc= +github.com/aws/aws-sdk-go v1.47.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -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= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= -github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -203,50 +64,22 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 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= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= @@ -255,276 +88,110 @@ github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70d github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= -github.com/fullstorydev/grpcurl v1.8.0/go.mod h1:Mn2jWbdMrQGJQ8UD62uNyMumT2acsZUCkZIqFxsQf1o= -github.com/fullstorydev/grpcurl v1.8.1/go.mod h1:3BWhvHZwNO7iLXaQlojdg5NA6SxUDePli4ecpK1N7gw= -github.com/fullstorydev/grpcurl v1.8.2/go.mod h1:YvWNT3xRp2KIRuvCphFodG0fKkMXwaxA9CJgKCcyzUQ= -github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= -github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= -github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -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-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= +github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= +github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/kit v0.4.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -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 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-piv/piv-go v1.11.0 h1:5vAaCdRTFSIW4PeqMbnsDlUZ7odMYWnHBDGdmtU/Zhg= github.com/go-piv/piv-go v1.11.0/go.mod h1:NZ2zmjVkfFaL/CF8cVQ/pXdXtuj110zEKGdJM6fJZZM= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= -github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -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= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= -github.com/google/certificate-transparency-go v1.1.2-0.20210422104406-9f33727a7a18/go.mod h1:6CKh9dscIRoqc2kC6YUFICHZMT9NrClyPrRVFrdw1QQ= -github.com/google/certificate-transparency-go v1.1.2-0.20210512142713-bed466244fa6/go.mod h1:aF2dp7Dh81mY8Y/zpzyXps4fQW5zQbDu2CxfpJB6NkI= -github.com/google/certificate-transparency-go v1.1.2/go.mod h1:3OL+HKDqHPUfdKrHVQxO6T8nDLO0HF7LRTlkIWXaWvQ= -github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= -github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= -github.com/google/go-attestation v0.3.2/go.mod h1:N0ADdnY0cr7eLJyZ75o8kofGGTUF2XrZTJuTPo5acwk= -github.com/google/go-attestation v0.4.4-0.20220404204839-8820d49b18d9/go.mod h1:KDsPHk8a2MX9g20kYSdxB21t7je5NghSaFeVn0Zu3Ao= +github.com/google/certificate-transparency-go v1.1.6 h1:SW5K3sr7ptST/pIvNkSVWMiJqemRmkjJPPT0jzXdOOY= +github.com/google/certificate-transparency-go v1.1.6/go.mod h1:0OJjOsOk+wj6aYQgP7FU0ioQ0AJUmnWPFMqTjQeazPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= -github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOmkVoJOpwnS0wfdsJCV9CoD5nJYsHoFk/0CrTK4M= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= -github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= -github.com/google/go-sev-guest v0.6.1 h1:NajHkAaLqN9/aW7bCFSUplUMtDgk2+HcN7jC2btFtk0= -github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI= -github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw= -github.com/google/go-tpm v0.3.2/go.mod h1:j71sMBTfp3X5jPHz852ZOfQMUOf65Gb/Th8pRmp7fvg= -github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo= -github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51BeghL4= -github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0= -github.com/google/go-tpm-tools v0.2.0/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4= -github.com/google/go-tpm-tools v0.2.1/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4= -github.com/google/go-tpm-tools v0.3.1/go.mod h1:PSg+r5hSZI5tP3X7LBQx2sW1VSZUqZHBSrKyDqrB21U= -github.com/google/go-tpm-tools v0.3.9/go.mod h1:22JvWmHcD5w55cs+nMeqDGDxgNS15/2pDq2cLqnc3rc= -github.com/google/go-tpm-tools v0.3.12 h1:hpWglH4RaZnGVbgOK3IThI5K++jnFvjQ94EIN34xrUU= -github.com/google/go-tpm-tools v0.3.12/go.mod h1:2OtmyPGPuaWWIOjr+IDhNQb6t5njjbSmZtzc350Q6Ro= -github.com/google/go-tspi v0.2.1-0.20190423175329-115dea689aad/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-sev-guest v0.9.3 h1:GOJ+EipURdeWFl/YYdgcCxyPeMgQUWlI056iFkBD8UU= +github.com/google/go-tdx-guest v0.2.3-0.20231011100059-4cf02bed9d33 h1:lRlUusuieEuqljjihCXb+Mr73VNitOYPJYWXzJKtBWs= +github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= +github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= +github.com/google/go-tpm-tools v0.4.2 h1:iyaCPKt2N5Rd0yz0G8ANa022SgCNZkMpp+db6QELtvI= +github.com/google/go-tpm-tools v0.4.2/go.mod h1:fGUDZu4tw3V4hUVuFHmiYgRd0c58/IXivn9v3Ea/ck4= github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus= github.com/google/go-tspi v0.3.0/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/licenseclassifier v0.0.0-20210325184830-bb04aff29e72/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= -github.com/google/trillian v1.3.14-0.20210409160123-c5ea3abd4a41/go.mod h1:1dPv0CUjNQVFEDuAUFhZql16pw/VlPgaX8qj+g5pVzQ= -github.com/google/trillian v1.3.14-0.20210511103300-67b5f349eefa/go.mod h1:s4jO3Ai4NSvxucdvqUHON0bCqJyoya32eNw6XJwsmNc= -github.com/google/trillian v1.4.0/go.mod h1:1Bja2nEgMDlEJWWRXBUemSPG9qYw84ZYX2gHRVHlR+g= -github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= -github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= -github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= -github.com/goreleaser/goreleaser v0.134.0/go.mod h1:ZT6Y2rSYa6NxQzIsdfWWNWAlYGXGbreo66NmE+3X3WQ= -github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w= -github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.4.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda/go.mod h1:MyndkAZd5rUMdNogn35MWXBX1UiBigrU8eTj8DoAC2c= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= -github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -532,17 +199,13 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-hclog v1.2.2 h1:ihRI7YFwcZdiSD7SIenIhHfQH3OuDvWerAUBZbeQS3M= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= @@ -550,44 +213,22 @@ github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3 github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -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/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault/api v1.9.2 h1:YjkZLJ7K3inKgMZ0wzCU9OHqc+UqMQyXsPXnf3Cl2as= -github.com/hashicorp/vault/api v1.9.2/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= -github.com/hashicorp/vault/api/auth/approle v0.4.1 h1:NElpX7DZ2uaLGwY+leWXHUqw9tepsYkcHvIowgIZteI= -github.com/hashicorp/vault/api/auth/approle v0.4.1/go.mod h1:rlI2VbmuHkptRun7DngpxOSvRC+JuITqAs/Z09pUucU= -github.com/hashicorp/vault/api/auth/kubernetes v0.4.1 h1:amFWL1ZhwMWdmqvT51J9phXu835kY25wFfTrY/3yXd0= -github.com/hashicorp/vault/api/auth/kubernetes v0.4.1/go.mod h1:ikWDT8Adnfvm+8DzKez50vvLD9GWD/unZfJxeqP09sU= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= -github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +github.com/hashicorp/vault/api v1.10.0 h1:/US7sIjWN6Imp4o/Rj1Ce2Nr5bki/AXi9vAW3p2tOJQ= +github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= +github.com/hashicorp/vault/api/auth/approle v0.5.0 h1:a1TK6VGwYqSAfkmX4y4dJ4WBxMU5dStIZqScW4EPXR8= +github.com/hashicorp/vault/api/auth/approle v0.5.0/go.mod h1:CHOQIA1AZACfjTzHggmyfiOZ+xCSKNRFqe48FTCzH0k= +github.com/hashicorp/vault/api/auth/kubernetes v0.5.0 h1:CXO0fD7M3iCGovP/UApeHhPcH4paDFKcu7AjEXi94rI= +github.com/hashicorp/vault/api/auth/kubernetes v0.5.0/go.mod h1:afrElBIO9Q4sHFVuVWgNevG4uAs1bT2AZFA9aEiI608= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -636,300 +277,118 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= -github.com/jhump/protoreflect v1.8.2/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= -github.com/jhump/protoreflect v1.9.0/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= 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/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/micromdm/scep/v2 v2.1.0 h1:2fS9Rla7qRR266hvUoEauBJ7J6FhgssEiq2OkSKXmaU= -github.com/micromdm/scep/v2 v2.1.0/go.mod h1:BkF7TkPPhmgJAMtHfP+sFTKXmgzNJgLQlvvGoOExBcc= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -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/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= -github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/newrelic/go-agent/v3 v3.23.1 h1:n4CK4EEod2A47T74wQFztavh9g3wHxxmlndj53ksbVg= -github.com/newrelic/go-agent/v3 v3.23.1/go.mod h1:dG7Q7yLUrqOo7SYVJADVDN9+P8c/87xp9axldPxmdHM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= -github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/newrelic/go-agent/v3 v3.28.0 h1:zrDJpU6wp84VvU0uUM0ExuSFSRGcKfPvw4WMEnBgIMo= +github.com/newrelic/go-agent/v3 v3.28.0/go.mod h1:qKzHfnXvk2XM0iOkBLMmeNckhUd4AGlI66vliWxp/Wk= +github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv/v3 v3.0.1 h1:x06SQA46+PKIUftmEujdwSEpIx8kR+M9eLYsUxeYveU= github.com/peterbourgon/diskv/v3 v3.0.1/go.mod h1:kJ5Ny7vLdARGU3WUuy6uzO6T0nb/2gWcT1JiBvRmb5o= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -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_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -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/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= -github.com/pseudomuto/protoc-gen-doc v1.4.1/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg= -github.com/pseudomuto/protoc-gen-doc v1.5.0/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg= -github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/schollz/jsonstore v1.1.0 h1:WZBDjgezFS34CHI+myb4s8GGpir3UMpy7vWoCeO0n6E= github.com/schollz/jsonstore v1.1.0/go.mod h1:15c6+9guw8vDRyozGjN3FoILt0wpruJk9Pi66vjaZfg= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -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= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slackhq/nebula v1.6.1 h1:/OCTR3abj0Sbf2nGoLUrdDXImrCv0ZVFpVPP5qa0DsM= github.com/slackhq/nebula v1.6.1/go.mod h1:UmkqnXe4O53QwToSl/gG7sM4BroQwAB7dd4hUaT6MlI= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= -github.com/smallstep/go-attestation v0.4.4-0.20230509120429-e17291421738 h1:h+cZgVniTaE0uuRMdxTThLaJeuxsv4aas6oStz6f5VQ= -github.com/smallstep/go-attestation v0.4.4-0.20230509120429-e17291421738/go.mod h1:mk2hyNbyai1oon+ilW9t42BuBVw7ee8elDdgrPq4394= +github.com/smallstep/go-attestation v0.4.4-0.20230627102604-cf579e53cbd2 h1:UIAS8DTWkeclraEGH2aiJPyNPu16VbT41w4JoBlyFfU= +github.com/smallstep/go-attestation v0.4.4-0.20230627102604-cf579e53cbd2/go.mod h1:vNAduivU014fubg6ewygkAvQC0IQVXqdc8vaGl/0er4= github.com/smallstep/nosql v0.6.0 h1:ur7ysI8s9st0cMXnTvB8tA3+x5Eifmkb6hl4uqNV5jc= github.com/smallstep/nosql v0.6.0/go.mod h1:jOXwLtockXORUPPZ2MCUcIkGR6w0cN1QGZniY9DITQA= -github.com/smallstep/pkcs7 v0.0.0-20230302202335-4c094085c948 h1:/80FqDt6pzL9clNW8G2IsRAzKGNAuzsEs7g1Y5oaM/Y= -github.com/smallstep/pkcs7 v0.0.0-20230302202335-4c094085c948/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5-0.20210205191134-5ec6847320e5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/smallstep/pkcs7 v0.0.0-20231024181729-3b98ecc1ca81 h1:B6cED3iLJTgxpdh4tuqByDjRRKan2EvtnOfHr2zHJVg= +github.com/smallstep/pkcs7 v0.0.0-20231024181729-3b98ecc1ca81/go.mod h1:SoUAr/4M46rZ3WaLstHxGhLEgoYIDRqxQEXLOmOEB0Y= +github.com/smallstep/scep v0.0.0-20231024192529-aee96d7ad34d h1:06LUHn4Ia2X6syjIaCMNaXXDNdU+1N/oOHynJbWgpXw= +github.com/smallstep/scep v0.0.0-20231024192529-aee96d7ad34d/go.mod h1:4d0ub42ut1mMtvGyMensjuHYEUpRrASvkzLEJvoRQcU= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -938,28 +397,15 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -971,483 +417,155 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 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/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= -github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= -github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= -github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= -go.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0-alpha.0/go.mod h1:kdV+xzCJ3luEBSIeQyB/OEKkWKd8Zkux4sbDeANrosU= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0-alpha.0/go.mod h1:wKt7jgDgf/OfKiYmCq5WFGxOFAkVMLxiiXgLDFhECr8= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/etcdctl/v3 v3.5.0-alpha.0/go.mod h1:YPwSaBciV5G6Gpt435AasAG3ROetZsKNUzibRa/++oo= -go.etcd.io/etcd/etcdctl/v3 v3.5.0/go.mod h1:vGTfKdsh87RI7kA2JHFBEGxjQEYx+pi299wqEOdi34M= -go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= -go.etcd.io/etcd/pkg/v3 v3.5.0-alpha.0/go.mod h1:tV31atvwzcybuqejDoY3oaNRTtlD2l/Ot78Pc9w7DMY= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0-alpha.0/go.mod h1:FAwse6Zlm5v4tEWZaTjmNhe17Int4Oxbu7+2r0DiD3w= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0-alpha.0/go.mod h1:tsKetYpt980ZTpzl/gb+UOJj9RkIyCb1u4wjzMg90BQ= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.etcd.io/etcd/tests/v3 v3.5.0-alpha.0/go.mod h1:HnrHxjyCuZ8YDt8PYVyQQ5d1ZQfzJVEtQWllr5Vp/30= -go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= -go.etcd.io/etcd/v3 v3.5.0-alpha.0/go.mod h1:JZ79d3LV6NUfPjUxXrpiFAYcjhT+06qqw+i28snx8To= -go.etcd.io/etcd/v3 v3.5.0/go.mod h1:FldM0/VzcxYWLvWx1sdA7ghKw7C3L2DvUTzGrcEtsC4= -go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -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/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/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.step.sm/cli-utils v0.8.0 h1:b/Tc1/m3YuQq+u3ghTFP7Dz5zUekZj6GUmd5pCvkEXQ= go.step.sm/cli-utils v0.8.0/go.mod h1:S77aISrC0pKuflqiDfxxJlUbiXcAanyJ4POOnzFSxD4= -go.step.sm/crypto v0.33.0 h1:fP8awo6YkZ0/rrLhzbHYA3U8g24VnWEebZRnGwUobRo= -go.step.sm/crypto v0.33.0/go.mod h1:rMETKeIA1ZsLBiKT6phQ2IIeBH3GL+XqimeobcqUw1g= -go.step.sm/linkedca v0.20.0 h1:bH41rvyDm3nSSJ5xgGsKUZOpzJcq5x2zacMIeqtq9oI= -go.step.sm/linkedca v0.20.0/go.mod h1:eybHw6ZTpuFmkUQnTBRWM2SPIGaP0VbYeo1bupfPT70= +go.step.sm/crypto v0.37.0 h1:on84zlUM7t9HsTQd7A5dmzu3t1ig2ShleiGhPwux1dA= +go.step.sm/crypto v0.37.0/go.mod h1:aTwcV592Z8XvHGmtdmkYTQBWCKv3XmfKv3rP/QjbC4w= +go.step.sm/linkedca v0.20.1 h1:bHDn1+UG1NgRrERkWbbCiAIvv4lD5NOFaswPDTyO5vU= +go.step.sm/linkedca v0.20.1/go.mod h1:Vaq4+Umtjh7DLFI1KuIxeo598vfBzgSYZUjgVJ7Syxw= 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= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= -golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw= golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sys v0.0.0-20170728174421-0f826bdd13b5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191119060738-e882bf8e40c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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-20210629170331-7dc0b73dc9fb/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= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191118222007-07fc4c7f2b98/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201014170642-d1624618ad65/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1455,162 +573,28 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.37.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= -google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.132.0 h1:8t2/+qZ26kAOGSmOiHwVycqVaDg7q3JDILrNi/Z6rvc= -google.golang.org/api v0.132.0/go.mod h1:AeTBC6GpJnJSRJjktDcPX0QwtS8pGYZOV6MSuSCusw0= +google.golang.org/api v0.151.0 h1:FhfXLO/NFdJIzQtCqjpysWwqKk8AzGWBUhMIx67cVDU= +google.golang.org/api v0.151.0/go.mod h1:ccy+MJ6nrYFgE3WgRx/AMXOxOmU8Q4hSa+jjibzhxcg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210331142528-b7513248f0ba/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210427215850-f767ed18ee4d/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8= -google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -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= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= +google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k= +google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= -google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1619,65 +603,27 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/logging/handler_test.go b/logging/handler_test.go index 6cafc10c..8ab2a3c0 100644 --- a/logging/handler_test.go +++ b/logging/handler_test.go @@ -58,7 +58,7 @@ func TestHealthOKHandling(t *testing.T) { next: tt.handler, } - r := httptest.NewRequest("GET", tt.path, nil) + r := httptest.NewRequest("GET", tt.path, http.NoBody) w := httptest.NewRecorder() l.ServeHTTP(w, r) @@ -132,7 +132,7 @@ func TestHandlingRegardlessOfOptions(t *testing.T) { next: tt.handler, } - r := httptest.NewRequest("GET", tt.path, nil) + r := httptest.NewRequest("GET", tt.path, http.NoBody) w := httptest.NewRecorder() l.ServeHTTP(w, r) diff --git a/logging/logger.go b/logging/logger.go index 7ea25077..1716a7f4 100644 --- a/logging/logger.go +++ b/logging/logger.go @@ -3,6 +3,7 @@ package logging import ( "encoding/json" "net/http" + "os" "strings" "github.com/pkg/errors" @@ -38,6 +39,13 @@ func New(name string, raw json.RawMessage) (*Logger, error) { var formatter logrus.Formatter switch strings.ToLower(config.Format) { case "", "text": + _, noColor := os.LookupEnv("NO_COLOR") + // With EnvironmentOverrideColors set, logrus looks at CLICOLOR and + // CLICOLOR_FORCE + formatter = &logrus.TextFormatter{ + DisableColors: noColor, + EnvironmentOverrideColors: true, + } case "json": formatter = new(logrus.JSONFormatter) case "common": diff --git a/pki/helm.go b/pki/helm.go index 3c5cb5a9..3de2c2ec 100644 --- a/pki/helm.go +++ b/pki/helm.go @@ -1,6 +1,7 @@ package pki import ( + "fmt" "io" "text/template" @@ -49,21 +50,42 @@ func (p *PKI) WriteHelmTemplate(w io.Writer) error { // to what's in p.GenerateConfig(), but that codepath isn't taken when // writing the Helm template. The default JWK provisioner is added earlier in // the process and that's part of the provisioners above. + // + // To prevent name clashes for the default ACME provisioner, we append "-1" to + // the name if it already exists. See https://github.com/smallstep/cli/issues/1018 + // for the reason. + // // TODO(hs): consider refactoring the initialization, so that this becomes // easier to reason about and maintain. if p.options.enableACME { + acmeProvisionerName := "acme" + for _, prov := range provisioners { + if prov.GetName() == acmeProvisionerName { + acmeProvisionerName = fmt.Sprintf("%s-1", acmeProvisionerName) + break + } + } provisioners = append(provisioners, &provisioner.ACME{ Type: "ACME", - Name: "acme", + Name: acmeProvisionerName, }) } // Add default SSHPOP provisioner if enabled. Similar to the above, this is - // the same as what happens in p.GenerateConfig(). + // the same as what happens in p.GenerateConfig(). To prevent name clashes for the + // default SSHPOP provisioner, we append "-1" to it if it already exists. See + // https://github.com/smallstep/cli/issues/1018 for the reason. if p.options.enableSSH { + sshProvisionerName := "sshpop" + for _, prov := range provisioners { + if prov.GetName() == sshProvisionerName { + sshProvisionerName = fmt.Sprintf("%s-1", sshProvisionerName) + break + } + } provisioners = append(provisioners, &provisioner.SSHPOP{ Type: "SSHPOP", - Name: "sshpop", + Name: sshProvisionerName, Claims: &provisioner.Claims{ EnableSSHCA: &p.options.enableSSH, }, diff --git a/pki/helm_test.go b/pki/helm_test.go index 508f8c3e..3aa0d224 100644 --- a/pki/helm_test.go +++ b/pki/helm_test.go @@ -85,6 +85,13 @@ func TestPKI_WriteHelmTemplate(t *testing.T) { wantErr: false, } }, + "ok/with-acme-and-duplicate-provisioner-name": func(t *testing.T) test { + return test{ + pki: preparePKI(t, WithProvisioner("acme"), WithACME()), + testFile: "testdata/helm/with-acme-and-duplicate-provisioner-name.yml", + wantErr: false, + } + }, "ok/with-admin": func(t *testing.T) test { return test{ pki: preparePKI(t, WithAdmin()), @@ -99,6 +106,13 @@ func TestPKI_WriteHelmTemplate(t *testing.T) { wantErr: false, } }, + "ok/with-ssh-and-duplicate-provisioner-name": func(t *testing.T) test { + return test{ + pki: preparePKI(t, WithProvisioner("sshpop"), WithSSH()), + testFile: "testdata/helm/with-ssh-and-duplicate-provisioner-name.yml", + wantErr: false, + } + }, "ok/with-ssh-and-acme": func(t *testing.T) test { return test{ pki: preparePKI(t, WithSSH(), WithACME()), diff --git a/pki/pki.go b/pki/pki.go index 971c189b..234bae5a 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -319,7 +319,10 @@ type PKI struct { func New(o apiv1.Options, opts ...Option) (*PKI, error) { // TODO(hs): invoking `New` with a context active will use values from // that CA context while generating the context. Thay may or may not - // be fully expected and/or what we want. Check that. + // be fully expected and/or what we want. This specific behavior was + // changed after not relying on the `init` inside of `step`, resulting in + // the default context being active if `step.Init` isn't called explicitly. + // It can still result in surprising results, though. currentCtx := step.Contexts().GetCurrent() caService, err := cas.New(context.Background(), o) if err != nil { @@ -330,7 +333,7 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { if o.IsCreator { creator, ok := caService.(apiv1.CertificateAuthorityCreator) if !ok { - return nil, errors.Errorf("cas type '%s' does not implements CertificateAuthorityCreator", o.Type) + return nil, errors.Errorf("cas type %q does not implement CertificateAuthorityCreator", o.Type) } caCreator = creator } @@ -850,9 +853,16 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { // Add default ACME provisioner if enabled if p.options.enableACME { + // To prevent name clashes for the default ACME provisioner, we append "-1" to + // the name if it already exists. See https://github.com/smallstep/cli/issues/1018 + // for the reason. + acmeProvisionerName := "acme" + if p.options.provisioner == acmeProvisionerName { + acmeProvisionerName = fmt.Sprintf("%s-1", acmeProvisionerName) + } provisioners = append(provisioners, &provisioner.ACME{ Type: "ACME", - Name: "acme", + Name: acmeProvisionerName, }) } @@ -867,10 +877,16 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { EnableSSHCA: &enableSSHCA, } - // Add default SSHPOP provisioner + // Add default SSHPOP provisioner. To prevent name clashes for the default + // SSHPOP provisioner, we append "-1" to the name if it already exists. + // See https://github.com/smallstep/cli/issues/1018 for the reason. + sshProvisionerName := "sshpop" + if p.options.provisioner == sshProvisionerName { + sshProvisionerName = fmt.Sprintf("%s-1", sshProvisionerName) + } provisioners = append(provisioners, &provisioner.SSHPOP{ Type: "SSHPOP", - Name: "sshpop", + Name: sshProvisionerName, Claims: &provisioner.Claims{ EnableSSHCA: &enableSSHCA, }, @@ -910,10 +926,13 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { if err != nil { return nil, err } + defer _db.Shutdown() // free DB resources; unlock BadgerDB file + adminDB, err := admindb.New(_db.(nosql.DB), admin.DefaultAuthorityID) if err != nil { return nil, err } + // Add all the provisioners to the db. var adminID string for i, p := range provisioners { diff --git a/pki/pki_test.go b/pki/pki_test.go new file mode 100644 index 00000000..7d5bc8c5 --- /dev/null +++ b/pki/pki_test.go @@ -0,0 +1,313 @@ +package pki + +import ( + "context" + "path/filepath" + "testing" + + "github.com/smallstep/certificates/authority/admin" + admindb "github.com/smallstep/certificates/authority/admin/db/nosql" + authconfig "github.com/smallstep/certificates/authority/config" + "github.com/smallstep/certificates/authority/provisioner" + "github.com/smallstep/certificates/cas/apiv1" + "github.com/smallstep/certificates/db" + "github.com/smallstep/nosql" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.step.sm/cli-utils/step" +) + +func withDBDataSource(t *testing.T, dataSource string) func(c *authconfig.Config) error { + return func(c *authconfig.Config) error { + if c == nil || c.DB == nil { + require.Fail(t, "withDBDataSource prerequisites not met") + } + c.DB.DataSource = dataSource + return nil + } +} + +func TestPKI_GenerateConfig(t *testing.T) { + var preparePKI = func(t *testing.T, opts ...Option) *PKI { + o := apiv1.Options{ + Type: "softcas", + IsCreator: true, + } + + // TODO(hs): invoking `New` doesn't perform all operations that are executed + // when `ca init` is executed. Ideally this logic should be handled in one + // place and probably inside of the PKI initialization. For testing purposes + // the missing operations are faked by `setKeyPair`. + p, err := New(o, opts...) + require.NoError(t, err) + + // setKeyPair sets a predefined JWK and a default JWK provisioner. This is one + // of the things performed in the `ca init` code that's not part of `New`, but + // performed after that in p.GenerateKeyPairs`. We're currently using the same + // JWK for every test to keep test variance small: we're not testing JWK generation + // here after all. It's a bit dangerous to redefine the function here, but it's + // the simplest way to make this fully testable without refactoring the init now. + // The password for the predefined encrypted key is \x01\x03\x03\x07. + setKeyPair(t, p) + + return p + } + type args struct { + opt []ConfigOption + } + type test struct { + pki *PKI + args args + want *authconfig.Config + wantErr bool + } + var tests = map[string]func(t *testing.T) test{ + "ok/simple": func(t *testing.T) test { + pki := preparePKI(t) + pki.options.deploymentType = StandaloneDeployment + pki.options.provisioner = "default-prov" + return test{ + pki: pki, + args: args{ + []ConfigOption{}, + }, + want: &authconfig.Config{ + Address: "127.0.0.1:9000", + InsecureAddress: "", + DNSNames: []string{"127.0.0.1"}, + AuthorityConfig: &authconfig.AuthConfig{ + DeploymentType: "", // TODO(hs): (why is) this is not set to standalone? + EnableAdmin: false, + Provisioners: provisioner.List{ + &provisioner.JWK{ + Type: "JWK", + Name: "default-prov", + }, + }, + }, + DB: &db.Config{ + Type: "badgerv2", + DataSource: filepath.Join(step.Path(), "db"), + }, + }, + wantErr: false, + } + }, + "ok/with-acme": func(t *testing.T) test { + pki := preparePKI(t) + pki.options.deploymentType = StandaloneDeployment + pki.options.provisioner = "default-prov" + pki.options.enableACME = true + return test{ + pki: pki, + args: args{ + []ConfigOption{}, + }, + want: &authconfig.Config{ + Address: "127.0.0.1:9000", + InsecureAddress: "", + DNSNames: []string{"127.0.0.1"}, + AuthorityConfig: &authconfig.AuthConfig{ + DeploymentType: "", // TODO(hs): (why is) this is not set to standalone? + EnableAdmin: false, + Provisioners: provisioner.List{ + &provisioner.JWK{ + Type: "JWK", + Name: "default-prov", + }, + &provisioner.ACME{ + Type: "ACME", + Name: "acme", + }, + }, + }, + DB: &db.Config{ + Type: "badgerv2", + DataSource: filepath.Join(step.Path(), "db"), + }, + }, + wantErr: false, + } + }, + "ok/with-acme-and-double-provisioner-name": func(t *testing.T) test { + pki := preparePKI(t) + pki.options.deploymentType = StandaloneDeployment + pki.options.provisioner = "acme" + pki.options.enableACME = true + return test{ + pki: pki, + args: args{ + []ConfigOption{}, + }, + want: &authconfig.Config{ + Address: "127.0.0.1:9000", + InsecureAddress: "", + DNSNames: []string{"127.0.0.1"}, + AuthorityConfig: &authconfig.AuthConfig{ + DeploymentType: "", // TODO(hs): (why is) this is not set to standalone? + EnableAdmin: false, + Provisioners: provisioner.List{ + &provisioner.JWK{ + Type: "JWK", + Name: "acme", + }, + &provisioner.ACME{ + Type: "ACME", + Name: "acme-1", + }, + }, + }, + DB: &db.Config{ + Type: "badgerv2", + DataSource: filepath.Join(step.Path(), "db"), + }, + }, + wantErr: false, + } + }, + "ok/with-ssh": func(t *testing.T) test { + pki := preparePKI(t) + pki.options.deploymentType = StandaloneDeployment + pki.options.provisioner = "default-prov" + pki.options.enableSSH = true + return test{ + pki: pki, + args: args{ + []ConfigOption{}, + }, + want: &authconfig.Config{ + Address: "127.0.0.1:9000", + InsecureAddress: "", + DNSNames: []string{"127.0.0.1"}, + AuthorityConfig: &authconfig.AuthConfig{ + DeploymentType: "", // TODO(hs): (why is) this is not set to standalone? + EnableAdmin: false, + Provisioners: provisioner.List{ + &provisioner.JWK{ + Type: "JWK", + Name: "default-prov", + }, + &provisioner.SSHPOP{ + Type: "SSHPOP", + Name: "sshpop", + }, + }, + }, + DB: &db.Config{ + Type: "badgerv2", + DataSource: filepath.Join(step.Path(), "db"), + }, + }, + wantErr: false, + } + }, + "ok/with-ssh-and-double-provisioner-name": func(t *testing.T) test { + pki := preparePKI(t) + pki.options.deploymentType = StandaloneDeployment + pki.options.provisioner = "sshpop" + pki.options.enableSSH = true + return test{ + pki: pki, + args: args{ + []ConfigOption{}, + }, + want: &authconfig.Config{ + Address: "127.0.0.1:9000", + InsecureAddress: "", + DNSNames: []string{"127.0.0.1"}, + AuthorityConfig: &authconfig.AuthConfig{ + DeploymentType: "", // TODO(hs): (why is) this is not set to standalone? + EnableAdmin: false, + Provisioners: provisioner.List{ + &provisioner.JWK{ + Type: "JWK", + Name: "sshpop", + }, + &provisioner.SSHPOP{ + Type: "SSHPOP", + Name: "sshpop-1", + }, + }, + }, + DB: &db.Config{ + Type: "badgerv2", + DataSource: filepath.Join(step.Path(), "db"), + }, + }, + wantErr: false, + } + }, + "ok/with-admin": func(t *testing.T) test { + pki := preparePKI(t) + pki.options.deploymentType = StandaloneDeployment + pki.options.provisioner = "default-prov" + pki.options.enableAdmin = true + tempDir := t.TempDir() + return test{ + pki: pki, + args: args{ + []ConfigOption{withDBDataSource(t, filepath.Join(tempDir, "db"))}, + }, + want: &authconfig.Config{ + Address: "127.0.0.1:9000", + InsecureAddress: "", + DNSNames: []string{"127.0.0.1"}, + AuthorityConfig: &authconfig.AuthConfig{ + DeploymentType: "", // TODO(hs): (why is) this is not set to standalone? + EnableAdmin: true, + Provisioners: provisioner.List{}, // when admin is enabled, provisioner list is expected to be empty + }, + DB: &db.Config{ + Type: "badgerv2", + DataSource: filepath.Join(tempDir, "db"), + }, + }, + wantErr: false, + } + }, + } + for name, run := range tests { + tc := run(t) + t.Run(name, func(t *testing.T) { + got, err := tc.pki.GenerateConfig(tc.args.opt...) + if tc.wantErr { + assert.NotNil(t, err) + assert.Nil(t, got) + return + } + + assert.Nil(t, err) + if assert.NotNil(t, got) { + assert.Equal(t, tc.want.Address, got.Address) + assert.Equal(t, tc.want.InsecureAddress, got.InsecureAddress) + assert.Equal(t, tc.want.DNSNames, got.DNSNames) + assert.Equal(t, tc.want.DB, got.DB) + if assert.NotNil(t, tc.want.AuthorityConfig) { + assert.Equal(t, tc.want.AuthorityConfig.DeploymentType, got.AuthorityConfig.DeploymentType) + assert.Equal(t, tc.want.AuthorityConfig.EnableAdmin, got.AuthorityConfig.EnableAdmin) + if numberOfProvisioners := len(tc.want.AuthorityConfig.Provisioners); numberOfProvisioners > 0 { + if assert.Len(t, got.AuthorityConfig.Provisioners, numberOfProvisioners) { + for i, p := range tc.want.AuthorityConfig.Provisioners { + assert.Equal(t, p.GetType(), got.AuthorityConfig.Provisioners[i].GetType()) + assert.Equal(t, p.GetName(), got.AuthorityConfig.Provisioners[i].GetName()) + } + } + } + if tc.want.AuthorityConfig.EnableAdmin { + _db, err := db.New(tc.want.DB) + require.NoError(t, err) + defer _db.Shutdown() + + adminDB, err := admindb.New(_db.(nosql.DB), admin.DefaultAuthorityID) + require.NoError(t, err) + + provs, err := adminDB.GetProvisioners(context.Background()) + require.NoError(t, err) + + assert.NotEmpty(t, provs) // currently about the best we can do in terms of checks + } + } + } + }) + } +} diff --git a/pki/testdata/helm/with-acme-and-duplicate-provisioner-name.yml b/pki/testdata/helm/with-acme-and-duplicate-provisioner-name.yml new file mode 100644 index 00000000..f4532207 --- /dev/null +++ b/pki/testdata/helm/with-acme-and-duplicate-provisioner-name.yml @@ -0,0 +1,82 @@ +# Helm template +inject: + enabled: true + # Config contains the configuration files ca.json and defaults.json + config: + files: + ca.json: + root: /home/step/certs/root_ca.crt + federateRoots: [] + crt: /home/step/certs/intermediate_ca.crt + key: /home/step/secrets/intermediate_ca_key + address: 127.0.0.1:9000 + dnsNames: + - 127.0.0.1 + logger: + format: json + db: + type: badgerv2 + dataSource: /home/step/db + authority: + enableAdmin: false + provisioners: + - {"type":"JWK","name":"acme","key":{"use":"sig","kty":"EC","kid":"zsUmysmDVoGJ71YoPHyZ-68tNihDaDaO5Mu7xX3M-_I","crv":"P-256","alg":"ES256","x":"Pqnua4CzqKz6ua41J3yeWZ1sRkGt0UlCkbHv8H2DGuY","y":"UhoZ_2ItDen9KQTcjay-ph-SBXH0mwqhHyvrrqIFDOI"},"encryptedKey":"eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiZjVvdGVRS2hvOXl4MmQtSGlMZi05QSJ9.eYA6tt3fNuUpoxKWDT7P0Lbn2juxhEbTxEnwEMbjlYLLQ3sxL-dYTA.ven-FhmdjlC9itH0.a2jRTarN9vPd6F_mWnNBlOn6KbfMjCApmci2t65XbAsLzYFzhI_79Ykm5ueMYTupWLTjBJctl-g51ZHmsSB55pStbpoyyLNAsUX2E1fTmHe-Ni8bRrspwLv15FoN1Xo1g0mpR-ufWIFxOsW-QIfnMmMIIkygVuHFXmg2tFpzTNNG5aS29K3dN2nyk0WJrdIq79hZSTqVkkBU25Yu3A46sgjcM86XcIJJ2XUEih_KWEa6T1YrkixGu96pebjVqbO0R6dbDckfPF7FqNnwPHVtb1ACFpEYoOJVIbUCMaARBpWsxYhjJZlEM__XA46l8snFQDkNY3CdN0p1_gF3ckA.JLmq9nmu1h9oUi1S8ZxYjA","options":{"x509":{},"ssh":{}}} + - {"type":"ACME","name":"acme-1"} + tls: + cipherSuites: + - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + minVersion: 1.2 + maxVersion: 1.3 + renegotiation: false + + defaults.json: + ca-url: https://127.0.0.1 + ca-config: /home/step/config/ca.json + fingerprint: e543cad8e9f6417076bb5aed3471c588152118aac1e0ca7984a43ee7f76da5e3 + root: /home/step/certs/root_ca.crt + + # Certificates contains the root and intermediate certificate and + # optionally the SSH host and user public keys + certificates: + # intermediate_ca contains the text of the intermediate CA Certificate + intermediate_ca: | + -----BEGIN CERTIFICATE----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIGludGVybWVkaWF0ZSBDQSBjZXJ0IGJ5 + dGVz + -----END CERTIFICATE----- + + + # root_ca contains the text of the root CA Certificate + root_ca: | + -----BEGIN CERTIFICATE----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIHJvb3QgQ0EgY2VydCBieXRlcw== + -----END CERTIFICATE----- + + + # Secrets contains the root and intermediate keys and optionally the SSH + # private keys + secrets: + # ca_password contains the password used to encrypt x509.intermediate_ca_key, ssh.host_ca_key and ssh.user_ca_key + # This value must be base64 encoded. + ca_password: + provisioner_password: + + x509: + # intermediate_ca_key contains the contents of your encrypted intermediate CA key + intermediate_ca_key: | + -----BEGIN EC PRIVATE KEY----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIGludGVybWVkaWF0ZSBDQSBrZXkgYnl0 + ZXM= + -----END EC PRIVATE KEY----- + + + # root_ca_key contains the contents of your encrypted root CA key + # Note that this value can be omitted without impacting the functionality of step-certificates + # If supplied, this should be encrypted using a unique password that is not used for encrypting + # the intermediate_ca_key, ssh.host_ca_key or ssh.user_ca_key. + root_ca_key: | + -----BEGIN EC PRIVATE KEY----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIHJvb3QgQ0Ega2V5IGJ5dGVz + -----END EC PRIVATE KEY----- + diff --git a/pki/testdata/helm/with-ssh-and-acme.yml b/pki/testdata/helm/with-ssh-and-acme.yml index 639aca6a..7398c7e5 100644 --- a/pki/testdata/helm/with-ssh-and-acme.yml +++ b/pki/testdata/helm/with-ssh-and-acme.yml @@ -23,7 +23,7 @@ inject: authority: enableAdmin: false provisioners: - - {"type":"JWK","name":"step-cli","key":{"use":"sig","kty":"EC","kid":"zsUmysmDVoGJ71YoPHyZ-68tNihDaDaO5Mu7xX3M-_I","crv":"P-256","alg":"ES256","x":"Pqnua4CzqKz6ua41J3yeWZ1sRkGt0UlCkbHv8H2DGuY","y":"UhoZ_2ItDen9KQTcjay-ph-SBXH0mwqhHyvrrqIFDOI"},"encryptedKey":"eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiZjVvdGVRS2hvOXl4MmQtSGlMZi05QSJ9.eYA6tt3fNuUpoxKWDT7P0Lbn2juxhEbTxEnwEMbjlYLLQ3sxL-dYTA.ven-FhmdjlC9itH0.a2jRTarN9vPd6F_mWnNBlOn6KbfMjCApmci2t65XbAsLzYFzhI_79Ykm5ueMYTupWLTjBJctl-g51ZHmsSB55pStbpoyyLNAsUX2E1fTmHe-Ni8bRrspwLv15FoN1Xo1g0mpR-ufWIFxOsW-QIfnMmMIIkygVuHFXmg2tFpzTNNG5aS29K3dN2nyk0WJrdIq79hZSTqVkkBU25Yu3A46sgjcM86XcIJJ2XUEih_KWEa6T1YrkixGu96pebjVqbO0R6dbDckfPF7FqNnwPHVtb1ACFpEYoOJVIbUCMaARBpWsxYhjJZlEM__XA46l8snFQDkNY3CdN0p1_gF3ckA.JLmq9nmu1h9oUi1S8ZxYjA","claims":{"enableSSHCA":true,"disableRenewal":false,"allowRenewalAfterExpiry":false},"options":{"x509":{},"ssh":{}}} + - {"type":"JWK","name":"step-cli","key":{"use":"sig","kty":"EC","kid":"zsUmysmDVoGJ71YoPHyZ-68tNihDaDaO5Mu7xX3M-_I","crv":"P-256","alg":"ES256","x":"Pqnua4CzqKz6ua41J3yeWZ1sRkGt0UlCkbHv8H2DGuY","y":"UhoZ_2ItDen9KQTcjay-ph-SBXH0mwqhHyvrrqIFDOI"},"encryptedKey":"eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiZjVvdGVRS2hvOXl4MmQtSGlMZi05QSJ9.eYA6tt3fNuUpoxKWDT7P0Lbn2juxhEbTxEnwEMbjlYLLQ3sxL-dYTA.ven-FhmdjlC9itH0.a2jRTarN9vPd6F_mWnNBlOn6KbfMjCApmci2t65XbAsLzYFzhI_79Ykm5ueMYTupWLTjBJctl-g51ZHmsSB55pStbpoyyLNAsUX2E1fTmHe-Ni8bRrspwLv15FoN1Xo1g0mpR-ufWIFxOsW-QIfnMmMIIkygVuHFXmg2tFpzTNNG5aS29K3dN2nyk0WJrdIq79hZSTqVkkBU25Yu3A46sgjcM86XcIJJ2XUEih_KWEa6T1YrkixGu96pebjVqbO0R6dbDckfPF7FqNnwPHVtb1ACFpEYoOJVIbUCMaARBpWsxYhjJZlEM__XA46l8snFQDkNY3CdN0p1_gF3ckA.JLmq9nmu1h9oUi1S8ZxYjA","claims":{"enableSSHCA":true,"disableRenewal":false,"allowRenewalAfterExpiry":false,"disableSmallstepExtensions":false},"options":{"x509":{},"ssh":{}}} - {"type":"ACME","name":"acme"} - {"type":"SSHPOP","name":"sshpop","claims":{"enableSSHCA":true}} tls: diff --git a/pki/testdata/helm/with-ssh-and-duplicate-provisioner-name.yml b/pki/testdata/helm/with-ssh-and-duplicate-provisioner-name.yml new file mode 100644 index 00000000..a499b155 --- /dev/null +++ b/pki/testdata/helm/with-ssh-and-duplicate-provisioner-name.yml @@ -0,0 +1,104 @@ +# Helm template +inject: + enabled: true + # Config contains the configuration files ca.json and defaults.json + config: + files: + ca.json: + root: /home/step/certs/root_ca.crt + federateRoots: [] + crt: /home/step/certs/intermediate_ca.crt + key: /home/step/secrets/intermediate_ca_key + ssh: + hostKey: /home/step/secrets/ssh_host_ca_key + userKey: /home/step/secrets/ssh_user_ca_key + address: 127.0.0.1:9000 + dnsNames: + - 127.0.0.1 + logger: + format: json + db: + type: badgerv2 + dataSource: /home/step/db + authority: + enableAdmin: false + provisioners: + - {"type":"JWK","name":"sshpop","key":{"use":"sig","kty":"EC","kid":"zsUmysmDVoGJ71YoPHyZ-68tNihDaDaO5Mu7xX3M-_I","crv":"P-256","alg":"ES256","x":"Pqnua4CzqKz6ua41J3yeWZ1sRkGt0UlCkbHv8H2DGuY","y":"UhoZ_2ItDen9KQTcjay-ph-SBXH0mwqhHyvrrqIFDOI"},"encryptedKey":"eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiZjVvdGVRS2hvOXl4MmQtSGlMZi05QSJ9.eYA6tt3fNuUpoxKWDT7P0Lbn2juxhEbTxEnwEMbjlYLLQ3sxL-dYTA.ven-FhmdjlC9itH0.a2jRTarN9vPd6F_mWnNBlOn6KbfMjCApmci2t65XbAsLzYFzhI_79Ykm5ueMYTupWLTjBJctl-g51ZHmsSB55pStbpoyyLNAsUX2E1fTmHe-Ni8bRrspwLv15FoN1Xo1g0mpR-ufWIFxOsW-QIfnMmMIIkygVuHFXmg2tFpzTNNG5aS29K3dN2nyk0WJrdIq79hZSTqVkkBU25Yu3A46sgjcM86XcIJJ2XUEih_KWEa6T1YrkixGu96pebjVqbO0R6dbDckfPF7FqNnwPHVtb1ACFpEYoOJVIbUCMaARBpWsxYhjJZlEM__XA46l8snFQDkNY3CdN0p1_gF3ckA.JLmq9nmu1h9oUi1S8ZxYjA","claims":{"enableSSHCA":true,"disableRenewal":false,"allowRenewalAfterExpiry":false,"disableSmallstepExtensions":false},"options":{"x509":{},"ssh":{}}} + - {"type":"SSHPOP","name":"sshpop-1","claims":{"enableSSHCA":true}} + tls: + cipherSuites: + - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + minVersion: 1.2 + maxVersion: 1.3 + renegotiation: false + + defaults.json: + ca-url: https://127.0.0.1 + ca-config: /home/step/config/ca.json + fingerprint: e543cad8e9f6417076bb5aed3471c588152118aac1e0ca7984a43ee7f76da5e3 + root: /home/step/certs/root_ca.crt + + # Certificates contains the root and intermediate certificate and + # optionally the SSH host and user public keys + certificates: + # intermediate_ca contains the text of the intermediate CA Certificate + intermediate_ca: | + -----BEGIN CERTIFICATE----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIGludGVybWVkaWF0ZSBDQSBjZXJ0IGJ5 + dGVz + -----END CERTIFICATE----- + + + # root_ca contains the text of the root CA Certificate + root_ca: | + -----BEGIN CERTIFICATE----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIHJvb3QgQ0EgY2VydCBieXRlcw== + -----END CERTIFICATE----- + + # ssh_host_ca contains the text of the public ssh key for the SSH root CA + ssh_host_ca: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ0IdS5sZm6KITBMZLEJD6b5ROVraYHcAOr3feFel8r1Wp4DRPR1oU0W00J/zjNBRBbANlJoYN4x/8WNNVZ49Ms= + + # ssh_user_ca contains the text of the public ssh key for the SSH root CA + ssh_user_ca: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEWA1qUxaGwVNErsvEOGe2d6TvLMF+aiVpuOiIEvpMJ3JeJmecLQctjWqeIbpSvy6/gRa7c82Ge5rLlapYmOChs= + + # Secrets contains the root and intermediate keys and optionally the SSH + # private keys + secrets: + # ca_password contains the password used to encrypt x509.intermediate_ca_key, ssh.host_ca_key and ssh.user_ca_key + # This value must be base64 encoded. + ca_password: + provisioner_password: + + x509: + # intermediate_ca_key contains the contents of your encrypted intermediate CA key + intermediate_ca_key: | + -----BEGIN EC PRIVATE KEY----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIGludGVybWVkaWF0ZSBDQSBrZXkgYnl0 + ZXM= + -----END EC PRIVATE KEY----- + + + # root_ca_key contains the contents of your encrypted root CA key + # Note that this value can be omitted without impacting the functionality of step-certificates + # If supplied, this should be encrypted using a unique password that is not used for encrypting + # the intermediate_ca_key, ssh.host_ca_key or ssh.user_ca_key. + root_ca_key: | + -----BEGIN EC PRIVATE KEY----- + dGhlc2UgYXJlIGp1c3Qgc29tZSBmYWtlIHJvb3QgQ0Ega2V5IGJ5dGVz + -----END EC PRIVATE KEY----- + + ssh: + # ssh_host_ca_key contains the contents of your encrypted SSH Host CA key + host_ca_key: | + -----BEGIN EC PRIVATE KEY----- + ZmFrZSBzc2ggaG9zdCBrZXkgYnl0ZXM= + -----END EC PRIVATE KEY----- + + + # ssh_user_ca_key contains the contents of your encrypted SSH User CA key + user_ca_key: | + -----BEGIN EC PRIVATE KEY----- + ZmFrZSBzc2ggdXNlciBrZXkgYnl0ZXM= + -----END EC PRIVATE KEY----- + diff --git a/pki/testdata/helm/with-ssh.yml b/pki/testdata/helm/with-ssh.yml index 2e4845f0..d5b38de7 100644 --- a/pki/testdata/helm/with-ssh.yml +++ b/pki/testdata/helm/with-ssh.yml @@ -23,7 +23,7 @@ inject: authority: enableAdmin: false provisioners: - - {"type":"JWK","name":"step-cli","key":{"use":"sig","kty":"EC","kid":"zsUmysmDVoGJ71YoPHyZ-68tNihDaDaO5Mu7xX3M-_I","crv":"P-256","alg":"ES256","x":"Pqnua4CzqKz6ua41J3yeWZ1sRkGt0UlCkbHv8H2DGuY","y":"UhoZ_2ItDen9KQTcjay-ph-SBXH0mwqhHyvrrqIFDOI"},"encryptedKey":"eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiZjVvdGVRS2hvOXl4MmQtSGlMZi05QSJ9.eYA6tt3fNuUpoxKWDT7P0Lbn2juxhEbTxEnwEMbjlYLLQ3sxL-dYTA.ven-FhmdjlC9itH0.a2jRTarN9vPd6F_mWnNBlOn6KbfMjCApmci2t65XbAsLzYFzhI_79Ykm5ueMYTupWLTjBJctl-g51ZHmsSB55pStbpoyyLNAsUX2E1fTmHe-Ni8bRrspwLv15FoN1Xo1g0mpR-ufWIFxOsW-QIfnMmMIIkygVuHFXmg2tFpzTNNG5aS29K3dN2nyk0WJrdIq79hZSTqVkkBU25Yu3A46sgjcM86XcIJJ2XUEih_KWEa6T1YrkixGu96pebjVqbO0R6dbDckfPF7FqNnwPHVtb1ACFpEYoOJVIbUCMaARBpWsxYhjJZlEM__XA46l8snFQDkNY3CdN0p1_gF3ckA.JLmq9nmu1h9oUi1S8ZxYjA","claims":{"enableSSHCA":true,"disableRenewal":false,"allowRenewalAfterExpiry":false},"options":{"x509":{},"ssh":{}}} + - {"type":"JWK","name":"step-cli","key":{"use":"sig","kty":"EC","kid":"zsUmysmDVoGJ71YoPHyZ-68tNihDaDaO5Mu7xX3M-_I","crv":"P-256","alg":"ES256","x":"Pqnua4CzqKz6ua41J3yeWZ1sRkGt0UlCkbHv8H2DGuY","y":"UhoZ_2ItDen9KQTcjay-ph-SBXH0mwqhHyvrrqIFDOI"},"encryptedKey":"eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiZjVvdGVRS2hvOXl4MmQtSGlMZi05QSJ9.eYA6tt3fNuUpoxKWDT7P0Lbn2juxhEbTxEnwEMbjlYLLQ3sxL-dYTA.ven-FhmdjlC9itH0.a2jRTarN9vPd6F_mWnNBlOn6KbfMjCApmci2t65XbAsLzYFzhI_79Ykm5ueMYTupWLTjBJctl-g51ZHmsSB55pStbpoyyLNAsUX2E1fTmHe-Ni8bRrspwLv15FoN1Xo1g0mpR-ufWIFxOsW-QIfnMmMIIkygVuHFXmg2tFpzTNNG5aS29K3dN2nyk0WJrdIq79hZSTqVkkBU25Yu3A46sgjcM86XcIJJ2XUEih_KWEa6T1YrkixGu96pebjVqbO0R6dbDckfPF7FqNnwPHVtb1ACFpEYoOJVIbUCMaARBpWsxYhjJZlEM__XA46l8snFQDkNY3CdN0p1_gF3ckA.JLmq9nmu1h9oUi1S8ZxYjA","claims":{"enableSSHCA":true,"disableRenewal":false,"allowRenewalAfterExpiry":false,"disableSmallstepExtensions":false},"options":{"x509":{},"ssh":{}}} - {"type":"SSHPOP","name":"sshpop","claims":{"enableSSHCA":true}} tls: cipherSuites: diff --git a/scep/api/api.go b/scep/api/api.go index 98da818b..bab60302 100644 --- a/scep/api/api.go +++ b/scep/api/api.go @@ -12,12 +12,13 @@ import ( "net/url" "strings" - "github.com/go-chi/chi" - microscep "github.com/micromdm/scep/v2/scep" - "go.mozilla.org/pkcs7" + "github.com/go-chi/chi/v5" + "github.com/smallstep/pkcs7" + smallscep "github.com/smallstep/scep" "github.com/smallstep/certificates/api" "github.com/smallstep/certificates/api/log" + "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/scep" ) @@ -150,11 +151,14 @@ func decodeRequest(r *http.Request) (request, error) { defer r.Body.Close() method := r.Method - query := r.URL.Query() + query, err := url.ParseQuery(r.URL.RawQuery) + if err != nil { + return request{}, fmt.Errorf("failed parsing URL query: %w", err) + } - var operation string - if _, ok := query["operation"]; ok { - operation = query.Get("operation") + operation := query.Get("operation") + if operation == "" { + return request{}, errors.New("no operation provided") } switch method { @@ -166,14 +170,10 @@ func decodeRequest(r *http.Request) (request, error) { Message: []byte{}, }, nil case opnPKIOperation: - var message string - if _, ok := query["message"]; ok { - message = query.Get("message") - } - // TODO: verify this; right type of encoding? Needs additional transformations? - decodedMessage, err := base64.StdEncoding.DecodeString(message) + message := query.Get("message") + decodedMessage, err := decodeMessage(message, r) if err != nil { - return request{}, err + return request{}, fmt.Errorf("failed decoding message: %w", err) } return request{ Operation: operation, @@ -185,7 +185,7 @@ func decodeRequest(r *http.Request) (request, error) { case http.MethodPost: body, err := io.ReadAll(io.LimitReader(r.Body, maxPayloadSize)) if err != nil { - return request{}, err + return request{}, fmt.Errorf("failed reading request body: %w", err) } return request{ Operation: operation, @@ -196,6 +196,77 @@ func decodeRequest(r *http.Request) (request, error) { } } +func decodeMessage(message string, r *http.Request) ([]byte, error) { + if message == "" { + return nil, errors.New("message must not be empty") + } + + // decode the message, which should be base64 standard encoded. Any characters that + // were escaped in the original query, were unescaped as part of url.ParseQuery, so + // that doesn't need to be performed here. Return early if successful. + decodedMessage, err := base64.StdEncoding.DecodeString(message) + if err == nil { + return decodedMessage, nil + } + + // only interested in corrupt input errors below this. This type of error is the + // most likely to return, but better safe than sorry. + var cie base64.CorruptInputError + if !errors.As(err, &cie) { + return nil, fmt.Errorf("failed base64 decoding message: %w", err) + } + + // the below code is a workaround for macOS when it sends a GET PKIOperation, which seems to result + // in a query with the '+' and '/' not being percent encoded; only the padding ('=') is encoded. + // When that is unescaped in the code before this, this results in invalid base64. The workaround + // is to obtain the original query, extract the message, apply transformation(s) to make it valid + // base64 and try decoding it again. If it succeeds, the happy path can be followed with the patched + // message. Otherwise we still return an error. + rawQuery, err := parseRawQuery(r.URL.RawQuery) + if err != nil { + return nil, fmt.Errorf("failed to parse raw query: %w", err) + } + + rawMessage := rawQuery.Get("message") + if rawMessage == "" { + return nil, errors.New("no message in raw query") + } + + rawMessage = strings.ReplaceAll(rawMessage, "%3D", "=") // apparently the padding arrives encoded; the others (+, /) not? + decodedMessage, err = base64.StdEncoding.DecodeString(rawMessage) + if err != nil { + return nil, fmt.Errorf("failed base64 decoding raw message: %w", err) + } + + return decodedMessage, nil +} + +// parseRawQuery parses a URL query into url.Values. It skips +// unescaping keys and values. This code is based on url.ParseQuery. +func parseRawQuery(query string) (url.Values, error) { + m := make(url.Values) + err := parseRawQueryWithoutUnescaping(m, query) + return m, err +} + +// parseRawQueryWithoutUnescaping parses the raw query into url.Values, skipping +// unescaping of the parts. This code is based on url.parseQuery. +func parseRawQueryWithoutUnescaping(m url.Values, query string) (err error) { + for query != "" { + var key string + key, query, _ = strings.Cut(query, "&") + if strings.Contains(key, ";") { + return errors.New("invalid semicolon separator in query") + } + if key == "" { + continue + } + key, value, _ := strings.Cut(key, "=") + m[key] = append(m[key], value) + } + return err +} + // lookupProvisioner loads the provisioner associated with the request. // Responds 404 if the provisioner does not exist. func lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { @@ -208,7 +279,7 @@ func lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { } ctx := r.Context() - auth := scep.MustFromContext(ctx) + auth := authority.MustFromContext(ctx) p, err := auth.LoadProvisionerByName(provisionerName) if err != nil { fail(w, err) @@ -221,7 +292,7 @@ func lookupProvisioner(next http.HandlerFunc) http.HandlerFunc { return } - ctx = context.WithValue(ctx, scep.ProvisionerContextKey, scep.Provisioner(prov)) + ctx = scep.NewProvisionerContext(ctx, scep.Provisioner(prov)) next(w, r.WithContext(ctx)) } } @@ -249,7 +320,7 @@ func GetCACert(ctx context.Context) (Response, error) { // create degenerate pkcs7 certificate structure, according to // https://tools.ietf.org/html/rfc8894#section-4.2.1.2, because // not signed or encrypted data has to be returned. - data, err := microscep.DegenerateCertificates(certs) + data, err := smallscep.DegenerateCertificates(certs) if err != nil { return Response{}, err } @@ -274,16 +345,16 @@ func GetCACaps(ctx context.Context) (Response, error) { // PKIOperation performs PKI operations and returns a SCEP response func PKIOperation(ctx context.Context, req request) (Response, error) { - // parse the message using microscep implementation - microMsg, err := microscep.ParsePKIMessage(req.Message) + // parse the message using smallscep implementation + microMsg, err := smallscep.ParsePKIMessage(req.Message) if err != nil { // return the error, because we can't use the msg for creating a CertRep return Response{}, err } - // this is essentially doing the same as microscep.ParsePKIMessage, but + // this is essentially doing the same as smallscep.ParsePKIMessage, but // gives us access to the p7 itself in scep.PKIMessage. Essentially a small - // wrapper for the microscep implementation. + // wrapper for the smallscep implementation. p7, err := pkcs7.Parse(microMsg.Raw) if err != nil { return Response{}, err @@ -313,12 +384,12 @@ func PKIOperation(ctx context.Context, req request) (Response, error) { // even if using the renewal flow as described in the README.md. MicroMDM SCEP client also only does PKCSreq by default, unless // a certificate exists; then it will use RenewalReq. Adding the challenge check here may be a small breaking change for clients. // We'll have to see how it works out. - if msg.MessageType == microscep.PKCSReq || msg.MessageType == microscep.RenewalReq { - if err := auth.ValidateChallenge(ctx, challengePassword, transactionID); err != nil { + if msg.MessageType == smallscep.PKCSReq || msg.MessageType == smallscep.RenewalReq { + if err := auth.ValidateChallenge(ctx, csr, challengePassword, transactionID); err != nil { if errors.Is(err, provisioner.ErrSCEPChallengeInvalid) { - return createFailureResponse(ctx, csr, msg, microscep.BadRequest, err) + return createFailureResponse(ctx, csr, msg, smallscep.BadRequest, err) } - return createFailureResponse(ctx, csr, msg, microscep.BadRequest, errors.New("failed validating challenge password")) + return createFailureResponse(ctx, csr, msg, smallscep.BadRequest, errors.New("failed validating challenge password")) } } @@ -332,7 +403,16 @@ func PKIOperation(ctx context.Context, req request) (Response, error) { certRep, err := auth.SignCSR(ctx, csr, msg) if err != nil { - return createFailureResponse(ctx, csr, msg, microscep.BadRequest, fmt.Errorf("error when signing new certificate: %w", err)) + if notifyErr := auth.NotifyFailure(ctx, csr, transactionID, 0, err.Error()); notifyErr != nil { + // TODO(hs): ignore this error case? It's not critical if the notification fails; but logging it might be good + _ = notifyErr + } + return createFailureResponse(ctx, csr, msg, smallscep.BadRequest, fmt.Errorf("error when signing new certificate: %w", err)) + } + + if notifyErr := auth.NotifySuccess(ctx, csr, certRep.Certificate, transactionID); notifyErr != nil { + // TODO(hs): ignore this error case? It's not critical if the notification fails; but logging it might be good + _ = notifyErr } res := Response{ @@ -368,7 +448,7 @@ func fail(w http.ResponseWriter, err error) { http.Error(w, err.Error(), http.StatusInternalServerError) } -func createFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *scep.PKIMessage, info microscep.FailInfo, failError error) (Response, error) { +func createFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *scep.PKIMessage, info smallscep.FailInfo, failError error) (Response, error) { auth := scep.MustFromContext(ctx) certRepMsg, err := auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error()) if err != nil { diff --git a/scep/api/api_test.go b/scep/api/api_test.go index bdb51594..a1782933 100644 --- a/scep/api/api_test.go +++ b/scep/api/api_test.go @@ -3,15 +3,27 @@ package api import ( "bytes" + "encoding/base64" "errors" + "fmt" "net/http" "net/http/httptest" - "reflect" + "net/url" + "strings" "testing" "testing/iotest" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_decodeRequest(t *testing.T) { + randomB64 := "wx/1mQ49TpdLRfvVjQhXNSe8RB3hjZEarqYp5XVIxpSbvOhQSs8hP2TgucID1IputbA8JC6CbsUpcVae3+8hRNqs5pTsSHP2aNxsw8AHGSX9dZVymSclkUV8irk+ztfEfs7aLA==" + expectedRandom, err := base64.StdEncoding.DecodeString(randomB64) + require.NoError(t, err) + weirdMacOSCase := "wx/1mQ49TpdLRfvVjQhXNSe8RB3hjZEarqYp5XVIxpSbvOhQSs8hP2TgucID1IputbA8JC6CbsUpcVae3+8hRNqs5pTsSHP2aNxsw8AHGSX9dZVymSclkUV8irk+ztfEfs7aLA%3D%3D" + expectedWeirdMacOSCase, err := base64.StdEncoding.DecodeString(strings.ReplaceAll(weirdMacOSCase, "%3D", "=")) + require.NoError(t, err) type args struct { r *http.Request } @@ -21,10 +33,26 @@ func Test_decodeRequest(t *testing.T) { want request wantErr bool }{ + { + name: "fail/invalid-query", + args: args{ + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=bla;message=invalid-separator", http.NoBody), + }, + want: request{}, + wantErr: true, + }, + { + name: "fail/empty-operation", + args: args{ + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=", http.NoBody), + }, + want: request{}, + wantErr: true, + }, { name: "fail/unsupported-method", args: args{ - r: httptest.NewRequest(http.MethodPatch, "http://scep:8080/?operation=AnUnsupportOperation", nil), + r: httptest.NewRequest(http.MethodPatch, "http://scep:8080/?operation=AnUnsupportOperation", http.NoBody), }, want: request{}, wantErr: true, @@ -32,7 +60,15 @@ func Test_decodeRequest(t *testing.T) { { name: "fail/get-unsupported-operation", args: args{ - r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=AnUnsupportOperation", nil), + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=AnUnsupportOperation", http.NoBody), + }, + want: request{}, + wantErr: true, + }, + { + name: "fail/get-PKIOperation-empty-message", + args: args{ + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=PKIOperation&message=", http.NoBody), }, want: request{}, wantErr: true, @@ -40,7 +76,7 @@ func Test_decodeRequest(t *testing.T) { { name: "fail/get-PKIOperation", args: args{ - r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=PKIOperation&message='somewronginput'", nil), + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=PKIOperation&message='somewronginput'", http.NoBody), }, want: request{}, wantErr: true, @@ -56,7 +92,7 @@ func Test_decodeRequest(t *testing.T) { { name: "ok/get-GetCACert", args: args{ - r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=GetCACert", nil), + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=GetCACert", http.NoBody), }, want: request{ Operation: "GetCACert", @@ -67,7 +103,7 @@ func Test_decodeRequest(t *testing.T) { { name: "ok/get-GetCACaps", args: args{ - r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=GetCACaps", nil), + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=GetCACaps", http.NoBody), }, want: request{ Operation: "GetCACaps", @@ -78,7 +114,7 @@ func Test_decodeRequest(t *testing.T) { { name: "ok/get-PKIOperation", args: args{ - r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=PKIOperation&message=MTIzNA==", nil), + r: httptest.NewRequest(http.MethodGet, "http://scep:8080/?operation=PKIOperation&message=MTIzNA==", http.NoBody), }, want: request{ Operation: "PKIOperation", @@ -86,6 +122,39 @@ func Test_decodeRequest(t *testing.T) { }, wantErr: false, }, + { + name: "ok/get-PKIOperation-escaped", + args: args{ + r: httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://scep:8080/?operation=PKIOperation&message=%s", url.QueryEscape(randomB64)), http.NoBody), + }, + want: request{ + Operation: "PKIOperation", + Message: expectedRandom, + }, + wantErr: false, + }, + { + name: "ok/get-PKIOperation-not-escaped", // bit of a special case, but this is supported because of the macOS case now + args: args{ + r: httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://scep:8080/?operation=PKIOperation&message=%s", randomB64), http.NoBody), + }, + want: request{ + Operation: "PKIOperation", + Message: expectedRandom, + }, + wantErr: false, + }, + { + name: "ok/get-PKIOperation-weird-macos-case", // a special case for macOS, which seems to result in the message not arriving fully percent-encoded + args: args{ + r: httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://scep:8080/?operation=PKIOperation&message=%s", weirdMacOSCase), http.NoBody), + }, + want: request{ + Operation: "PKIOperation", + Message: expectedWeirdMacOSCase, + }, + wantErr: false, + }, { name: "ok/post-PKIOperation", args: args{ @@ -101,13 +170,14 @@ func Test_decodeRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := decodeRequest(tt.args.r) - if (err != nil) != tt.wantErr { - t.Errorf("decodeRequest() error = %v, wantErr %v", err, tt.wantErr) + if tt.wantErr { + assert.Error(t, err) + assert.Equal(t, tt.want, got) return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("decodeRequest() = %v, want %v", got, tt.want) - } + + assert.NoError(t, err) + assert.Equal(t, tt.want, got) }) } } diff --git a/scep/authority.go b/scep/authority.go index 23c28813..85faba07 100644 --- a/scep/authority.go +++ b/scep/authority.go @@ -2,14 +2,15 @@ package scep import ( "context" + "crypto" "crypto/x509" "errors" "fmt" - "net/url" + "sync" - microx509util "github.com/micromdm/scep/v2/cryptoutil/x509util" - microscep "github.com/micromdm/scep/v2/scep" - "go.mozilla.org/pkcs7" + "github.com/smallstep/pkcs7" + smallscep "github.com/smallstep/scep" + smallscepx509util "github.com/smallstep/scep/x509util" "go.step.sm/crypto/x509util" @@ -18,12 +19,17 @@ import ( // Authority is the layer that handles all SCEP interactions. type Authority struct { - prefix string - dns string - intermediateCertificate *x509.Certificate - caCerts []*x509.Certificate // TODO(hs): change to use these instead of root and intermediate - service *Service - signAuth SignAuthority + signAuth SignAuthority + roots []*x509.Certificate + intermediates []*x509.Certificate + defaultSigner crypto.Signer + signerCertificate *x509.Certificate + defaultDecrypter crypto.Decrypter + decrypterCertificate *x509.Certificate + scepProvisionerNames []string + + provisionersMutex sync.RWMutex + encryptionAlgorithmMutex sync.Mutex } type authorityKey struct{} @@ -49,19 +55,6 @@ func MustFromContext(ctx context.Context) *Authority { } } -// AuthorityOptions required to create a new SCEP Authority. -type AuthorityOptions struct { - // Service provides the certificate chain, the signer and the decrypter to the Authority - Service *Service - // DNS is the host used to generate accurate SCEP links. By default the authority - // will use the Host from the request, so this value will only be used if - // request.Host is empty. - DNS string - // Prefix is a URL path prefix under which the SCEP api is served. This - // prefix is required to generate accurate SCEP links. - Prefix string -} - // SignAuthority is the interface for a signing authority type SignAuthority interface { Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) @@ -69,24 +62,67 @@ type SignAuthority interface { } // New returns a new Authority that implements the SCEP interface. -func New(signAuth SignAuthority, ops AuthorityOptions) (*Authority, error) { - authority := &Authority{ - prefix: ops.Prefix, - dns: ops.DNS, - signAuth: signAuth, +func New(signAuth SignAuthority, opts Options) (*Authority, error) { + if err := opts.Validate(); err != nil { + return nil, err + } + + return &Authority{ + signAuth: signAuth, // TODO: provide signAuth through context instead? + roots: opts.Roots, + intermediates: opts.Intermediates, + defaultSigner: opts.Signer, + signerCertificate: opts.SignerCert, + defaultDecrypter: opts.Decrypter, + decrypterCertificate: opts.SignerCert, // the intermediate signer cert is also the decrypter cert (if RSA) + scepProvisionerNames: opts.SCEPProvisionerNames, + }, nil +} + +// Validate validates if the SCEP Authority has a valid configuration. +// The validation includes a check if a decrypter is available, either +// an authority wide decrypter, or a provisioner specific decrypter. +func (a *Authority) Validate() error { + if a == nil { + return nil } - // TODO: this is not really nice to do; the Service should be removed - // in its entirety to make this more interoperable with the rest of - // step-ca, I think. - if ops.Service != nil { - authority.caCerts = ops.Service.certificateChain - // TODO(hs): look into refactoring SCEP into using just caCerts everywhere, if it makes sense for more elaborate SCEP configuration. Keeping it like this for clarity (for now). - authority.intermediateCertificate = ops.Service.certificateChain[0] - authority.service = ops.Service + a.provisionersMutex.RLock() + defer a.provisionersMutex.RUnlock() + + noDefaultDecrypterAvailable := a.defaultDecrypter == nil + for _, name := range a.scepProvisionerNames { + p, err := a.LoadProvisionerByName(name) + if err != nil { + return fmt.Errorf("failed loading provisioner %q: %w", name, err) + } + if scepProv, ok := p.(*provisioner.SCEP); ok { + cert, decrypter := scepProv.GetDecrypter() + // TODO(hs): return sentinel/typed error, to be able to ignore/log these cases during init? + if cert == nil && noDefaultDecrypterAvailable { + return fmt.Errorf("SCEP provisioner %q does not have a decrypter certificate", name) + } + if decrypter == nil && noDefaultDecrypterAvailable { + return fmt.Errorf("SCEP provisioner %q does not have decrypter", name) + } + } } - return authority, nil + return nil +} + +// UpdateProvisioners updates the SCEP Authority with the new, and hopefully +// current SCEP provisioners configured. This allows the Authority to be +// validated with the latest data. +func (a *Authority) UpdateProvisioners(scepProvisionerNames []string) { + if a == nil { + return + } + + a.provisionersMutex.Lock() + defer a.provisionersMutex.Unlock() + + a.scepProvisionerNames = scepProvisionerNames } var ( @@ -108,87 +144,58 @@ func (a *Authority) LoadProvisionerByName(name string) (provisioner.Interface, e return a.signAuth.LoadProvisionerByName(name) } -// GetLinkExplicit returns the requested link from the directory. -func (a *Authority) GetLinkExplicit(provName string, abs bool, baseURL *url.URL, inputs ...string) string { - return a.getLinkExplicit(provName, abs, baseURL, inputs...) -} - -// getLinkExplicit returns an absolute or partial path to the given resource and a base -// URL dynamically obtained from the request for which the link is being calculated. -func (a *Authority) getLinkExplicit(provisionerName string, abs bool, baseURL *url.URL, _ ...string) string { - link := "/" + provisionerName - if abs { - // Copy the baseURL value from the pointer. https://github.com/golang/go/issues/38351 - u := url.URL{} - if baseURL != nil { - u = *baseURL - } - - // If no Scheme is set, then default to http (in case of SCEP) - if u.Scheme == "" { - u.Scheme = "http" - } - - // If no Host is set, then use the default (first DNS attr in the ca.json). - if u.Host == "" { - u.Host = a.dns - } - - u.Path = a.prefix + link - return u.String() - } - - return link -} - -// GetCACertificates returns the certificate (chain) for the CA -func (a *Authority) GetCACertificates(ctx context.Context) ([]*x509.Certificate, error) { - // TODO: this should return: the "SCEP Server (RA)" certificate, the issuing CA up to and excl. the root - // Some clients do need the root certificate however; also see: https://github.com/openxpki/openxpki/issues/73 - // - // This means we might need to think about if we should use the current intermediate CA - // certificate as the "SCEP Server (RA)" certificate. It might be better to have a distinct - // RA certificate, with a corresponding rsa.PrivateKey, just for SCEP usage, which is signed by - // the intermediate CA. Will need to look how we can provide this nicely within step-ca. - // - // This might also mean that we might want to use a distinct instance of KMS for doing the key operations, - // so that we can use RSA just for SCEP. - // - // Using an RA does not seem to exist in https://tools.ietf.org/html/rfc8894, but is mentioned in - // https://tools.ietf.org/id/draft-nourse-scep-21.html. Will continue using the CA directly for now. - // - // The certificate to use should probably depend on the (configured) provisioner and may - // use a distinct certificate, apart from the intermediate. - - p, err := provisionerFromContext(ctx) - if err != nil { - return nil, err - } - - if len(a.caCerts) == 0 { - return nil, errors.New("no intermediate certificate available in SCEP authority") - } - - certs := []*x509.Certificate{} - certs = append(certs, a.caCerts[0]) - - // NOTE: we're adding the CA roots here, but they are (highly likely) different than what the RFC means. - // Clients are responsible to select the right cert(s) to use, though. - if p.ShouldIncludeRootInChain() && len(a.caCerts) > 1 { - certs = append(certs, a.caCerts[1]) +// GetCACertificates returns the certificate (chain) for the CA. +// +// This methods returns the "SCEP Server (RA)" certificate, the issuing CA up to and excl. the root. +// Some clients do need the root certificate however; also see: https://github.com/openxpki/openxpki/issues/73 +// +// In case a provisioner specific decrypter is available, this is used as the "SCEP Server (RA)" certificate +// instead of the CA intermediate directly. This uses a distinct instance of a KMS for doing the SCEP key +// operations, so that RSA can be used for just SCEP. +// +// Using an RA does not seem to exist in https://tools.ietf.org/html/rfc8894, but is mentioned in +// https://tools.ietf.org/id/draft-nourse-scep-21.html. +func (a *Authority) GetCACertificates(ctx context.Context) (certs []*x509.Certificate, err error) { + p := provisionerFromContext(ctx) + + // if a provisioner specific RSA decrypter is available, it is returned as + // the first certificate. + if decrypterCertificate, _ := p.GetDecrypter(); decrypterCertificate != nil { + certs = append(certs, decrypterCertificate) + } + + // the CA intermediate is added to the chain by default. It's possible to + // exclude it from being added through configuration. This can be useful in + // environments where the SCEP client doesn't select the right RSA decrypter + // certificate, resulting in the wrong recipient in the PKCS7 message. + if p.ShouldIncludeIntermediateInChain() || len(certs) == 0 { + // TODO(hs): ensure logic is in place that checks the signer is the first + // intermediate and that there are no double certificates. + certs = append(certs, a.intermediates...) + } + + // the CA roots are added for completeness when configured to do so. Clients + // are responsible to select the right cert(s) to store and use. + if p.ShouldIncludeRootInChain() { + certs = append(certs, a.roots...) } return certs, nil } // DecryptPKIEnvelope decrypts an enveloped message -func (a *Authority) DecryptPKIEnvelope(_ context.Context, msg *PKIMessage) error { +func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error { p7c, err := pkcs7.Parse(msg.P7.Content) if err != nil { return fmt.Errorf("error parsing pkcs7 content: %w", err) } - envelope, err := p7c.Decrypt(a.intermediateCertificate, a.service.decrypter) + cert, decrypter, err := a.selectDecrypter(ctx) + if err != nil { + return fmt.Errorf("failed selecting decrypter: %w", err) + } + + envelope, err := p7c.Decrypt(cert, decrypter) if err != nil { return fmt.Errorf("error decrypting encrypted pkcs7 content: %w", err) } @@ -196,30 +203,33 @@ func (a *Authority) DecryptPKIEnvelope(_ context.Context, msg *PKIMessage) error msg.pkiEnvelope = envelope switch msg.MessageType { - case microscep.CertRep: - certs, err := microscep.CACerts(msg.pkiEnvelope) + case smallscep.CertRep: + certs, err := smallscep.CACerts(msg.pkiEnvelope) if err != nil { return fmt.Errorf("error extracting CA certs from pkcs7 degenerate data: %w", err) } msg.CertRepMessage.Certificate = certs[0] return nil - case microscep.PKCSReq, microscep.UpdateReq, microscep.RenewalReq: + case smallscep.PKCSReq, smallscep.UpdateReq, smallscep.RenewalReq: csr, err := x509.ParseCertificateRequest(msg.pkiEnvelope) if err != nil { return fmt.Errorf("parse CSR from pkiEnvelope: %w", err) } - // check for challengePassword - cp, err := microx509util.ParseChallengePassword(msg.pkiEnvelope) + if err := csr.CheckSignature(); err != nil { + return fmt.Errorf("invalid CSR signature; %w", err) + } + // extract the challenge password + cp, err := smallscepx509util.ParseChallengePassword(msg.pkiEnvelope) if err != nil { return fmt.Errorf("parse challenge password in pkiEnvelope: %w", err) } - msg.CSRReqMessage = µscep.CSRReqMessage{ + msg.CSRReqMessage = &smallscep.CSRReqMessage{ RawDecrypted: msg.pkiEnvelope, CSR: csr, ChallengePassword: cp, } return nil - case microscep.GetCRL, microscep.GetCert, microscep.CertPoll: + case smallscep.GetCRL, smallscep.GetCert, smallscep.CertPoll: return errors.New("not implemented") } @@ -234,10 +244,7 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m // poll for the status. It seems to be similar as what can happen in ACME, so might want to model // the implementation after the one in the ACME authority. Requires storage, etc. - p, err := provisionerFromContext(ctx) - if err != nil { - return nil, err - } + p := provisionerFromContext(ctx) // check if CSRReqMessage has already been decrypted if msg.CSRReqMessage.CSR == nil { @@ -305,22 +312,15 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m cert := certChain[0] // and create a degenerate cert structure - deg, err := microscep.DegenerateCertificates([]*x509.Certificate{cert}) + deg, err := smallscep.DegenerateCertificates([]*x509.Certificate{cert}) if err != nil { - return nil, err + return nil, fmt.Errorf("failed generating degenerate certificate: %w", err) } - // apparently the pkcs7 library uses a global default setting for the content encryption - // algorithm to use when en- or decrypting data. We need to restore the current setting after - // the cryptographic operation, so that other usages of the library are not influenced by - // this call to Encrypt(). We are not required to use the same algorithm the SCEP client uses. - encryptionAlgorithmToRestore := pkcs7.ContentEncryptionAlgorithm - pkcs7.ContentEncryptionAlgorithm = p.GetContentEncryptionAlgorithm() - e7, err := pkcs7.Encrypt(deg, msg.P7.Certificates) + e7, err := a.encrypt(deg, msg.P7.Certificates, p.GetContentEncryptionAlgorithm()) if err != nil { - return nil, err + return nil, fmt.Errorf("failed encrypting degenerate certificate: %w", err) } - pkcs7.ContentEncryptionAlgorithm = encryptionAlgorithmToRestore // PKIMessageAttributes to be signed config := pkcs7.SignerInfoConfig{ @@ -331,11 +331,11 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m }, { Type: oidSCEPpkiStatus, - Value: microscep.SUCCESS, + Value: smallscep.SUCCESS, }, { Type: oidSCEPmessageType, - Value: microscep.CertRep, + Value: smallscep.CertRep, }, { Type: oidSCEPrecipientNonce, @@ -358,10 +358,13 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m // as the first certificate in the array signedData.AddCertificate(cert) - authCert := a.intermediateCertificate + signerCert, signer, err := a.selectSigner(ctx) + if err != nil { + return nil, fmt.Errorf("failed selecting signer: %w", err) + } // sign the attributes - if err := signedData.AddSigner(authCert, a.service.signer, config); err != nil { + if err := signedData.AddSigner(signerCert, signer, config); err != nil { return nil, err } @@ -371,8 +374,8 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m } cr := &CertRepMessage{ - PKIStatus: microscep.SUCCESS, - RecipientNonce: microscep.RecipientNonce(msg.SenderNonce), + PKIStatus: smallscep.SUCCESS, + RecipientNonce: smallscep.RecipientNonce(msg.SenderNonce), Certificate: cert, degenerate: deg, } @@ -381,15 +384,37 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m crepMsg := &PKIMessage{ Raw: certRepBytes, TransactionID: msg.TransactionID, - MessageType: microscep.CertRep, + MessageType: smallscep.CertRep, CertRepMessage: cr, } return crepMsg, nil } +func (a *Authority) encrypt(content []byte, recipients []*x509.Certificate, algorithm int) ([]byte, error) { + // apparently the pkcs7 library uses a global default setting for the content encryption + // algorithm to use when en- or decrypting data. We need to restore the current setting after + // the cryptographic operation, so that other usages of the library are not influenced by + // this call to Encrypt(). We are not required to use the same algorithm the SCEP client uses. + a.encryptionAlgorithmMutex.Lock() + defer a.encryptionAlgorithmMutex.Unlock() + + encryptionAlgorithmToRestore := pkcs7.ContentEncryptionAlgorithm + defer func() { + pkcs7.ContentEncryptionAlgorithm = encryptionAlgorithmToRestore + }() + + pkcs7.ContentEncryptionAlgorithm = algorithm + e7, err := pkcs7.Encrypt(content, recipients) + if err != nil { + return nil, err + } + + return e7, nil +} + // CreateFailureResponse creates an appropriately signed reply for PKI operations -func (a *Authority) CreateFailureResponse(_ context.Context, _ *x509.CertificateRequest, msg *PKIMessage, info FailInfoName, infoText string) (*PKIMessage, error) { +func (a *Authority) CreateFailureResponse(ctx context.Context, _ *x509.CertificateRequest, msg *PKIMessage, info FailInfoName, infoText string) (*PKIMessage, error) { config := pkcs7.SignerInfoConfig{ ExtraSignedAttributes: []pkcs7.Attribute{ { @@ -398,7 +423,7 @@ func (a *Authority) CreateFailureResponse(_ context.Context, _ *x509.Certificate }, { Type: oidSCEPpkiStatus, - Value: microscep.FAILURE, + Value: smallscep.FAILURE, }, { Type: oidSCEPfailInfo, @@ -410,7 +435,7 @@ func (a *Authority) CreateFailureResponse(_ context.Context, _ *x509.Certificate }, { Type: oidSCEPmessageType, - Value: microscep.CertRep, + Value: smallscep.CertRep, }, { Type: oidSCEPsenderNonce, @@ -428,8 +453,13 @@ func (a *Authority) CreateFailureResponse(_ context.Context, _ *x509.Certificate return nil, err } + signerCert, signer, err := a.selectSigner(ctx) + if err != nil { + return nil, fmt.Errorf("failed selecting signer: %w", err) + } + // sign the attributes - if err := signedData.AddSigner(a.intermediateCertificate, a.service.signer, config); err != nil { + if err := signedData.AddSigner(signerCert, signer, config); err != nil { return nil, err } @@ -439,16 +469,16 @@ func (a *Authority) CreateFailureResponse(_ context.Context, _ *x509.Certificate } cr := &CertRepMessage{ - PKIStatus: microscep.FAILURE, - FailInfo: microscep.FailInfo(info), - RecipientNonce: microscep.RecipientNonce(msg.SenderNonce), + PKIStatus: smallscep.FAILURE, + FailInfo: smallscep.FailInfo(info), + RecipientNonce: smallscep.RecipientNonce(msg.SenderNonce), } // create a CertRep message from the original crepMsg := &PKIMessage{ Raw: certRepBytes, TransactionID: msg.TransactionID, - MessageType: microscep.CertRep, + MessageType: smallscep.CertRep, CertRepMessage: cr, } @@ -457,10 +487,7 @@ func (a *Authority) CreateFailureResponse(_ context.Context, _ *x509.Certificate // GetCACaps returns the CA capabilities func (a *Authority) GetCACaps(ctx context.Context) []string { - p, err := provisionerFromContext(ctx) - if err != nil { - return defaultCapabilities - } + p := provisionerFromContext(ctx) caps := p.GetCapabilities() if len(caps) == 0 { @@ -476,10 +503,63 @@ func (a *Authority) GetCACaps(ctx context.Context) []string { return caps } -func (a *Authority) ValidateChallenge(ctx context.Context, challenge, transactionID string) error { - p, err := provisionerFromContext(ctx) - if err != nil { - return err +func (a *Authority) ValidateChallenge(ctx context.Context, csr *x509.CertificateRequest, challenge, transactionID string) error { + p := provisionerFromContext(ctx) + return p.ValidateChallenge(ctx, csr, challenge, transactionID) +} + +func (a *Authority) NotifySuccess(ctx context.Context, csr *x509.CertificateRequest, cert *x509.Certificate, transactionID string) error { + p := provisionerFromContext(ctx) + return p.NotifySuccess(ctx, csr, cert, transactionID) +} + +func (a *Authority) NotifyFailure(ctx context.Context, csr *x509.CertificateRequest, transactionID string, errorCode int, errorDescription string) error { + p := provisionerFromContext(ctx) + return p.NotifyFailure(ctx, csr, transactionID, errorCode, errorDescription) +} + +func (a *Authority) selectDecrypter(ctx context.Context) (cert *x509.Certificate, decrypter crypto.Decrypter, err error) { + p := provisionerFromContext(ctx) + cert, decrypter = p.GetDecrypter() + switch { + case cert != nil && decrypter != nil: + return + case cert == nil && decrypter != nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a decrypter certificate available", p.GetName()) + case cert != nil && decrypter == nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a decrypter available", p.GetName()) } - return p.ValidateChallenge(ctx, challenge, transactionID) + + cert, decrypter = a.decrypterCertificate, a.defaultDecrypter + switch { + case cert == nil && decrypter != nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a default decrypter certificate available", p.GetName()) + case cert != nil && decrypter == nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a default decrypter available", p.GetName()) + } + + return +} + +func (a *Authority) selectSigner(ctx context.Context) (cert *x509.Certificate, signer crypto.Signer, err error) { + p := provisionerFromContext(ctx) + cert, signer = p.GetSigner() + switch { + case cert != nil && signer != nil: + return + case cert == nil && signer != nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a signer certificate available", p.GetName()) + case cert != nil && signer == nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a signer available", p.GetName()) + } + + cert, signer = a.signerCertificate, a.defaultSigner + switch { + case cert == nil && signer != nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a default signer certificate available", p.GetName()) + case cert != nil && signer == nil: + return nil, nil, fmt.Errorf("provisioner %q does not have a default signer available", p.GetName()) + } + + return } diff --git a/scep/authority_test.go b/scep/authority_test.go new file mode 100644 index 00000000..e7e786ae --- /dev/null +++ b/scep/authority_test.go @@ -0,0 +1,73 @@ +package scep + +import ( + "crypto/x509" + "crypto/x509/pkix" + "testing" + + "github.com/smallstep/pkcs7" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.step.sm/crypto/keyutil" + "go.step.sm/crypto/minica" + "go.step.sm/crypto/randutil" +) + +func generateContent(t *testing.T, size int) []byte { + t.Helper() + b, err := randutil.Bytes(size) + require.NoError(t, err) + return b +} + +func generateRecipients(t *testing.T) []*x509.Certificate { + ca, err := minica.New() + require.NoError(t, err) + s, err := keyutil.GenerateSigner("RSA", "", 2048) + require.NoError(t, err) + tmpl := &x509.Certificate{ + PublicKey: s.Public(), + Subject: pkix.Name{CommonName: "Test PKCS#7 Encryption"}, + } + cert, err := ca.Sign(tmpl) + require.NoError(t, err) + return []*x509.Certificate{cert} +} + +func TestAuthority_encrypt(t *testing.T) { + t.Parallel() + a := &Authority{} + recipients := generateRecipients(t) + type args struct { + content []byte + recipients []*x509.Certificate + algorithm int + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"alg-0", args{generateContent(t, 32), recipients, pkcs7.EncryptionAlgorithmDESCBC}, false}, + {"alg-1", args{generateContent(t, 32), recipients, pkcs7.EncryptionAlgorithmAES128CBC}, false}, + {"alg-2", args{generateContent(t, 32), recipients, pkcs7.EncryptionAlgorithmAES256CBC}, false}, + {"alg-3", args{generateContent(t, 32), recipients, pkcs7.EncryptionAlgorithmAES128GCM}, false}, + {"alg-4", args{generateContent(t, 32), recipients, pkcs7.EncryptionAlgorithmAES256GCM}, false}, + {"alg-unknown", args{generateContent(t, 32), recipients, 42}, true}, + } + for _, tt := range tests { + tc := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got, err := a.encrypt(tc.args.content, tc.args.recipients, tc.args.algorithm) + if tc.wantErr { + assert.Error(t, err) + assert.Nil(t, got) + return + } + + assert.NoError(t, err) + assert.NotEmpty(t, got) + }) + } +} diff --git a/scep/common.go b/scep/common.go deleted file mode 100644 index 73b16ed4..00000000 --- a/scep/common.go +++ /dev/null @@ -1,29 +0,0 @@ -package scep - -import ( - "context" - "errors" -) - -// ContextKey is the key type for storing and searching for SCEP request -// essentials in the context of a request. -type ContextKey string - -const ( - // ProvisionerContextKey provisioner key - ProvisionerContextKey = ContextKey("provisioner") -) - -// provisionerFromContext searches the context for a SCEP provisioner. -// Returns the provisioner or an error. -func provisionerFromContext(ctx context.Context) (Provisioner, error) { - val := ctx.Value(ProvisionerContextKey) - if val == nil { - return nil, errors.New("provisioner expected in request context") - } - p, ok := val.(Provisioner) - if !ok || p == nil { - return nil, errors.New("provisioner in context is not a SCEP provisioner") - } - return p, nil -} diff --git a/scep/database.go b/scep/database.go deleted file mode 100644 index f73573fd..00000000 --- a/scep/database.go +++ /dev/null @@ -1,7 +0,0 @@ -package scep - -import "crypto/x509" - -type DB interface { - StoreCertificate(crt *x509.Certificate) error -} diff --git a/scep/options.go b/scep/options.go index 201f1beb..8bc30a61 100644 --- a/scep/options.go +++ b/scep/options.go @@ -4,65 +4,78 @@ import ( "crypto" "crypto/rsa" "crypto/x509" - - "github.com/pkg/errors" + "errors" ) type Options struct { - // CertificateChain is the issuer certificate, along with any other bundled certificates - // to be returned in the chain for consumers. Configured in the ca.json crt property. - CertificateChain []*x509.Certificate + // Roots contains the (federated) CA roots certificate(s) + Roots []*x509.Certificate `json:"-"` + // Intermediates points issuer certificate, along with any other bundled certificates + // to be returned in the chain for consumers. + Intermediates []*x509.Certificate `json:"-"` + // SignerCert points to the certificate of the CA signer. It usually is the same as the + // first certificate in the CertificateChain. + SignerCert *x509.Certificate `json:"-"` // Signer signs CSRs in SCEP. Configured in the ca.json key property. Signer crypto.Signer `json:"-"` // Decrypter decrypts encrypted SCEP messages. Configured in the ca.json key property. Decrypter crypto.Decrypter `json:"-"` + // DecrypterCert points to the certificate of the CA decrypter. + DecrypterCert *x509.Certificate `json:"-"` + // SCEPProvisionerNames contains the currently configured SCEP provioner names. These + // are used to be able to load the provisioners when the SCEP authority is being + // validated. + SCEPProvisionerNames []string +} + +type comparablePublicKey interface { + Equal(crypto.PublicKey) bool } // Validate checks the fields in Options. func (o *Options) Validate() error { - if o.CertificateChain == nil { - return errors.New("certificate chain not configured correctly") + switch { + case len(o.Intermediates) == 0: + return errors.New("no intermediate certificate available for SCEP authority") + case o.Signer == nil: + return errors.New("no signer available for SCEP authority") + case o.SignerCert == nil: + return errors.New("no signer certificate available for SCEP authority") } - if len(o.CertificateChain) < 1 { - return errors.New("certificate chain should at least have one certificate") + // check if the signer (intermediate CA) certificate has the same public key as + // the signer. According to the RFC it seems valid to have different keys for + // the intermediate and the CA signing new certificates, so this might change + // in the future. + signerPublicKey := o.Signer.Public().(comparablePublicKey) + if !signerPublicKey.Equal(o.SignerCert.PublicKey) { + return errors.New("mismatch between signer certificate and public key") } - // According to the RFC: https://tools.ietf.org/html/rfc8894#section-3.1, SCEP - // can be used with something different than RSA, but requires the encryption - // to be performed using the challenge password. An older version of specification - // states that only RSA is supported: https://tools.ietf.org/html/draft-nourse-scep-23#section-2.1.1 - // Other algorithms than RSA do not seem to be supported in certnanny/sscep, but it might work - // in micromdm/scep. Currently only RSA is allowed, but it might be an option - // to try other algorithms in the future. - intermediate := o.CertificateChain[0] - if intermediate.PublicKeyAlgorithm != x509.RSA { - return errors.New("only the RSA algorithm is (currently) supported") - } - - // TODO: add checks for key usage? - - signerPublicKey, ok := o.Signer.Public().(*rsa.PublicKey) - if !ok { - return errors.New("only RSA public keys are (currently) supported as signers") - } - - // check if the intermediate ca certificate has the same public key as the signer. - // According to the RFC it seems valid to have different keys for the intermediate - // and the CA signing new certificates, so this might change in the future. - if !signerPublicKey.Equal(intermediate.PublicKey) { - return errors.New("mismatch between certificate chain and signer public keys") + // decrypter can be nil in case a signing only key is used; validation complete. + if o.Decrypter == nil { + return nil } + // If a decrypter is available, check that it's backed by an RSA key. According to the + // RFC: https://tools.ietf.org/html/rfc8894#section-3.1, SCEP can be used with something + // different than RSA, but requires the encryption to be performed using the challenge + // password in that case. An older version of specification states that only RSA is + // supported: https://tools.ietf.org/html/draft-nourse-scep-23#section-2.1.1. Other + // algorithms do not seem to be supported in certnanny/sscep, but it might work + // in micromdm/scep. Currently only RSA is allowed, but it might be an option + // to try other algorithms in the future. decrypterPublicKey, ok := o.Decrypter.Public().(*rsa.PublicKey) if !ok { - return errors.New("only RSA public keys are (currently) supported as decrypters") + return errors.New("only RSA keys are (currently) supported as decrypters") } // check if intermediate public key is the same as the decrypter public key. // In certnanny/sscep it's mentioned that the signing key can be different - // from the decrypting (and encrypting) key. Currently that's not supported. - if !decrypterPublicKey.Equal(intermediate.PublicKey) { + // from the decrypting (and encrypting) key. These options are only used and + // validated when the intermediate CA is also used as the decrypter, though, + // so they should match. + if !decrypterPublicKey.Equal(o.SignerCert.PublicKey) { return errors.New("mismatch between certificate chain and decrypter public keys") } diff --git a/scep/provisioner.go b/scep/provisioner.go index 8120057e..3df4b367 100644 --- a/scep/provisioner.go +++ b/scep/provisioner.go @@ -2,20 +2,43 @@ package scep import ( "context" - "time" + "crypto" + "crypto/x509" "github.com/smallstep/certificates/authority/provisioner" ) -// Provisioner is an interface that implements a subset of the provisioner.Interface -- -// only those methods required by the SCEP api/authority. +// Provisioner is an interface that embeds the +// provisioner.Interface and adds some SCEP specific +// functions. type Provisioner interface { - AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error) - GetName() string - DefaultTLSCertDuration() time.Duration + provisioner.Interface GetOptions() *provisioner.Options GetCapabilities() []string ShouldIncludeRootInChain() bool + ShouldIncludeIntermediateInChain() bool + GetDecrypter() (*x509.Certificate, crypto.Decrypter) + GetSigner() (*x509.Certificate, crypto.Signer) GetContentEncryptionAlgorithm() int - ValidateChallenge(ctx context.Context, challenge, transactionID string) error + ValidateChallenge(ctx context.Context, csr *x509.CertificateRequest, challenge, transactionID string) error + NotifySuccess(ctx context.Context, csr *x509.CertificateRequest, cert *x509.Certificate, transactionID string) error + NotifyFailure(ctx context.Context, csr *x509.CertificateRequest, transactionID string, errorCode int, errorDescription string) error +} + +// provisionerKey is the key type for storing and searching a +// SCEP provisioner in the context. +type provisionerKey struct{} + +// provisionerFromContext searches the context for a SCEP provisioner. +// Returns the provisioner or panics if no SCEP provisioner is found. +func provisionerFromContext(ctx context.Context) Provisioner { + p, ok := ctx.Value(provisionerKey{}).(Provisioner) + if !ok { + panic("SCEP provisioner expected in request context") + } + return p +} + +func NewProvisionerContext(ctx context.Context, p Provisioner) context.Context { + return context.WithValue(ctx, provisionerKey{}, p) } diff --git a/scep/scep.go b/scep/scep.go index 372a5436..b89ed0ac 100644 --- a/scep/scep.go +++ b/scep/scep.go @@ -5,12 +5,12 @@ import ( "crypto/x509" "encoding/asn1" - microscep "github.com/micromdm/scep/v2/scep" - "go.mozilla.org/pkcs7" + "github.com/smallstep/pkcs7" + smallscep "github.com/smallstep/scep" ) // FailInfoName models the name/value of failInfo -type FailInfoName microscep.FailInfo +type FailInfoName smallscep.FailInfo // FailInfo models a failInfo object consisting of a // name/identifier and a failInfoText, the latter of @@ -35,10 +35,10 @@ var ( // PKIMessage defines the possible SCEP message types type PKIMessage struct { - microscep.TransactionID - microscep.MessageType - microscep.SenderNonce - *microscep.CSRReqMessage + smallscep.TransactionID + smallscep.MessageType + smallscep.SenderNonce + *smallscep.CSRReqMessage *CertRepMessage @@ -57,9 +57,9 @@ type PKIMessage struct { // CertRepMessage is a type of PKIMessage type CertRepMessage struct { - microscep.PKIStatus - microscep.RecipientNonce - microscep.FailInfo + smallscep.PKIStatus + smallscep.RecipientNonce + smallscep.FailInfo Certificate *x509.Certificate diff --git a/scep/service.go b/scep/service.go deleted file mode 100644 index 85f7c73f..00000000 --- a/scep/service.go +++ /dev/null @@ -1,28 +0,0 @@ -package scep - -import ( - "context" - "crypto" - "crypto/x509" -) - -// Service is a wrapper for crypto.Signer and crypto.Decrypter -type Service struct { - certificateChain []*x509.Certificate - signer crypto.Signer - decrypter crypto.Decrypter -} - -// NewService returns a new Service type. -func NewService(_ context.Context, opts Options) (*Service, error) { - if err := opts.Validate(); err != nil { - return nil, err - } - - // TODO: should this become similar to the New CertificateAuthorityService as in x509CAService? - return &Service{ - certificateChain: opts.CertificateChain, - signer: opts.Signer, - decrypter: opts.Decrypter, - }, nil -} diff --git a/scripts/badger-migration/main.go b/scripts/badger-migration/main.go index 89fb8e7d..3ae37abe 100644 --- a/scripts/badger-migration/main.go +++ b/scripts/badger-migration/main.go @@ -57,7 +57,9 @@ type DB interface { type dryRunDB struct{} -func (*dryRunDB) CreateTable([]byte) error { return nil } +func (*dryRunDB) CreateTable([]byte) error { return nil } + +//nolint:revive // allow unused parameters to show function signature func (*dryRunDB) Set(bucket, key, value []byte) error { return nil } func usage(fs *flag.FlagSet) { diff --git a/webhook/types.go b/webhook/types.go index 9eda0578..5e0e4d29 100644 --- a/webhook/types.go +++ b/webhook/types.go @@ -30,6 +30,7 @@ type X509Certificate struct { PublicKeyAlgorithm string `json:"publicKeyAlgorithm"` NotBefore time.Time `json:"notBefore"` NotAfter time.Time `json:"notAfter"` + Raw []byte `json:"raw"` } // SSHCertificateRequest is the certificate request sent to webhook servers for @@ -69,7 +70,8 @@ type X5CCertificate struct { // RequestBody is the body sent to webhook servers. type RequestBody struct { - Timestamp time.Time `json:"timestamp"` + Timestamp time.Time `json:"timestamp"` + ProvisionerName string `json:"provisionerName,omitempty"` // Only set after successfully completing acme device-attest-01 challenge AttestationData *AttestationData `json:"attestationData,omitempty"` // Set for most provisioners, but not acme or scep @@ -79,9 +81,11 @@ type RequestBody struct { X509Certificate *X509Certificate `json:"x509Certificate,omitempty"` SSHCertificateRequest *SSHCertificateRequest `json:"sshCertificateRequest,omitempty"` SSHCertificate *SSHCertificate `json:"sshCertificate,omitempty"` - // Only set for SCEP challenge validation requests - SCEPChallenge string `json:"scepChallenge,omitempty"` - SCEPTransactionID string `json:"scepTransactionID,omitempty"` + // Only set for SCEP webhook requests + SCEPChallenge string `json:"scepChallenge,omitempty"` + SCEPTransactionID string `json:"scepTransactionID,omitempty"` + SCEPErrorCode int `json:"scepErrorCode,omitempty"` + SCEPErrorDescription string `json:"scepErrorDescription,omitempty"` // Only set for X5C provisioners X5CCertificate *X5CCertificate `json:"x5cCertificate,omitempty"` // Set for X5C, AWS, GCP, and Azure provisioners