diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 00000000..471eedab --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,22 @@ +name: Dependabot auto-merge +on: pull_request + +permissions: + contents: write + pull-requests: write + +jobs: + dependabot: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1.1.1 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + - name: Enable auto-merge for Dependabot PRs + run: gh pr merge --auto --merge "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f66ad67b..c98837a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,10 +17,12 @@ jobs: runs-on: ubuntu-latest env: DOCKER_IMAGE: smallstep/step-ca + DOCKER_IMAGE_HSM: smallstep/step-ca-hsm outputs: version: ${{ steps.extract-tag.outputs.VERSION }} is_prerelease: ${{ steps.is_prerelease.outputs.IS_PRERELEASE }} docker_tags: ${{ env.DOCKER_TAGS }} + docker_tags_hsm: ${{ env.DOCKER_TAGS_HSM }} steps: - name: Is Pre-release id: is_prerelease @@ -36,10 +38,12 @@ jobs: 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_HSM }}:${VERSION}" >> ${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 }}:latest" >> ${GITHUB_ENV} - name: Create Release id: create_release uses: actions/create-release@v1 @@ -96,5 +100,19 @@ jobs: platforms: linux/amd64,linux/386,linux/arm,linux/arm64 tags: ${{ needs.create_release.outputs.docker_tags }} docker_image: smallstep/step-ca - docker_file: docker/Dockerfile.step-ca + docker_file: docker/Dockerfile + secrets: inherit + + build_upload_docker_hsm: + name: Build & Upload HSM Enabled Docker Images + needs: create_release + permissions: + id-token: write + contents: write + uses: smallstep/workflows/.github/workflows/docker-buildx-push.yml@main + with: + platforms: linux/amd64,linux/386,linux/arm,linux/arm64 + tags: ${{ needs.create_release.outputs.docker_tags_hsm }} + docker_image: smallstep/step-ca-hsm + docker_file: docker/Dockerfile.hsm secrets: inherit diff --git a/.goreleaser.yml b/.goreleaser.yml index 9b5398a9..e8f0a9b3 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -140,7 +140,7 @@ release: #### Windows - - 📦 [step-ca_windows_{{ .Version }}_arm64.zip](https://dl.step.sm/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) + - 📦 [step-ca_windows_{{ .Version }}_amd64.zip](https://dl.step.sm/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip) For more builds across platforms and architectures, see the `Assets` section below. And for packaged versions (Docker, k8s, Homebrew), see our [installation docs](https://smallstep.com/docs/step-ca/installation). @@ -185,3 +185,40 @@ release: # - glob: ./path/to/file.txt # - glob: ./glob/**/to/**/file/**/* # - glob: ./glob/foo/to/bar/file/foobar/override_from_previous + +scoop: + # Template for the url which is determined by the given Token (github or gitlab) + # Default for github is "https://github.com///releases/download/{{ .Tag }}/{{ .ArtifactName }}" + # Default for gitlab is "https://gitlab.com///uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}" + # 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: + owner: smallstep + name: scoop-bucket + + # Git author used to commit to the repository. + # Defaults are shown. + commit_author: + name: goreleaserbot + email: goreleaser@smallstep.com + + # The project name and current git tag are used in the format string. + commit_msg_template: "Scoop update for {{ .ProjectName }} version {{ .Tag }}" + + # Your app's homepage. + # Default is empty. + homepage: "https://smallstep.com/docs/step-ca" + + # Skip uploads for prerelease. + skip_upload: auto + + # Your app's description. + # Default is empty. + description: "A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management, so you can use TLS everywhere & SSO for SSH." + + # Your app's license + # Default is empty. + license: "Apache-2.0" + diff --git a/CHANGELOG.md b/CHANGELOG.md index 730c2066..657bc2fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,40 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] -## [v0.23.1] - 2022-01-10 +### Fixed + +- Fixed support for PKCS #7 RSA-OAEP decryption through + [smallstep/pkcs7#4](https://github.com/smallstep/pkcs7/pull/4), as used in SCEP. + +## [v0.23.2] - 2023-02-02 + +### Added + +- Added [`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin) to + docker images, and a new image, `smallstep/step-ca-hsm`, compiled with cgo + (smallstep/certificates#1243). +- Added [`scoop`](https://scoop.sh) packages back to the release + (smallstep/certificates#1250). +- Added optional flag `--pidfile` which allows passing a filename where step-ca + will write its process id (smallstep/certificates#1251). +- Added helpful message on CA startup when config can't be opened + (smallstep/certificates#1252). +- Improved validation and error messages on `device-attest-01` orders + (smallstep/certificates#1235). + +### Removed + +- The deprecated CLI utils `step-awskms-init`, `step-cloudkms-init`, + `step-pkcs11-init`, `step-yubikey-init` have been removed. + [`step`](https://github.com/smallstep/cli) and + [`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin) should be + used instead (smallstep/certificates#1240). + +### Fixed + +- Fixed remote management flags in docker images (smallstep/certificates#1228). + +## [v0.23.1] - 2023-01-10 ### Added diff --git a/Makefile b/Makefile index 90e96993..6665b0cc 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,5 @@ PKG?=github.com/smallstep/certificates/cmd/step-ca BINNAME?=step-ca -CLOUDKMS_BINNAME?=step-cloudkms-init -CLOUDKMS_PKG?=github.com/smallstep/certificates/cmd/step-cloudkms-init -AWSKMS_BINNAME?=step-awskms-init -AWSKMS_PKG?=github.com/smallstep/certificates/cmd/step-awskms-init -YUBIKEY_BINNAME?=step-yubikey-init -YUBIKEY_PKG?=github.com/smallstep/certificates/cmd/step-yubikey-init -PKCS11_BINNAME?=step-pkcs11-init -PKCS11_PKG?=github.com/smallstep/certificates/cmd/step-pkcs11-init # Set V to 1 for verbose output from the Makefile Q=$(if $V,,@) @@ -90,29 +82,13 @@ GOFLAGS := CGO_ENABLED=0 download: $Q go mod download -build: $(PREFIX)bin/$(BINNAME) $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(PREFIX)bin/$(AWSKMS_BINNAME) $(PREFIX)bin/$(YUBIKEY_BINNAME) $(PREFIX)bin/$(PKCS11_BINNAME) +build: $(PREFIX)bin/$(BINNAME) @echo "Build Complete!" $(PREFIX)bin/$(BINNAME): download $(call rwildcard,*.go) $Q mkdir -p $(@D) $Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(BINNAME) $(LDFLAGS) $(PKG) -$(PREFIX)bin/$(CLOUDKMS_BINNAME): download $(call rwildcard,*.go) - $Q mkdir -p $(@D) - $Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(LDFLAGS) $(CLOUDKMS_PKG) - -$(PREFIX)bin/$(AWSKMS_BINNAME): download $(call rwildcard,*.go) - $Q mkdir -p $(@D) - $Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(AWSKMS_BINNAME) $(LDFLAGS) $(AWSKMS_PKG) - -$(PREFIX)bin/$(YUBIKEY_BINNAME): download $(call rwildcard,*.go) - $Q mkdir -p $(@D) - $Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(YUBIKEY_BINNAME) $(LDFLAGS) $(YUBIKEY_PKG) - -$(PREFIX)bin/$(PKCS11_BINNAME): download $(call rwildcard,*.go) - $Q mkdir -p $(@D) - $Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(PKCS11_BINNAME) $(LDFLAGS) $(PKCS11_PKG) - # Target to force a build of step-ca without running tests simple: build @@ -133,7 +109,6 @@ generate: test: $Q $(GOFLAGS) gotestsum -- -coverprofile=coverage.out -short -covermode=atomic ./... - testcgo: $Q gotestsum -- -coverprofile=coverage.out -short -covermode=atomic ./... @@ -166,15 +141,11 @@ lint: INSTALL_PREFIX?=/usr/ -install: $(PREFIX)bin/$(BINNAME) $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(PREFIX)bin/$(AWSKMS_BINNAME) +install: $(PREFIX)bin/$(BINNAME) $Q install -D $(PREFIX)bin/$(BINNAME) $(DESTDIR)$(INSTALL_PREFIX)bin/$(BINNAME) - $Q install -D $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(DESTDIR)$(INSTALL_PREFIX)bin/$(CLOUDKMS_BINNAME) - $Q install -D $(PREFIX)bin/$(AWSKMS_BINNAME) $(DESTDIR)$(INSTALL_PREFIX)bin/$(AWSKMS_BINNAME) uninstall: $Q rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BINNAME) - $Q rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/$(CLOUDKMS_BINNAME) - $Q rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/$(AWSKMS_BINNAME) .PHONY: install uninstall @@ -186,18 +157,6 @@ clean: ifneq ($(BINNAME),"") $Q rm -f bin/$(BINNAME) endif -ifneq ($(CLOUDKMS_BINNAME),"") - $Q rm -f bin/$(CLOUDKMS_BINNAME) -endif -ifneq ($(AWSKMS_BINNAME),"") - $Q rm -f bin/$(AWSKMS_BINNAME) -endif -ifneq ($(YUBIKEY_BINNAME),"") - $Q rm -f bin/$(YUBIKEY_BINNAME) -endif -ifneq ($(PKCS11_BINNAME),"") - $Q rm -f bin/$(PKCS11_BINNAME) -endif .PHONY: clean diff --git a/acme/account_test.go b/acme/account_test.go index 88718a9a..b8ce7276 100644 --- a/acme/account_test.go +++ b/acme/account_test.go @@ -135,7 +135,6 @@ func TestExternalAccountKey_BindTo(t *testing.T) { if assert.True(t, errors.As(err, &ae)) { assert.Equals(t, ae.Type, tt.err.Type) assert.Equals(t, ae.Detail, tt.err.Detail) - assert.Equals(t, ae.Identifier, tt.err.Identifier) assert.Equals(t, ae.Subproblems, tt.err.Subproblems) } } else { diff --git a/acme/api/account_test.go b/acme/api/account_test.go index 3f8641b8..d46c9eed 100644 --- a/acme/api/account_test.go +++ b/acme/api/account_test.go @@ -388,7 +388,6 @@ func TestHandler_GetOrdersByAccountID(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -828,7 +827,6 @@ func TestHandler_NewAccount(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -1032,7 +1030,6 @@ func TestHandler_GetOrUpdateAccount(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { diff --git a/acme/api/eab_test.go b/acme/api/eab_test.go index c923a2f6..14dbdad1 100644 --- a/acme/api/eab_test.go +++ b/acme/api/eab_test.go @@ -866,7 +866,6 @@ func TestHandler_validateExternalAccountBinding(t *testing.T) { assert.Equals(t, ae.Status, tc.err.Status) assert.HasPrefix(t, ae.Err.Error(), tc.err.Err.Error()) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) } } else { @@ -1145,7 +1144,6 @@ func Test_validateEABJWS(t *testing.T) { assert.Equals(t, tc.err.Status, err.Status) assert.HasPrefix(t, err.Err.Error(), tc.err.Err.Error()) assert.Equals(t, tc.err.Detail, err.Detail) - assert.Equals(t, tc.err.Identifier, err.Identifier) assert.Equals(t, tc.err.Subproblems, err.Subproblems) } else { assert.Nil(t, err) diff --git a/acme/api/handler_test.go b/acme/api/handler_test.go index e814aaba..7ef7cd68 100644 --- a/acme/api/handler_test.go +++ b/acme/api/handler_test.go @@ -193,7 +193,6 @@ func TestHandler_GetDirectory(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -366,7 +365,6 @@ func TestHandler_GetAuthorization(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -509,7 +507,6 @@ func TestHandler_GetCertificate(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.HasPrefix(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -768,7 +765,6 @@ func TestHandler_GetChallenge(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { diff --git a/acme/api/middleware_test.go b/acme/api/middleware_test.go index faff0616..3db3773c 100644 --- a/acme/api/middleware_test.go +++ b/acme/api/middleware_test.go @@ -93,7 +93,6 @@ func TestHandler_addNonce(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -147,7 +146,6 @@ func TestHandler_addDirLink(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -252,7 +250,6 @@ func TestHandler_verifyContentType(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -320,7 +317,6 @@ func TestHandler_isPostAsGet(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -410,7 +406,6 @@ func TestHandler_parseJWS(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -606,7 +601,6 @@ func TestHandler_verifyAndExtractJWSPayload(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -808,7 +802,6 @@ func TestHandler_lookupJWK(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -1008,7 +1001,6 @@ func TestHandler_extractJWK(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -1384,7 +1376,6 @@ func TestHandler_validateJWS(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -1567,7 +1558,6 @@ func TestHandler_extractOrLookupJWK(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -1652,7 +1642,6 @@ func TestHandler_checkPrerequisites(t *testing.T) { assert.FatalError(t, json.Unmarshal(bytes.TrimSpace(body), &ae)) assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { diff --git a/acme/api/order_test.go b/acme/api/order_test.go index b7b58b7f..9f03c547 100644 --- a/acme/api/order_test.go +++ b/acme/api/order_test.go @@ -486,7 +486,6 @@ func TestHandler_GetOrder(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -1846,7 +1845,6 @@ func TestHandler_NewOrder(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -2144,7 +2142,6 @@ func TestHandler_FinalizeOrder(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { diff --git a/acme/api/revoke_test.go b/acme/api/revoke_test.go index 240ac748..c4182400 100644 --- a/acme/api/revoke_test.go +++ b/acme/api/revoke_test.go @@ -1090,7 +1090,6 @@ func TestHandler_RevokeCert(t *testing.T) { assert.Equals(t, ae.Type, tc.err.Type) assert.Equals(t, ae.Detail, tc.err.Detail) - assert.Equals(t, ae.Identifier, tc.err.Identifier) assert.Equals(t, ae.Subproblems, tc.err.Subproblems) assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"}) } else { @@ -1230,7 +1229,6 @@ func TestHandler_isAccountAuthorized(t *testing.T) { assert.Equals(t, acmeErr.Type, tc.err.Type) assert.Equals(t, acmeErr.Status, tc.err.Status) assert.Equals(t, acmeErr.Detail, tc.err.Detail) - assert.Equals(t, acmeErr.Identifier, tc.err.Identifier) assert.Equals(t, acmeErr.Subproblems, tc.err.Subproblems) }) @@ -1323,7 +1321,6 @@ func Test_wrapUnauthorizedError(t *testing.T) { assert.Equals(t, acmeErr.Type, tc.want.Type) assert.Equals(t, acmeErr.Status, tc.want.Status) assert.Equals(t, acmeErr.Detail, tc.want.Detail) - assert.Equals(t, acmeErr.Identifier, tc.want.Identifier) assert.Equals(t, acmeErr.Subproblems, tc.want.Subproblems) }) } diff --git a/acme/authorization.go b/acme/authorization.go index d2df5ea5..cb629073 100644 --- a/acme/authorization.go +++ b/acme/authorization.go @@ -8,15 +8,16 @@ import ( // Authorization representst an ACME Authorization. type Authorization struct { - ID string `json:"-"` - AccountID string `json:"-"` - Token string `json:"-"` - Identifier Identifier `json:"identifier"` - Status Status `json:"status"` - Challenges []*Challenge `json:"challenges"` - Wildcard bool `json:"wildcard"` - ExpiresAt time.Time `json:"expires"` - Error *Error `json:"error,omitempty"` + ID string `json:"-"` + AccountID string `json:"-"` + Token string `json:"-"` + Fingerprint string `json:"-"` + Identifier Identifier `json:"identifier"` + Status Status `json:"status"` + Challenges []*Challenge `json:"challenges"` + Wildcard bool `json:"wildcard"` + ExpiresAt time.Time `json:"expires"` + Error *Error `json:"error,omitempty"` } // ToLog enables response logging. diff --git a/acme/challenge.go b/acme/challenge.go index 6e401501..baa9be76 100644 --- a/acme/challenge.go +++ b/acme/challenge.go @@ -31,6 +31,7 @@ import ( "github.com/ryboe/q" "go.step.sm/crypto/jose" + "go.step.sm/crypto/keyutil" "go.step.sm/crypto/pemutil" "github.com/smallstep/certificates/authority/provisioner" @@ -84,10 +85,9 @@ func (ch *Challenge) ToLog() (interface{}, error) { return string(b), nil } -// Validate attempts to validate the challenge. Stores changes to the Challenge -// type using the DB interface. -// satisfactorily validated, the 'status' and 'validated' attributes are -// updated. +// Validate attempts to validate the Challenge. Stores changes to the Challenge +// type using the DB interface. If the Challenge is validated, the 'status' and +// 'validated' attributes are updated. func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey, payload []byte) error { // If already valid or invalid then return without performing validation. if ch.Status != StatusPending { @@ -340,20 +340,26 @@ func dns01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebK return nil } -type Payload struct { +type payloadType struct { AttObj string `json:"attObj"` Error string `json:"error"` } -type AttestationObject struct { +type attestationObject struct { Format string `json:"fmt"` AttStatement map[string]interface{} `json:"attStmt,omitempty"` } // TODO(bweeks): move attestation verification to a shared package. -// TODO(bweeks): define new error type for failed attestation validation. func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, payload []byte) error { - var p Payload + // Load authorization to store the key fingerprint. + az, err := db.GetAuthorization(ctx, ch.AuthorizationID) + if err != nil { + return WrapErrorISE(err, "error loading authorization") + } + + // Parse payload. + var p payloadType if err := json.Unmarshal(payload, &p); err != nil { return WrapErrorISE(err, "error unmarshalling JSON") } @@ -367,7 +373,7 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose return WrapErrorISE(err, "error base64 decoding attObj") } - att := AttestationObject{} + att := attestationObject{} if err := cbor.Unmarshal(attObj, &att); err != nil { return WrapErrorISE(err, "error unmarshalling CBOR") } @@ -391,7 +397,6 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose } return WrapErrorISE(err, "error validating attestation") } - // Validate nonce with SHA-256 of the token. if len(data.Nonce) != 0 { sum := sha256.Sum256([]byte(ch.Token)) @@ -407,6 +412,9 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose if data.UDID != ch.Value && data.SerialNumber != ch.Value { return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match")) } + + // Update attestation key fingerprint to compare against the CSR + az.Fingerprint = data.Fingerprint case "step": data, err := doStepAttestationFormat(ctx, prov, ch, jwk, &att) if err != nil { @@ -420,13 +428,22 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose return WrapErrorISE(err, "error validating attestation") } - // Validate Apple's ClientIdentifier (Identifier.Value) with device - // identifiers. + // Validate the YubiKey serial number from the attestation + // certificate with the challenged Order value. // // Note: We might want to use an external service for this. if data.SerialNumber != ch.Value { - return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match")) + subproblem := NewSubproblemWithIdentifier( + ErrorMalformedType, + 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").AddSubproblems(subproblem)) } + + // Update attestation key fingerprint to compare against the CSR + az.Fingerprint = data.Fingerprint + case "tpm": data, err := doTPMAttestationFormat(ctx, ch, db, &att) if err != nil { @@ -462,6 +479,15 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose ch.Error = nil ch.ValidatedAt = clock.Now().Format(time.RFC3339) + // Store the fingerprint in the authorization. + // + // TODO: add method to update authorization and challenge atomically. + if az.Fingerprint != "" { + if err := db.UpdateAuthorization(ctx, az); err != nil { + return WrapErrorISE(err, "error updating authorization") + } + } + if err := db.UpdateChallenge(ctx, ch); err != nil { return WrapErrorISE(err, "error updating challenge") } @@ -482,7 +508,7 @@ type tpmAttestationData struct { ExtraData []byte // TODO(hs): rename this to KeyAuthorization to reflect its usage? } -func doTPMAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *AttestationObject) (*tpmAttestationData, error) { +func doTPMAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *attestationObject) (*tpmAttestationData, error) { p := MustProvisionerFromContext(ctx) prov, ok := p.(*provisioner.ACME) @@ -659,9 +685,10 @@ type appleAttestationData struct { UDID string SEPVersion string Certificate *x509.Certificate + Fingerprint string } -func doAppleAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, att *AttestationObject) (*appleAttestationData, error) { +func doAppleAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, att *attestationObject) (*appleAttestationData, error) { // Use configured or default attestation roots if none is configured. roots, ok := prov.GetAttestationRoots() if !ok { @@ -715,6 +742,9 @@ func doAppleAttestationFormat(ctx context.Context, prov Provisioner, ch *Challen data := &appleAttestationData{ Certificate: leaf, } + if data.Fingerprint, err = keyutil.Fingerprint(leaf.PublicKey); err != nil { + return nil, WrapErrorISE(err, "error calculating key fingerprint") + } for _, ext := range leaf.Extensions { switch { case ext.Id.Equal(oidAppleSerialNumber): @@ -760,9 +790,10 @@ var oidYubicoSerialNumber = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 41482, 3, 7} type stepAttestationData struct { Certificate *x509.Certificate SerialNumber string + Fingerprint string } -func doStepAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, jwk *jose.JSONWebKey, att *AttestationObject) (*stepAttestationData, error) { +func doStepAttestationFormat(ctx context.Context, prov Provisioner, ch *Challenge, jwk *jose.JSONWebKey, att *attestationObject) (*stepAttestationData, error) { // Use configured or default attestation roots if none is configured. roots, ok := prov.GetAttestationRoots() if !ok { @@ -855,6 +886,9 @@ func doStepAttestationFormat(ctx context.Context, prov Provisioner, ch *Challeng data := &stepAttestationData{ Certificate: leaf, } + if data.Fingerprint, err = keyutil.Fingerprint(leaf.PublicKey); err != nil { + return nil, WrapErrorISE(err, "error calculating key fingerprint") + } for _, ext := range leaf.Extensions { if !ext.Id.Equal(oidYubicoSerialNumber) { continue diff --git a/acme/challenge_test.go b/acme/challenge_test.go index 1aa9f6ab..ccd8f6b8 100644 --- a/acme/challenge_test.go +++ b/acme/challenge_test.go @@ -15,6 +15,7 @@ import ( "encoding/asn1" "encoding/base64" "encoding/hex" + "encoding/json" "encoding/pem" "errors" "fmt" @@ -30,12 +31,15 @@ import ( "time" "github.com/fxamacker/cbor/v2" - "github.com/smallstep/assert" - "github.com/smallstep/certificates/authority/config" - "github.com/smallstep/certificates/authority/provisioner" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.step.sm/crypto/jose" "go.step.sm/crypto/keyutil" "go.step.sm/crypto/minica" + + "github.com/smallstep/certificates/authority/config" + "github.com/smallstep/certificates/authority/provisioner" ) type mockClient struct { @@ -50,6 +54,30 @@ func (m *mockClient) TLSDial(network, addr string, tlsConfig *tls.Config) (*tls. return m.tlsDial(network, addr, tlsConfig) } +func fatalError(t *testing.T, err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } +} + +func mustNonAttestationProvisioner(t *testing.T) Provisioner { + t.Helper() + + prov := &provisioner.ACME{ + Type: "ACME", + Name: "acme", + Challenges: []provisioner.ACMEChallenge{provisioner.HTTP_01}, + } + if err := prov.Init(provisioner.Config{ + Claims: config.GlobalProvisionerClaims, + }); err != nil { + t.Fatal(err) + } + prov.AttestationFormats = []provisioner.ACMEAttestationFormat{"bogus-format"} // results in no attestation formats enabled + return prov +} + func mustAttestationProvisioner(t *testing.T, roots []byte) Provisioner { t.Helper() @@ -67,6 +95,108 @@ func mustAttestationProvisioner(t *testing.T, roots []byte) Provisioner { return prov } +func mustAccountAndKeyAuthorization(t *testing.T, token string) (*jose.JSONWebKey, string) { + t.Helper() + + jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) + fatalError(t, err) + + keyAuth, err := KeyAuthorization(token, jwk) + fatalError(t, err) + return jwk, keyAuth +} + +func mustAttestApple(t *testing.T, nonce string) ([]byte, *x509.Certificate, *x509.Certificate) { + t.Helper() + + ca, err := minica.New() + fatalError(t, err) + + signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + fatalError(t, err) + + nonceSum := sha256.Sum256([]byte(nonce)) + leaf, err := ca.Sign(&x509.Certificate{ + Subject: pkix.Name{CommonName: "attestation cert"}, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + {Id: oidAppleSerialNumber, Value: []byte("serial-number")}, + {Id: oidAppleUniqueDeviceIdentifier, Value: []byte("udid")}, + {Id: oidAppleSecureEnclaveProcessorOSVersion, Value: []byte("16.0")}, + {Id: oidAppleNonce, Value: nonceSum[:]}, + }, + }) + fatalError(t, err) + + attObj, err := cbor.Marshal(struct { + Format string `json:"fmt"` + AttStatement map[string]interface{} `json:"attStmt,omitempty"` + }{ + Format: "apple", + AttStatement: map[string]interface{}{ + "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, + }, + }) + fatalError(t, err) + + payload, err := json.Marshal(struct { + AttObj string `json:"attObj"` + }{ + AttObj: base64.RawURLEncoding.EncodeToString(attObj), + }) + fatalError(t, err) + + return payload, leaf, ca.Root +} + +func mustAttestYubikey(t *testing.T, nonce, keyAuthorization string, serial int) ([]byte, *x509.Certificate, *x509.Certificate) { + ca, err := minica.New() + fatalError(t, err) + + keyAuthSum := sha256.Sum256([]byte(keyAuthorization)) + + signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + fatalError(t, err) + sig, err := signer.Sign(rand.Reader, keyAuthSum[:], crypto.SHA256) + fatalError(t, err) + cborSig, err := cbor.Marshal(sig) + fatalError(t, err) + + serialNumber, err := asn1.Marshal(serial) + fatalError(t, err) + + leaf, err := ca.Sign(&x509.Certificate{ + Subject: pkix.Name{CommonName: "attestation cert"}, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + {Id: oidYubicoSerialNumber, Value: serialNumber}, + }, + }) + fatalError(t, err) + + attObj, err := cbor.Marshal(struct { + Format string `json:"fmt"` + AttStatement map[string]interface{} `json:"attStmt,omitempty"` + }{ + Format: "step", + AttStatement: map[string]interface{}{ + "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, + "alg": -7, + "sig": cborSig, + }, + }) + fatalError(t, err) + + payload, err := json.Marshal(struct { + AttObj string `json:"attObj"` + }{ + AttObj: base64.RawURLEncoding.EncodeToString(attObj), + }) + fatalError(t, err) + + return payload, leaf, ca.Root +} + func Test_storeError(t *testing.T) { type test struct { ch *Challenge @@ -87,16 +217,17 @@ func Test_storeError(t *testing.T) { ch: ch, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusValid) - - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusValid, updch.Status) + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -114,16 +245,17 @@ func Test_storeError(t *testing.T) { ch: ch, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusValid) - - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusValid, updch.Status) + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return NewError(ErrorMalformedType, "bar") }, }, @@ -141,16 +273,17 @@ func Test_storeError(t *testing.T) { ch: ch, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusValid) - - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusValid, updch.Status) + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -167,16 +300,17 @@ func Test_storeError(t *testing.T) { ch: ch, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusInvalid) - - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusInvalid, updch.Status) + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -188,16 +322,15 @@ func Test_storeError(t *testing.T) { t.Run(name, func(t *testing.T) { tc := run(t) if err := storeError(context.Background(), tc.db, tc.ch, tc.markInvalid, err); err != nil { - if assert.NotNil(t, tc.err) { + if assert.Error(t, tc.err) { var k *Error if errors.As(err, &k) { - assert.Equals(t, k.Type, tc.err.Type) - assert.Equals(t, k.Detail, tc.err.Detail) - assert.Equals(t, k.Status, tc.err.Status) - assert.Equals(t, k.Err.Error(), tc.err.Err.Error()) - assert.Equals(t, k.Detail, tc.err.Detail) + assert.Equal(t, tc.err.Type, k.Type) + assert.Equal(t, tc.err.Detail, k.Detail) + assert.Equal(t, tc.err.Status, k.Status) + assert.Equal(t, tc.err.Err.Error(), k.Err.Error()) } else { - assert.FatalError(t, errors.New("unexpected error type")) + assert.Fail(t, "unexpected error type") } } } else { @@ -217,7 +350,7 @@ func TestKeyAuthorization(t *testing.T) { tests := map[string]func(t *testing.T) test{ "fail/jwk-thumbprint-error": func(t *testing.T) test { jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) jwk.Key = "foo" return test{ token: "1234", @@ -228,9 +361,9 @@ func TestKeyAuthorization(t *testing.T) { "ok": func(t *testing.T) test { token := "1234" jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) thumbprint, err := jwk.Thumbprint(crypto.SHA256) - assert.FatalError(t, err) + require.NoError(t, err) encPrint := base64.RawURLEncoding.EncodeToString(thumbprint) return test{ token: token, @@ -243,21 +376,20 @@ func TestKeyAuthorization(t *testing.T) { t.Run(name, func(t *testing.T) { tc := run(t) if ka, err := KeyAuthorization(tc.token, tc.jwk); err != nil { - if assert.NotNil(t, tc.err) { + if assert.Error(t, tc.err) { var k *Error if errors.As(err, &k) { - assert.Equals(t, k.Type, tc.err.Type) - assert.Equals(t, k.Detail, tc.err.Detail) - assert.Equals(t, k.Status, tc.err.Status) - assert.Equals(t, k.Err.Error(), tc.err.Err.Error()) - assert.Equals(t, k.Detail, tc.err.Detail) + assert.Equal(t, tc.err.Type, k.Type) + assert.Equal(t, tc.err.Detail, k.Detail) + assert.Equal(t, tc.err.Status, k.Status) + assert.Equal(t, tc.err.Err.Error(), k.Err.Error()) } else { - assert.FatalError(t, errors.New("unexpected error type")) + assert.Fail(t, "unexpected error type") } } } else { if assert.Nil(t, tc.err) { - assert.Equals(t, tc.exp, ka) + assert.Equal(t, tc.exp, ka) } } }) @@ -266,12 +398,14 @@ func TestKeyAuthorization(t *testing.T) { func TestChallenge_Validate(t *testing.T) { type test struct { - ch *Challenge - vc Client - jwk *jose.JSONWebKey - db DB - srv *httptest.Server - err *Error + ch *Challenge + vc Client + jwk *jose.JSONWebKey + db DB + srv *httptest.Server + payload []byte + ctx context.Context + err *Error } tests := map[string]func(t *testing.T) test{ "ok/already-valid": func(t *testing.T) test { @@ -318,18 +452,19 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("http-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -354,18 +489,19 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("http-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -395,18 +531,19 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("http-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal:8080/.well-known/acme-challenge/%s: force", ch.Token) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -430,19 +567,20 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("dns-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -467,19 +605,20 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("dns-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -502,19 +641,20 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing TLS dial for %v:443: force", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -531,14 +671,14 @@ func TestChallenge_Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -550,12 +690,12 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Error, nil) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusValid, updch.Status) + assert.Nil(t, updch.Error) return nil }, }, @@ -577,14 +717,14 @@ func TestChallenge_Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { @@ -616,12 +756,12 @@ func TestChallenge_Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Error, nil) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusValid, updch.Status) + assert.Nil(t, updch.Error) return nil }, }, @@ -629,6 +769,91 @@ func TestChallenge_Validate(t *testing.T) { jwk: jwk, } }, + "fail/device-attest-01": func(t *testing.T) test { + payload, err := json.Marshal(struct { + Error string `json:"error"` + }{ + Error: "an error", + }) + assert.NoError(t, err) + return test{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorRejectedIdentifierType, "payload contained error: an error") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + + return errors.New("force") + }, + }, + err: NewError(ErrorServerInternalType, "failure saving error to acme challenge: force"), + } + }, + "ok/device-attest-01": func(t *testing.T) test { + jwk, keyAuth := mustAccountAndKeyAuthorization(t, "token") + payload, leaf, root := mustAttestYubikey(t, "nonce", keyAuth, 1234) + + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + + return test{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "1234", + }, + payload: payload, + ctx: ctx, + jwk: jwk, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateAuthorization: func(ctx context.Context, az *Authorization) error { + fingerprint, err := keyutil.Fingerprint(leaf.PublicKey) + assert.NoError(t, err) + assert.Equal(t, "azID", az.ID) + assert.Equal(t, fingerprint, az.Fingerprint) + return nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusValid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "1234", updch.Value) + + return nil + }, + }, + } + }, } for name, run := range tests { t.Run(name, func(t *testing.T) { @@ -638,18 +863,21 @@ func TestChallenge_Validate(t *testing.T) { defer tc.srv.Close() } - ctx := NewClientContext(context.Background(), tc.vc) - if err := tc.ch.Validate(ctx, tc.db, tc.jwk, nil); err != nil { - if assert.NotNil(t, tc.err) { + ctx := tc.ctx + if ctx == nil { + ctx = context.Background() + } + ctx = NewClientContext(ctx, tc.vc) + if err := tc.ch.Validate(ctx, tc.db, tc.jwk, tc.payload); err != nil { + if assert.Error(t, tc.err) { var k *Error if errors.As(err, &k) { - assert.Equals(t, k.Type, tc.err.Type) - assert.Equals(t, k.Detail, tc.err.Detail) - assert.Equals(t, k.Status, tc.err.Status) - assert.Equals(t, k.Err.Error(), tc.err.Err.Error()) - assert.Equals(t, k.Detail, tc.err.Detail) + assert.Equal(t, tc.err.Type, k.Type) + assert.Equal(t, tc.err.Detail, k.Detail) + assert.Equal(t, tc.err.Status, k.Status) + assert.Equal(t, tc.err.Err.Error(), k.Err.Error()) } else { - assert.FatalError(t, errors.New("unexpected error type")) + assert.Fail(t, "unexpected error type") } } } else { @@ -694,17 +922,18 @@ func TestHTTP01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -728,17 +957,18 @@ func TestHTTP01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -764,17 +994,18 @@ func TestHTTP01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s with status code 400", ch.Token) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -801,17 +1032,18 @@ func TestHTTP01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s with status code 400", ch.Token) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -846,7 +1078,7 @@ func TestHTTP01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) jwk.Key = "foo" return test{ ch: ch, @@ -870,10 +1102,10 @@ func TestHTTP01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) return test{ ch: ch, vc: &mockClient{ @@ -886,18 +1118,19 @@ func TestHTTP01Validate(t *testing.T) { jwk: jwk, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusInvalid) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusInvalid, updch.Status) err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got foo", expKeyAuth) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -912,10 +1145,10 @@ func TestHTTP01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) return test{ ch: ch, vc: &mockClient{ @@ -928,18 +1161,19 @@ func TestHTTP01Validate(t *testing.T) { jwk: jwk, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusInvalid) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusInvalid, updch.Status) err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got foo", expKeyAuth) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -955,10 +1189,10 @@ func TestHTTP01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) return test{ ch: ch, vc: &mockClient{ @@ -971,13 +1205,14 @@ func TestHTTP01Validate(t *testing.T) { jwk: jwk, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusValid) - assert.Equals(t, updch.Error, nil) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusValid, updch.Status) + assert.Nil(t, updch.Error) + va, err := time.Parse(time.RFC3339, updch.ValidatedAt) - assert.FatalError(t, err) + require.NoError(t, err) now := clock.Now() assert.True(t, va.Add(-time.Minute).Before(now)) assert.True(t, va.Add(time.Minute).After(now)) @@ -997,10 +1232,10 @@ func TestHTTP01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) return test{ ch: ch, vc: &mockClient{ @@ -1013,14 +1248,14 @@ func TestHTTP01Validate(t *testing.T) { jwk: jwk, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, "zap.internal", updch.Value) + assert.Equal(t, StatusValid, updch.Status) + assert.Nil(t, updch.Error) - assert.Equals(t, updch.Status, StatusValid) - assert.Equals(t, updch.Error, nil) va, err := time.Parse(time.RFC3339, updch.ValidatedAt) - assert.FatalError(t, err) + require.NoError(t, err) now := clock.Now() assert.True(t, va.Add(-time.Minute).Before(now)) assert.True(t, va.Add(time.Minute).After(now)) @@ -1035,16 +1270,15 @@ func TestHTTP01Validate(t *testing.T) { tc := run(t) ctx := NewClientContext(context.Background(), tc.vc) if err := http01Validate(ctx, tc.ch, tc.db, tc.jwk); err != nil { - if assert.NotNil(t, tc.err) { + if assert.Error(t, tc.err) { var k *Error if errors.As(err, &k) { - assert.Equals(t, k.Type, tc.err.Type) - assert.Equals(t, k.Detail, tc.err.Detail) - assert.Equals(t, k.Status, tc.err.Status) - assert.Equals(t, k.Err.Error(), tc.err.Err.Error()) - assert.Equals(t, k.Detail, tc.err.Detail) + assert.Equal(t, tc.err.Type, k.Type) + assert.Equal(t, tc.err.Detail, k.Detail) + assert.Equal(t, tc.err.Status, k.Status) + assert.Equal(t, tc.err.Err.Error(), k.Err.Error()) } else { - assert.FatalError(t, errors.New("unexpected error type")) + assert.Fail(t, "unexpected error type") } } } else { @@ -1082,18 +1316,19 @@ func TestDNS01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, fulldomain, updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", domain) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -1117,18 +1352,19 @@ func TestDNS01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, fulldomain, updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", domain) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1143,7 +1379,7 @@ func TestDNS01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) jwk.Key = "foo" return test{ @@ -1166,10 +1402,10 @@ func TestDNS01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) return test{ ch: ch, @@ -1180,18 +1416,19 @@ func TestDNS01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, fulldomain, updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got %s", expKeyAuth, []string{"foo", "bar"}) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -1208,10 +1445,10 @@ func TestDNS01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) return test{ ch: ch, @@ -1222,18 +1459,19 @@ func TestDNS01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusPending) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, fulldomain, updch.Value) + assert.Equal(t, StatusPending, updch.Status) err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got %s", expKeyAuth, []string{"foo", "bar"}) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1249,10 +1487,10 @@ func TestDNS01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) h := sha256.Sum256([]byte(expKeyAuth)) expected := base64.RawURLEncoding.EncodeToString(h[:]) @@ -1265,15 +1503,14 @@ func TestDNS01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusValid) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, fulldomain, ch.Value) + assert.Equal(t, StatusValid, updch.Status) + assert.Nil(t, updch.Error) - assert.Equals(t, updch.Status, StatusValid) - assert.Equals(t, updch.Error, nil) va, err := time.Parse(time.RFC3339, updch.ValidatedAt) - assert.FatalError(t, err) + require.NoError(t, err) now := clock.Now() assert.True(t, va.Add(-time.Minute).Before(now)) assert.True(t, va.Add(time.Minute).After(now)) @@ -1294,10 +1531,10 @@ func TestDNS01Validate(t *testing.T) { } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) h := sha256.Sum256([]byte(expKeyAuth)) expected := base64.RawURLEncoding.EncodeToString(h[:]) @@ -1310,15 +1547,14 @@ func TestDNS01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Status, StatusValid) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, fulldomain, updch.Value) + assert.Equal(t, StatusValid, updch.Status) + assert.Nil(t, updch.Error) - assert.Equals(t, updch.Status, StatusValid) - assert.Equals(t, updch.Error, nil) va, err := time.Parse(time.RFC3339, updch.ValidatedAt) - assert.FatalError(t, err) + require.NoError(t, err) now := clock.Now() assert.True(t, va.Add(-time.Minute).Before(now)) assert.True(t, va.Add(time.Minute).After(now)) @@ -1335,16 +1571,15 @@ func TestDNS01Validate(t *testing.T) { tc := run(t) ctx := NewClientContext(context.Background(), tc.vc) if err := dns01Validate(ctx, tc.ch, tc.db, tc.jwk); err != nil { - if assert.NotNil(t, tc.err) { + if assert.Error(t, tc.err) { var k *Error if errors.As(err, &k) { - assert.Equals(t, k.Type, tc.err.Type) - assert.Equals(t, k.Detail, tc.err.Detail) - assert.Equals(t, k.Status, tc.err.Status) - assert.Equals(t, k.Err.Error(), tc.err.Err.Error()) - assert.Equals(t, k.Detail, tc.err.Detail) + assert.Equal(t, tc.err.Type, k.Type) + assert.Equal(t, tc.err.Detail, k.Detail) + assert.Equal(t, tc.err.Status, k.Status) + assert.Equal(t, tc.err.Err.Error(), k.Err.Error()) } else { - assert.FatalError(t, errors.New("unexpected error type")) + assert.Fail(t, "unexpected error type") } } } else { @@ -1483,19 +1718,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusPending, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorConnectionType, "error doing TLS dial for %v:443: force", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -1513,19 +1749,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusPending, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorConnectionType, "error doing TLS dial for %v:443: force", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1544,19 +1781,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, ch.Status) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) - - err := NewError(ErrorConnectionType, "error doing TLS dial for %v:443:", ch.Value) - - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusPending, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + + err := NewError(ErrorConnectionType, "error doing TLS dial for %v:443: context deadline exceeded", ch.Value) + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1575,19 +1813,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "tls-alpn-01 challenge for %v resulted in no certificates", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1605,19 +1844,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "tls-alpn-01 challenge for %v resulted in no certificates", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -1628,7 +1868,7 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) srv := httptest.NewTLSServer(nil) @@ -1641,19 +1881,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "cannot negotiate ALPN acme-tls/1 protocol for tls-alpn-01 challenge") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1665,7 +1906,7 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) srv := httptest.NewTLSServer(nil) @@ -1678,19 +1919,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "cannot negotiate ALPN acme-tls/1 protocol for tls-alpn-01 challenge") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -1703,14 +1945,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -1722,19 +1964,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: leaf certificate must contain a single IP address or DNS name, %v", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1746,14 +1989,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -1765,19 +2008,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: leaf certificate must contain a single IP address or DNS name, %v", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -1790,14 +2034,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true, ch.Value, "other.internal") - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -1809,19 +2053,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: leaf certificate must contain a single IP address or DNS name, %v", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1833,14 +2078,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true, "other.internal") - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -1852,19 +2097,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: leaf certificate must contain a single IP address or DNS name, %v", ch.Value) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1876,15 +2122,15 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) jwk.Key = "foo" cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -1903,10 +2149,10 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) cert, err := newTLSALPNValidationCert(nil, false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -1918,19 +2164,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: missing acmeValidationV1 extension") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -1942,10 +2189,10 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) cert, err := newTLSALPNValidationCert(nil, false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -1957,19 +2204,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: missing acmeValidationV1 extension") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -1982,14 +2230,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, false, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2001,19 +2249,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: acmeValidationV1 extension not critical") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -2025,14 +2274,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, false, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2044,19 +2293,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: acmeValidationV1 extension not critical") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -2069,10 +2319,10 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) cert, err := newTLSALPNValidationCert([]byte{1, 2, 3}, false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2084,19 +2334,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: malformed acmeValidationV1 extension value") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -2108,10 +2359,10 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) cert, err := newTLSALPNValidationCert([]byte{1, 2, 3}, false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2123,19 +2374,20 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: malformed acmeValidationV1 extension value") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -2148,15 +2400,15 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) incorrectTokenHash := sha256.Sum256([]byte("mismatched")) cert, err := newTLSALPNValidationCert(incorrectTokenHash[:], false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2168,21 +2420,22 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: "+ "expected acmeValidationV1 extension value %s for this challenge but got %s", hex.EncodeToString(expKeyAuthHash[:]), hex.EncodeToString(incorrectTokenHash[:])) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -2194,15 +2447,15 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) incorrectTokenHash := sha256.Sum256([]byte("mismatched")) cert, err := newTLSALPNValidationCert(incorrectTokenHash[:], false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2214,21 +2467,22 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: "+ "expected acmeValidationV1 extension value %s for this challenge but got %s", hex.EncodeToString(expKeyAuthHash[:]), hex.EncodeToString(incorrectTokenHash[:])) - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -2241,14 +2495,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], true, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2260,20 +2514,21 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: "+ "obsolete id-pe-acmeIdentifier in acmeValidationV1 extension") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return nil }, }, @@ -2285,14 +2540,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], true, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2304,20 +2559,21 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusInvalid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) err := NewError(ErrorRejectedIdentifierType, "incorrect certificate for tls-alpn-01 challenge: "+ "obsolete id-pe-acmeIdentifier in acmeValidationV1 extension") - assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) - assert.Equals(t, updch.Error.Type, err.Type) - assert.Equals(t, updch.Error.Detail, err.Detail) - assert.Equals(t, updch.Error.Status, err.Status) - assert.Equals(t, updch.Error.Detail, err.Detail) + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + return errors.New("force") }, }, @@ -2330,14 +2586,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch := makeTLSCh() jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2349,12 +2605,13 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusValid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Error, nil) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusValid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "zap.internal", updch.Value) + assert.Nil(t, updch.Error) + return nil }, }, @@ -2367,14 +2624,14 @@ func TestTLSALPN01Validate(t *testing.T) { ch.Value = "127.0.0.1" jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuth, err := KeyAuthorization(ch.Token, jwk) - assert.FatalError(t, err) + require.NoError(t, err) expKeyAuthHash := sha256.Sum256([]byte(expKeyAuth)) cert, err := newTLSALPNValidationCert(expKeyAuthHash[:], false, true, ch.Value) - assert.FatalError(t, err) + require.NoError(t, err) srv, tlsDial := newTestTLSALPNServer(cert) srv.Start() @@ -2386,12 +2643,13 @@ func TestTLSALPN01Validate(t *testing.T) { }, db: &MockDB{ MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { - assert.Equals(t, updch.ID, ch.ID) - assert.Equals(t, updch.Token, ch.Token) - assert.Equals(t, updch.Status, StatusValid) - assert.Equals(t, updch.Type, ch.Type) - assert.Equals(t, updch.Value, ch.Value) - assert.Equals(t, updch.Error, nil) + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusValid, updch.Status) + assert.Equal(t, ChallengeType("tls-alpn-01"), updch.Type) + assert.Equal(t, "127.0.0.1", updch.Value) + assert.Nil(t, updch.Error) + return nil }, }, @@ -2410,16 +2668,16 @@ func TestTLSALPN01Validate(t *testing.T) { ctx := NewClientContext(context.Background(), tc.vc) if err := tlsalpn01Validate(ctx, tc.ch, tc.db, tc.jwk); err != nil { - if assert.NotNil(t, tc.err) { + if assert.Error(t, tc.err) { var k *Error if errors.As(err, &k) { - assert.Equals(t, k.Type, tc.err.Type) - assert.Equals(t, k.Detail, tc.err.Detail) - assert.Equals(t, k.Status, tc.err.Status) - assert.Equals(t, k.Err.Error(), tc.err.Err.Error()) - assert.Equals(t, k.Detail, tc.err.Detail) + assert.Equal(t, tc.err.Type, k.Type) + assert.Equal(t, tc.err.Detail, k.Detail) + assert.Equal(t, tc.err.Status, k.Status) + assert.Equal(t, tc.err.Err.Error(), k.Err.Error()) + assert.Equal(t, tc.err.Subproblems, k.Subproblems) } else { - assert.FatalError(t, errors.New("unexpected error type")) + assert.Fail(t, "unexpected error type") } } } else { @@ -2563,12 +2821,16 @@ func Test_doAppleAttestationFormat(t *testing.T) { if err != nil { t.Fatal(err) } + fingerprint, err := keyutil.Fingerprint(signer.Public()) + if err != nil { + t.Fatal(err) + } type args struct { ctx context.Context prov Provisioner ch *Challenge - att *AttestationObject + att *attestationObject } tests := []struct { name string @@ -2576,7 +2838,7 @@ func Test_doAppleAttestationFormat(t *testing.T) { want *appleAttestationData wantErr bool }{ - {"ok", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"ok", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2587,50 +2849,51 @@ func Test_doAppleAttestationFormat(t *testing.T) { UDID: "udid", SEPVersion: "16.0", Certificate: leaf, + Fingerprint: fingerprint, }, false}, - {"fail apple issuer", args{ctx, mustAttestationProvisioner(t, nil), &Challenge{}, &AttestationObject{ + {"fail apple issuer", args{ctx, mustAttestationProvisioner(t, nil), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, }, }}, nil, true}, - {"fail missing x5c", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"fail missing x5c", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "foo": "bar", }, }}, nil, true}, - {"fail empty issuer", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"fail empty issuer", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{}, }, }}, nil, true}, - {"fail leaf type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"fail leaf type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{"leaf", ca.Intermediate.Raw}, }, }}, nil, true}, - {"fail leaf parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"fail leaf parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw[:100], ca.Intermediate.Raw}, }, }}, nil, true}, - {"fail intermediate type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"fail intermediate type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, "intermediate"}, }, }}, nil, true}, - {"fail intermediate parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"fail intermediate parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw[:100]}, }, }}, nil, true}, - {"fail verify", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &AttestationObject{ + {"fail verify", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{}, &attestationObject{ Format: "apple", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw}, @@ -2689,6 +2952,10 @@ func Test_doStepAttestationFormat(t *testing.T) { t.Fatal(err) } leaf := makeLeaf(signer, serialNumber) + fingerprint, err := keyutil.Fingerprint(signer.Public()) + if err != nil { + t.Fatal(err) + } jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) if err != nil { @@ -2726,7 +2993,7 @@ func Test_doStepAttestationFormat(t *testing.T) { prov Provisioner ch *Challenge jwk *jose.JSONWebKey - att *AttestationObject + att *attestationObject } tests := []struct { name string @@ -2734,7 +3001,7 @@ func Test_doStepAttestationFormat(t *testing.T) { want *stepAttestationData wantErr bool }{ - {"ok", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"ok", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2744,8 +3011,9 @@ func Test_doStepAttestationFormat(t *testing.T) { }}, &stepAttestationData{ SerialNumber: "1234", Certificate: leaf, + Fingerprint: fingerprint, }, false}, - {"fail yubico issuer", args{ctx, mustAttestationProvisioner(t, nil), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail yubico issuer", args{ctx, mustAttestationProvisioner(t, nil), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2753,7 +3021,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail x5c type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail x5c type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": [][]byte{leaf.Raw, ca.Intermediate.Raw}, @@ -2761,7 +3029,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail x5c empty", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail x5c empty", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{}, @@ -2769,7 +3037,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail leaf type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail leaf type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{"leaf", ca.Intermediate.Raw}, @@ -2777,7 +3045,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail leaf parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail leaf parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw[:100], ca.Intermediate.Raw}, @@ -2785,7 +3053,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail intermediate type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail intermediate type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, "intermediate"}, @@ -2793,7 +3061,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail intermediate parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail intermediate parse", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw[:100]}, @@ -2801,7 +3069,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail verify", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail verify", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw}, @@ -2809,7 +3077,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail sig type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail sig type", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2817,7 +3085,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": string(cborSig), }, }}, nil, true}, - {"fail sig unmarshal", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail sig unmarshal", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2825,7 +3093,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": []byte("bad-sig"), }, }}, nil, true}, - {"fail keyAuthorization", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, &jose.JSONWebKey{Key: []byte("not an asymmetric key")}, &AttestationObject{ + {"fail keyAuthorization", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, &jose.JSONWebKey{Key: []byte("not an asymmetric key")}, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2833,7 +3101,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail sig verify P-256", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail sig verify P-256", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2841,7 +3109,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": otherCBORSig, }, }}, nil, true}, - {"fail sig verify P-384", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail sig verify P-384", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{makeLeaf(mustSigner("EC", "P-384", 0), serialNumber).Raw, ca.Intermediate.Raw}, @@ -2849,7 +3117,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail sig verify RSA", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail sig verify RSA", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{makeLeaf(mustSigner("RSA", "", 2048), serialNumber).Raw, ca.Intermediate.Raw}, @@ -2857,7 +3125,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail sig verify Ed25519", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail sig verify Ed25519", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{makeLeaf(mustSigner("OKP", "Ed25519", 0), serialNumber).Raw, ca.Intermediate.Raw}, @@ -2865,7 +3133,7 @@ func Test_doStepAttestationFormat(t *testing.T) { "sig": cborSig, }, }}, nil, true}, - {"fail unmarshal serial number", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail unmarshal serial number", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{makeLeaf(signer, []byte("bad-serial")).Raw, ca.Intermediate.Raw}, @@ -2951,7 +3219,7 @@ func Test_doStepAttestationFormat_noCAIntermediate(t *testing.T) { prov Provisioner ch *Challenge jwk *jose.JSONWebKey - att *AttestationObject + att *attestationObject } tests := []struct { name string @@ -2959,7 +3227,7 @@ func Test_doStepAttestationFormat_noCAIntermediate(t *testing.T) { want *stepAttestationData wantErr bool }{ - {"fail no intermediate", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &AttestationObject{ + {"fail no intermediate", args{ctx, mustAttestationProvisioner(t, caRoot), &Challenge{Token: "token"}, jwk, &attestationObject{ Format: "step", AttStatement: map[string]interface{}{ "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, @@ -2981,3 +3249,762 @@ func Test_doStepAttestationFormat_noCAIntermediate(t *testing.T) { }) } } + +func Test_deviceAttest01Validate(t *testing.T) { + invalidPayload := "!?" + errorPayload, err := json.Marshal(struct { + Error string `json:"error"` + }{ + Error: "an error", + }) + require.NoError(t, err) + errorBase64Payload, err := json.Marshal(struct { + AttObj string `json:"attObj"` + }{ + AttObj: "?!", + }) + require.NoError(t, err) + errorCBORPayload, err := json.Marshal(struct { + AttObj string `json:"attObj"` + }{ + AttObj: "AAAA", + }) + require.NoError(t, err) + type args struct { + ctx context.Context + ch *Challenge + db DB + jwk *jose.JSONWebKey + payload []byte + } + type test struct { + args args + wantErr *Error + } + tests := map[string]func(t *testing.T) test{ + "fail/getAuthorization": func(t *testing.T) test { + return test{ + args: args{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return nil, errors.New("not found") + }, + }, + payload: []byte(invalidPayload), + }, + wantErr: NewErrorISE("error loading authorization: not found"), + } + }, + "fail/json.Unmarshal": func(t *testing.T) test { + return test{ + args: args{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + }, + payload: []byte(invalidPayload), + }, + wantErr: NewErrorISE("error unmarshalling JSON: invalid character '!' looking for beginning of value"), + } + + }, + "fail/storeError": func(t *testing.T) test { + return test{ + args: args{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: errorPayload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorRejectedIdentifierType, "payload contained error: an error") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return errors.New("force") + }, + }, + }, + wantErr: NewErrorISE("failure saving error to acme challenge: force"), + } + }, + "ok/storeError-return-nil": func(t *testing.T) test { + return test{ + args: args{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: errorPayload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorRejectedIdentifierType, "payload contained error: an error") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + "fail/base64-decode": func(t *testing.T) test { + return test{ + args: args{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + }, + payload: errorBase64Payload, + }, + wantErr: NewErrorISE("error base64 decoding attObj: illegal base64 data at input byte 0"), + } + }, + "fail/cbor.Unmarshal": func(t *testing.T) test { + return test{ + args: args{ + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + }, + payload: errorCBORPayload, + }, + wantErr: NewErrorISE("error unmarshalling CBOR: cbor: cannot unmarshal positive integer into Go value of type acme.attestationObject"), + } + }, + "ok/prov.IsAttestationFormatEnabled": func(t *testing.T) test { + jwk, keyAuth := mustAccountAndKeyAuthorization(t, "token") + payload, _, _ := mustAttestYubikey(t, "nonce", keyAuth, 12345678) + ctx := NewProvisionerContext(context.Background(), mustNonAttestationProvisioner(t)) + + return test{ + args: args{ + ctx: ctx, + jwk: jwk, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorBadAttestationStatementType, "attestation format %q is not enabled", "step") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + "ok/doAppleAttestationFormat-storeError": func(t *testing.T) test { + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, nil)) + attObj, err := cbor.Marshal(struct { + Format string `json:"fmt"` + AttStatement map[string]interface{} `json:"attStmt,omitempty"` + }{ + Format: "apple", + AttStatement: map[string]interface{}{}, + }) + require.NoError(t, err) + payload, err := json.Marshal(struct { + AttObj string `json:"attObj"` + }{ + AttObj: base64.RawURLEncoding.EncodeToString(attObj), + }) + require.NoError(t, err) + return test{ + args: args{ + ctx: ctx, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorBadAttestationStatementType, "x5c not present") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + "ok/doAppleAttestationFormat-non-matching-nonce": func(t *testing.T) test { + jwk, _ := mustAccountAndKeyAuthorization(t, "token") + payload, _, root := mustAttestApple(t, "bad-nonce") + + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + + return test{ + args: args{ + ctx: ctx, + jwk: jwk, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "serial-number", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "serial-number", updch.Value) + + err := NewError(ErrorBadAttestationStatementType, "challenge token does not match") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + "ok/doAppleAttestationFormat-non-matching-challenge-value": func(t *testing.T) test { + jwk, _ := mustAccountAndKeyAuthorization(t, "token") + payload, _, root := mustAttestApple(t, "nonce") + + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + return test{ + args: args{ + ctx: ctx, + jwk: jwk, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "nonce", + Type: "device-attest-01", + Status: StatusPending, + Value: "non-matching-value", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "nonce", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "non-matching-value", updch.Value) + + err := NewError(ErrorBadAttestationStatementType, "permanent identifier does not match") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + "ok/doStepAttestationFormat-storeError": func(t *testing.T) test { + ca, err := minica.New() + require.NoError(t, err) + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: ca.Root.Raw}) + signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) + require.NoError(t, err) + token := "token" + keyAuth, err := KeyAuthorization(token, jwk) + require.NoError(t, err) + keyAuthSum := sha256.Sum256([]byte(keyAuth)) + sig, err := signer.Sign(rand.Reader, keyAuthSum[:], crypto.SHA256) + require.NoError(t, err) + cborSig, err := cbor.Marshal(sig) + require.NoError(t, err) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + attObj, err := cbor.Marshal(struct { + Format string `json:"fmt"` + AttStatement map[string]interface{} `json:"attStmt,omitempty"` + }{ + Format: "step", + AttStatement: map[string]interface{}{ + "alg": -7, + "sig": cborSig, + }, + }) + require.NoError(t, err) + payload, err := json.Marshal(struct { + AttObj string `json:"attObj"` + }{ + AttObj: base64.RawURLEncoding.EncodeToString(attObj), + }) + require.NoError(t, err) + return test{ + args: args{ + ctx: ctx, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorBadAttestationStatementType, "x5c not present") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + "ok/doStepAttestationFormat-non-matching-identifier": func(t *testing.T) test { + jwk, keyAuth := mustAccountAndKeyAuthorization(t, "token") + payload, leaf, root := mustAttestYubikey(t, "nonce", keyAuth, 87654321) + + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + + return test{ + args: args{ + ctx: ctx, + jwk: jwk, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateAuthorization: func(ctx context.Context, az *Authorization) error { + fingerprint, err := keyutil.Fingerprint(leaf.PublicKey) + assert.NoError(t, err) + assert.Equal(t, "azID", az.ID) + assert.Equal(t, fingerprint, az.Fingerprint) + return nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorBadAttestationStatementType, "permanent identifier does not match"). + AddSubproblems(NewSubproblemWithIdentifier( + ErrorMalformedType, + Identifier{Type: "permanent-identifier", Value: "12345678"}, + "challenge identifier \"12345678\" doesn't match the attested hardware identifier \"87654321\"", + )) + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + "ok/unknown-attestation-format": func(t *testing.T) test { + ca, err := minica.New() + require.NoError(t, err) + signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) + require.NoError(t, err) + token := "token" + keyAuth, err := KeyAuthorization(token, jwk) + require.NoError(t, err) + keyAuthSum := sha256.Sum256([]byte(keyAuth)) + sig, err := signer.Sign(rand.Reader, keyAuthSum[:], crypto.SHA256) + require.NoError(t, err) + cborSig, err := cbor.Marshal(sig) + require.NoError(t, err) + ctx := NewProvisionerContext(context.Background(), mustNonAttestationProvisioner(t)) + makeLeaf := func(signer crypto.Signer, serialNumber []byte) *x509.Certificate { + leaf, err := ca.Sign(&x509.Certificate{ + Subject: pkix.Name{CommonName: "attestation cert"}, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + {Id: oidYubicoSerialNumber, Value: serialNumber}, + }, + }) + if err != nil { + t.Fatal(err) + } + return leaf + } + require.NoError(t, err) + serialNumber, err := asn1.Marshal(87654321) + require.NoError(t, err) + leaf := makeLeaf(signer, serialNumber) + attObj, err := cbor.Marshal(struct { + Format string `json:"fmt"` + AttStatement map[string]interface{} `json:"attStmt,omitempty"` + }{ + Format: "bogus-format", + AttStatement: map[string]interface{}{ + "x5c": []interface{}{leaf.Raw, ca.Intermediate.Raw}, + "alg": -7, + "sig": cborSig, + }, + }) + require.NoError(t, err) + payload, err := json.Marshal(struct { + AttObj string `json:"attObj"` + }{ + AttObj: base64.RawURLEncoding.EncodeToString(attObj), + }) + require.NoError(t, err) + return test{ + args: args{ + ctx: ctx, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusInvalid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + err := NewError(ErrorBadAttestationStatementType, "unexpected attestation object format") + + assert.EqualError(t, updch.Error.Err, err.Err.Error()) + assert.Equal(t, err.Type, updch.Error.Type) + assert.Equal(t, err.Detail, updch.Error.Detail) + assert.Equal(t, err.Status, updch.Error.Status) + assert.Equal(t, err.Subproblems, updch.Error.Subproblems) + + return nil + }, + }, + jwk: jwk, + }, + wantErr: nil, + } + }, + "fail/db.UpdateAuthorization": func(t *testing.T) test { + jwk, keyAuth := mustAccountAndKeyAuthorization(t, "token") + payload, leaf, root := mustAttestYubikey(t, "nonce", keyAuth, 12345678) + + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + + return test{ + args: args{ + ctx: ctx, + jwk: jwk, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateAuthorization: func(ctx context.Context, az *Authorization) error { + fingerprint, err := keyutil.Fingerprint(leaf.PublicKey) + assert.NoError(t, err) + assert.Equal(t, "azID", az.ID) + assert.Equal(t, fingerprint, az.Fingerprint) + return errors.New("force") + }, + }, + }, + wantErr: NewError(ErrorServerInternalType, "error updating authorization: force"), + } + }, + "fail/db.UpdateChallenge": func(t *testing.T) test { + jwk, keyAuth := mustAccountAndKeyAuthorization(t, "token") + payload, leaf, root := mustAttestYubikey(t, "nonce", keyAuth, 12345678) + + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + + return test{ + args: args{ + ctx: ctx, + jwk: jwk, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateAuthorization: func(ctx context.Context, az *Authorization) error { + fingerprint, err := keyutil.Fingerprint(leaf.PublicKey) + assert.NoError(t, err) + assert.Equal(t, "azID", az.ID) + assert.Equal(t, fingerprint, az.Fingerprint) + return nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusValid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + return errors.New("force") + }, + }, + }, + wantErr: NewError(ErrorServerInternalType, "error updating challenge: force"), + } + }, + "ok": func(t *testing.T) test { + jwk, keyAuth := mustAccountAndKeyAuthorization(t, "token") + payload, leaf, root := mustAttestYubikey(t, "nonce", keyAuth, 12345678) + + caRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}) + ctx := NewProvisionerContext(context.Background(), mustAttestationProvisioner(t, caRoot)) + + return test{ + args: args{ + ctx: ctx, + jwk: jwk, + ch: &Challenge{ + ID: "chID", + AuthorizationID: "azID", + Token: "token", + Type: "device-attest-01", + Status: StatusPending, + Value: "12345678", + }, + payload: payload, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + assert.Equal(t, "azID", id) + return &Authorization{ID: "azID"}, nil + }, + MockUpdateAuthorization: func(ctx context.Context, az *Authorization) error { + fingerprint, err := keyutil.Fingerprint(leaf.PublicKey) + assert.NoError(t, err) + assert.Equal(t, "azID", az.ID) + assert.Equal(t, fingerprint, az.Fingerprint) + return nil + }, + MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { + assert.Equal(t, "chID", updch.ID) + assert.Equal(t, "token", updch.Token) + assert.Equal(t, StatusValid, updch.Status) + assert.Equal(t, ChallengeType("device-attest-01"), updch.Type) + assert.Equal(t, "12345678", updch.Value) + + return nil + }, + }, + }, + wantErr: nil, + } + }, + } + for name, run := range tests { + t.Run(name, func(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()) + return + } + + assert.Nil(t, tc.wantErr) + }) + } +} diff --git a/acme/db/nosql/authz.go b/acme/db/nosql/authz.go index 01cb7fed..d63aa89e 100644 --- a/acme/db/nosql/authz.go +++ b/acme/db/nosql/authz.go @@ -17,6 +17,7 @@ type dbAuthz struct { Identifier acme.Identifier `json:"identifier"` Status acme.Status `json:"status"` Token string `json:"token"` + Fingerprint string `json:"fingerprint,omitempty"` ChallengeIDs []string `json:"challengeIDs"` Wildcard bool `json:"wildcard"` CreatedAt time.Time `json:"createdAt"` @@ -61,15 +62,16 @@ func (db *DB) GetAuthorization(ctx context.Context, id string) (*acme.Authorizat } } return &acme.Authorization{ - ID: dbaz.ID, - AccountID: dbaz.AccountID, - Identifier: dbaz.Identifier, - Status: dbaz.Status, - Challenges: chs, - Wildcard: dbaz.Wildcard, - ExpiresAt: dbaz.ExpiresAt, - Token: dbaz.Token, - Error: dbaz.Error, + ID: dbaz.ID, + AccountID: dbaz.AccountID, + Identifier: dbaz.Identifier, + Status: dbaz.Status, + Challenges: chs, + Wildcard: dbaz.Wildcard, + ExpiresAt: dbaz.ExpiresAt, + Token: dbaz.Token, + Fingerprint: dbaz.Fingerprint, + Error: dbaz.Error, }, nil } @@ -97,6 +99,7 @@ func (db *DB) CreateAuthorization(ctx context.Context, az *acme.Authorization) e Identifier: az.Identifier, ChallengeIDs: chIDs, Token: az.Token, + Fingerprint: az.Fingerprint, Wildcard: az.Wildcard, } @@ -111,8 +114,8 @@ func (db *DB) UpdateAuthorization(ctx context.Context, az *acme.Authorization) e } nu := old.clone() - nu.Status = az.Status + nu.Fingerprint = az.Fingerprint nu.Error = az.Error return db.save(ctx, old.ID, nu, old, "authz", authzTable) } @@ -136,15 +139,16 @@ func (db *DB) GetAuthorizationsByAccountID(ctx context.Context, accountID string continue } authzs = append(authzs, &acme.Authorization{ - ID: dbaz.ID, - AccountID: dbaz.AccountID, - Identifier: dbaz.Identifier, - Status: dbaz.Status, - Challenges: nil, // challenges not required for current use case - Wildcard: dbaz.Wildcard, - ExpiresAt: dbaz.ExpiresAt, - Token: dbaz.Token, - Error: dbaz.Error, + ID: dbaz.ID, + AccountID: dbaz.AccountID, + Identifier: dbaz.Identifier, + Status: dbaz.Status, + Challenges: nil, // challenges not required for current use case + Wildcard: dbaz.Wildcard, + ExpiresAt: dbaz.ExpiresAt, + Token: dbaz.Token, + Fingerprint: dbaz.Fingerprint, + Error: dbaz.Error, }) } diff --git a/acme/db/nosql/authz_test.go b/acme/db/nosql/authz_test.go index c7d47eda..6bc2b94d 100644 --- a/acme/db/nosql/authz_test.go +++ b/acme/db/nosql/authz_test.go @@ -473,6 +473,7 @@ func TestDB_UpdateAuthorization(t *testing.T) { ExpiresAt: now.Add(5 * time.Minute), ChallengeIDs: []string{"foo", "bar"}, Wildcard: true, + Fingerprint: "fingerprint", } b, err := json.Marshal(dbaz) assert.FatalError(t, err) @@ -549,10 +550,11 @@ func TestDB_UpdateAuthorization(t *testing.T) { {ID: "foo"}, {ID: "bar"}, }, - Token: dbaz.Token, - Wildcard: dbaz.Wildcard, - ExpiresAt: dbaz.ExpiresAt, - Error: acme.NewError(acme.ErrorMalformedType, "malformed"), + Token: dbaz.Token, + Wildcard: dbaz.Wildcard, + ExpiresAt: dbaz.ExpiresAt, + Fingerprint: "fingerprint", + Error: acme.NewError(acme.ErrorMalformedType, "malformed"), } return test{ az: updAz, @@ -582,6 +584,7 @@ func TestDB_UpdateAuthorization(t *testing.T) { assert.Equals(t, dbNew.Wildcard, dbaz.Wildcard) assert.Equals(t, dbNew.CreatedAt, dbaz.CreatedAt) assert.Equals(t, dbNew.ExpiresAt, dbaz.ExpiresAt) + assert.Equals(t, dbNew.Fingerprint, dbaz.Fingerprint) assert.Equals(t, dbNew.Error.Error(), acme.NewError(acme.ErrorMalformedType, "The request message was malformed").Error()) return nu, true, nil }, diff --git a/acme/db/nosql/challenge.go b/acme/db/nosql/challenge.go index f84a6f4e..c9224574 100644 --- a/acme/db/nosql/challenge.go +++ b/acme/db/nosql/challenge.go @@ -6,8 +6,10 @@ import ( "time" "github.com/pkg/errors" - "github.com/smallstep/certificates/acme" + "github.com/smallstep/nosql" + + "github.com/smallstep/certificates/acme" ) type dbChallenge struct { @@ -19,7 +21,7 @@ type dbChallenge struct { Value string `json:"value"` ValidatedAt string `json:"validatedAt"` CreatedAt time.Time `json:"createdAt"` - Error *acme.Error `json:"error"` + Error *acme.Error `json:"error"` // TODO(hs): a bit dangerous; should become db-specific type } func (dbc *dbChallenge) clone() *dbChallenge { diff --git a/acme/errors.go b/acme/errors.go index a969bd96..44f367a0 100644 --- a/acme/errors.go +++ b/acme/errors.go @@ -270,14 +270,34 @@ var ( } ) -// Error represents an ACME +// Error represents an ACME Error type Error struct { - Type string `json:"type"` - Detail string `json:"detail"` - Subproblems []interface{} `json:"subproblems,omitempty"` - Identifier interface{} `json:"identifier,omitempty"` - Err error `json:"-"` - Status int `json:"-"` + Type string `json:"type"` + Detail string `json:"detail"` + Subproblems []Subproblem `json:"subproblems,omitempty"` + Err error `json:"-"` + Status int `json:"-"` +} + +// Subproblem represents an ACME subproblem. It's fairly +// similar to an ACME error, but differs in that it can't +// include subproblems itself, the error is reflected +// in the Detail property and doesn't have a Status. +type Subproblem struct { + Type string `json:"type"` + Detail string `json:"detail"` + // The "identifier" field MUST NOT be present at the top level in ACME + // problem documents. It can only be present in subproblems. + // Subproblems need not all have the same type, and they do not need to + // match the top level type. + Identifier *Identifier `json:"identifier,omitempty"` +} + +// 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 } // NewError creates a new Error type. @@ -285,6 +305,26 @@ func NewError(pt ProblemType, msg string, args ...interface{}) *Error { return newError(pt, errors.Errorf(msg, args...)) } +// 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. +func NewSubproblem(pt ProblemType, msg string, args ...interface{}) Subproblem { + e := newError(pt, fmt.Errorf(msg, args...)) + s := Subproblem{ + Type: e.Type, + Detail: e.Err.Error(), + } + return s +} + +// NewSubproblemWithIdentifier creates a new Subproblem with a specific ACME +// Identifier. It calls NewSubproblem and sets the Identifier. +func NewSubproblemWithIdentifier(pt ProblemType, identifier Identifier, msg string, args ...interface{}) Subproblem { + s := NewSubproblem(pt, msg, args...) + s.Identifier = &identifier + return s +} + func newError(pt ProblemType, err error) *Error { meta, ok := errorMap[pt] if !ok { diff --git a/acme/order.go b/acme/order.go index 7748df22..8dfcf97a 100644 --- a/acme/order.go +++ b/acme/order.go @@ -3,6 +3,7 @@ package acme import ( "bytes" "context" + "crypto/subtle" "crypto/x509" "encoding/json" "net" @@ -11,6 +12,7 @@ import ( "time" "github.com/smallstep/certificates/authority/provisioner" + "go.step.sm/crypto/keyutil" "go.step.sm/crypto/x509util" ) @@ -125,6 +127,27 @@ func (o *Order) UpdateStatus(ctx context.Context, db DB) error { return nil } +// getKeyFingerprint returns a fingerprint from the list of authorizations. This +// fingerprint is used on the device-attest-01 flow to verify the attestation +// certificate public key with the CSR public key. +// +// There's no point on reading all the authorizations as there will be only one +// for a permanent identifier. +func (o *Order) getAuthorizationFingerprint(ctx context.Context, db DB) (string, error) { + for _, azID := range o.AuthorizationIDs { + az, err := db.GetAuthorization(ctx, azID) + if err != nil { + return "", WrapErrorISE(err, "error getting authorization %q", azID) + } + // There's no point on reading all the authorizations as there will + // be only one for a permanent identifier. + if az.Fingerprint != "" { + return az.Fingerprint, nil + } + } + return "", nil +} + // Finalize signs a certificate if the necessary conditions for Order completion // have been met. // @@ -150,6 +173,24 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques return NewErrorISE("unexpected status %s for order %s", o.Status, o.ID) } + // Get key fingerprint if any. And then compare it with the CSR fingerprint. + // + // In device-attest-01 challenges we should check that the keys in the CSR + // and the attestation certificate are the same. + fingerprint, err := o.getAuthorizationFingerprint(ctx, db) + if err != nil { + return err + } + if fingerprint != "" { + fp, err := keyutil.Fingerprint(csr.PublicKey) + if err != nil { + return WrapErrorISE(err, "error calculating key fingerprint") + } + if subtle.ConstantTimeCompare([]byte(fingerprint), []byte(fp)) == 0 { + return NewError(ErrorUnauthorizedType, "order %s csr does not match the attested key", o.ID) + } + } + // canonicalize the CSR to allow for comparison csr = canonicalize(csr) @@ -165,6 +206,15 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques for i := range o.Identifiers { if o.Identifiers[i].Type == PermanentIdentifier { permanentIdentifier = o.Identifiers[i].Value + // the first (and only) Permanent Identifier that gets added to the certificate + // should be equal to the Subject Common Name if it's set. If not equal, the CSR + // is rejected, because the Common Name hasn't been challenged in that case. This + // could result in unauthorized access if a relying system relies on the Common + // Name in its authorization logic. + if csr.Subject.CommonName != "" && csr.Subject.CommonName != permanentIdentifier { + return NewError(ErrorBadCSRType, "CSR Subject Common Name does not match identifiers exactly: "+ + "CSR Subject Common Name = %s, Order Permanent Identifier = %s", csr.Subject.CommonName, permanentIdentifier) + } break } } diff --git a/acme/order_test.go b/acme/order_test.go index 606e9f71..b8018c7b 100644 --- a/acme/order_test.go +++ b/acme/order_test.go @@ -2,9 +2,12 @@ package acme import ( "context" + "crypto" "crypto/x509" "crypto/x509/pkix" + "encoding/asn1" "encoding/json" + "fmt" "net" "net/url" "reflect" @@ -16,6 +19,7 @@ import ( "github.com/smallstep/assert" "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/provisioner" + "go.step.sm/crypto/keyutil" "go.step.sm/crypto/x509util" ) @@ -306,6 +310,14 @@ func (m *mockSignAuth) Revoke(context.Context, *authority.RevokeOptions) error { } func TestOrder_Finalize(t *testing.T) { + mustSigner := func(kty, crv string, size int) crypto.Signer { + s, err := keyutil.GenerateSigner(kty, crv, size) + if err != nil { + t.Fatal(err) + } + return s + } + type test struct { o *Order err *Error @@ -386,6 +398,72 @@ func TestOrder_Finalize(t *testing.T) { err: NewErrorISE("unrecognized order status: %s", o.Status), } }, + "fail/non-matching-permanent-identifier-common-name": func(t *testing.T) test { + now := clock.Now() + o := &Order{ + ID: "oID", + AccountID: "accID", + Status: StatusReady, + ExpiresAt: now.Add(5 * time.Minute), + AuthorizationIDs: []string{"a", "b"}, + Identifiers: []Identifier{ + {Type: "permanent-identifier", Value: "a-permanent-identifier"}, + }, + } + + signer := mustSigner("EC", "P-256", 0) + fingerprint, err := keyutil.Fingerprint(signer.Public()) + if err != nil { + t.Fatal(err) + } + + csr := &x509.CertificateRequest{ + Subject: pkix.Name{ + CommonName: "a-different-identifier", + }, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + { + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3}, + Value: []byte("a-permanent-identifier"), + }, + }, + } + return test{ + o: o, + csr: csr, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + switch id { + case "a": + return &Authorization{ + ID: id, + Status: StatusValid, + }, nil + case "b": + return &Authorization{ + ID: id, + Fingerprint: fingerprint, + Status: StatusValid, + }, nil + default: + assert.FatalError(t, errors.Errorf("unexpected authorization %s", id)) + return nil, errors.New("force") + } + }, + MockUpdateOrder: func(ctx context.Context, o *Order) error { + return nil + }, + }, + err: &Error{ + Type: "urn:ietf:params:acme:error:badCSR", + Detail: "The CSR is unacceptable", + Status: 400, + Err: fmt.Errorf("CSR Subject Common Name does not match identifiers exactly: "+ + "CSR Subject Common Name = %s, Order Permanent Identifier = %s", csr.Subject.CommonName, "a-permanent-identifier"), + }, + } + }, "fail/error-provisioner-auth": func(t *testing.T) test { now := clock.Now() o := &Order{ @@ -415,6 +493,11 @@ func TestOrder_Finalize(t *testing.T) { return nil, errors.New("force") }, }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, + }, err: NewErrorISE("error retrieving authorization options from ACME provisioner: force"), } }, @@ -454,6 +537,11 @@ func TestOrder_Finalize(t *testing.T) { } }, }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, + }, err: NewErrorISE("error creating template options from ACME provisioner: error unmarshaling template data: invalid character 'o' in literal false (expecting 'a')"), } }, @@ -495,6 +583,11 @@ func TestOrder_Finalize(t *testing.T) { return nil, errors.New("force") }, }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, + }, err: NewErrorISE("error signing certificate for order oID: force"), } }, @@ -541,6 +634,9 @@ func TestOrder_Finalize(t *testing.T) { }, }, db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { assert.Equals(t, cert.AccountID, o.AccountID) assert.Equals(t, cert.OrderID, o.ID) @@ -595,6 +691,9 @@ func TestOrder_Finalize(t *testing.T) { }, }, db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { cert.ID = "certID" assert.Equals(t, cert.AccountID, o.AccountID) @@ -617,6 +716,297 @@ func TestOrder_Finalize(t *testing.T) { err: NewErrorISE("error updating order oID: force"), } }, + "fail/csr-fingerprint": func(t *testing.T) test { + now := clock.Now() + o := &Order{ + ID: "oID", + AccountID: "accID", + Status: StatusReady, + ExpiresAt: now.Add(5 * time.Minute), + AuthorizationIDs: []string{"a", "b"}, + Identifiers: []Identifier{ + {Type: "permanent-identifier", Value: "a-permanent-identifier"}, + }, + } + + signer := mustSigner("EC", "P-256", 0) + + csr := &x509.CertificateRequest{ + Subject: pkix.Name{ + CommonName: "a-permanent-identifier", + }, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + { + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3}, + Value: []byte("a-permanent-identifier"), + }, + }, + } + + leaf := &x509.Certificate{ + Subject: pkix.Name{CommonName: "a-permanent-identifier"}, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + { + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3}, + Value: []byte("a-permanent-identifier"), + }, + }, + } + inter := &x509.Certificate{Subject: pkix.Name{CommonName: "inter"}} + root := &x509.Certificate{Subject: pkix.Name{CommonName: "root"}} + + return test{ + o: o, + csr: csr, + prov: &MockProvisioner{ + MauthorizeSign: func(ctx context.Context, token string) ([]provisioner.SignOption, error) { + assert.Equals(t, token, "") + return nil, nil + }, + MgetOptions: func() *provisioner.Options { + return nil + }, + }, + ca: &mockSignAuth{ + sign: func(_csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { + assert.Equals(t, _csr, csr) + return []*x509.Certificate{leaf, inter, root}, nil + }, + }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ + ID: id, + Fingerprint: "other-fingerprint", + Status: StatusValid, + }, nil + }, + MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { + cert.ID = "certID" + assert.Equals(t, cert.AccountID, o.AccountID) + assert.Equals(t, cert.OrderID, o.ID) + assert.Equals(t, cert.Leaf, leaf) + assert.Equals(t, cert.Intermediates, []*x509.Certificate{inter, root}) + return nil + }, + MockUpdateOrder: func(ctx context.Context, updo *Order) error { + assert.Equals(t, updo.CertificateID, "certID") + assert.Equals(t, updo.Status, StatusValid) + assert.Equals(t, updo.ID, o.ID) + assert.Equals(t, updo.AccountID, o.AccountID) + assert.Equals(t, updo.ExpiresAt, o.ExpiresAt) + assert.Equals(t, updo.AuthorizationIDs, o.AuthorizationIDs) + assert.Equals(t, updo.Identifiers, o.Identifiers) + return nil + }, + }, + err: NewError(ErrorUnauthorizedType, "order oID csr does not match the attested key"), + } + }, + "ok/permanent-identifier": func(t *testing.T) test { + now := clock.Now() + o := &Order{ + ID: "oID", + AccountID: "accID", + Status: StatusReady, + ExpiresAt: now.Add(5 * time.Minute), + AuthorizationIDs: []string{"a", "b"}, + Identifiers: []Identifier{ + {Type: "permanent-identifier", Value: "a-permanent-identifier"}, + }, + } + + signer := mustSigner("EC", "P-256", 0) + fingerprint, err := keyutil.Fingerprint(signer.Public()) + if err != nil { + t.Fatal(err) + } + + csr := &x509.CertificateRequest{ + Subject: pkix.Name{ + CommonName: "a-permanent-identifier", + }, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + { + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3}, + Value: []byte("a-permanent-identifier"), + }, + }, + } + + leaf := &x509.Certificate{ + Subject: pkix.Name{CommonName: "a-permanent-identifier"}, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + { + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3}, + Value: []byte("a-permanent-identifier"), + }, + }, + } + inter := &x509.Certificate{Subject: pkix.Name{CommonName: "inter"}} + root := &x509.Certificate{Subject: pkix.Name{CommonName: "root"}} + + return test{ + o: o, + csr: csr, + prov: &MockProvisioner{ + MauthorizeSign: func(ctx context.Context, token string) ([]provisioner.SignOption, error) { + assert.Equals(t, token, "") + return nil, nil + }, + MgetOptions: func() *provisioner.Options { + return nil + }, + }, + ca: &mockSignAuth{ + sign: func(_csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { + assert.Equals(t, _csr, csr) + return []*x509.Certificate{leaf, inter, root}, nil + }, + }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + switch id { + case "a": + return &Authorization{ + ID: id, + Status: StatusValid, + }, nil + case "b": + return &Authorization{ + ID: id, + Fingerprint: fingerprint, + Status: StatusValid, + }, nil + default: + assert.FatalError(t, errors.Errorf("unexpected authorization %s", id)) + return nil, errors.New("force") + } + }, + MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { + cert.ID = "certID" + assert.Equals(t, cert.AccountID, o.AccountID) + assert.Equals(t, cert.OrderID, o.ID) + assert.Equals(t, cert.Leaf, leaf) + assert.Equals(t, cert.Intermediates, []*x509.Certificate{inter, root}) + return nil + }, + MockUpdateOrder: func(ctx context.Context, updo *Order) error { + assert.Equals(t, updo.CertificateID, "certID") + assert.Equals(t, updo.Status, StatusValid) + assert.Equals(t, updo.ID, o.ID) + assert.Equals(t, updo.AccountID, o.AccountID) + assert.Equals(t, updo.ExpiresAt, o.ExpiresAt) + assert.Equals(t, updo.AuthorizationIDs, o.AuthorizationIDs) + assert.Equals(t, updo.Identifiers, o.Identifiers) + return nil + }, + }, + } + }, + "ok/permanent-identifier-only": func(t *testing.T) test { + now := clock.Now() + o := &Order{ + ID: "oID", + AccountID: "accID", + Status: StatusReady, + ExpiresAt: now.Add(5 * time.Minute), + AuthorizationIDs: []string{"a", "b"}, + Identifiers: []Identifier{ + {Type: "dns", Value: "foo.internal"}, + {Type: "permanent-identifier", Value: "a-permanent-identifier"}, + }, + } + + signer := mustSigner("EC", "P-256", 0) + fingerprint, err := keyutil.Fingerprint(signer.Public()) + if err != nil { + t.Fatal(err) + } + + csr := &x509.CertificateRequest{ + Subject: pkix.Name{ + CommonName: "a-permanent-identifier", + }, + DNSNames: []string{"foo.internal"}, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + { + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3}, + Value: []byte("a-permanent-identifier"), + }, + }, + } + + leaf := &x509.Certificate{ + Subject: pkix.Name{CommonName: "a-permanent-identifier"}, + PublicKey: signer.Public(), + ExtraExtensions: []pkix.Extension{ + { + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 8, 3}, + Value: []byte("a-permanent-identifier"), + }, + }, + } + inter := &x509.Certificate{Subject: pkix.Name{CommonName: "inter"}} + root := &x509.Certificate{Subject: pkix.Name{CommonName: "root"}} + + return test{ + o: o, + csr: csr, + prov: &MockProvisioner{ + MauthorizeSign: func(ctx context.Context, token string) ([]provisioner.SignOption, error) { + assert.Equals(t, token, "") + return nil, nil + }, + MgetOptions: func() *provisioner.Options { + return nil + }, + }, + // TODO(hs): we should work on making the mocks more realistic. Ideally, we should get rid of + // the mock entirely, relying on an instances of provisioner, authority and DB (possibly hardest), so + // that behavior of the tests is what an actual CA would do. We could gradually phase them out by + // using the mocking functions as a wrapper for actual test helpers generated per test case or per + // function that's tested. + ca: &mockSignAuth{ + sign: func(_csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { + assert.Equals(t, _csr, csr) + return []*x509.Certificate{leaf, inter, root}, nil + }, + }, + db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ + ID: id, + Fingerprint: fingerprint, + Status: StatusValid, + }, nil + }, + MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { + cert.ID = "certID" + assert.Equals(t, cert.AccountID, o.AccountID) + assert.Equals(t, cert.OrderID, o.ID) + assert.Equals(t, cert.Leaf, leaf) + assert.Equals(t, cert.Intermediates, []*x509.Certificate{inter, root}) + return nil + }, + MockUpdateOrder: func(ctx context.Context, updo *Order) error { + assert.Equals(t, updo.CertificateID, "certID") + assert.Equals(t, updo.Status, StatusValid) + assert.Equals(t, updo.ID, o.ID) + assert.Equals(t, updo.AccountID, o.AccountID) + assert.Equals(t, updo.ExpiresAt, o.ExpiresAt) + assert.Equals(t, updo.AuthorizationIDs, o.AuthorizationIDs) + assert.Equals(t, updo.Identifiers, o.Identifiers) + return nil + }, + }, + } + }, "ok/new-cert-dns": func(t *testing.T) test { now := clock.Now() o := &Order{ @@ -660,6 +1050,9 @@ func TestOrder_Finalize(t *testing.T) { }, }, db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { cert.ID = "certID" assert.Equals(t, cert.AccountID, o.AccountID) @@ -721,6 +1114,9 @@ func TestOrder_Finalize(t *testing.T) { }, }, db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { cert.ID = "certID" assert.Equals(t, cert.AccountID, o.AccountID) @@ -785,6 +1181,9 @@ func TestOrder_Finalize(t *testing.T) { }, }, db: &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, MockCreateCertificate: func(ctx context.Context, cert *Certificate) error { cert.ID = "certID" assert.Equals(t, cert.AccountID, o.AccountID) @@ -1492,3 +1891,55 @@ func TestOrder_sans(t *testing.T) { }) } } + +func TestOrder_getAuthorizationFingerprint(t *testing.T) { + ctx := context.Background() + type fields struct { + AuthorizationIDs []string + } + type args struct { + ctx context.Context + db DB + } + tests := []struct { + name string + fields fields + args args + want string + wantErr bool + }{ + {"ok", fields{[]string{"az1", "az2"}}, args{ctx, &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return &Authorization{ID: id, Status: StatusValid}, nil + }, + }}, "", false}, + {"ok fingerprint", fields{[]string{"az1", "az2"}}, args{ctx, &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + if id == "az1" { + return &Authorization{ID: id, Status: StatusValid}, nil + } + return &Authorization{ID: id, Fingerprint: "fingerprint", Status: StatusValid}, nil + }, + }}, "fingerprint", false}, + {"fail", fields{[]string{"az1", "az2"}}, args{ctx, &MockDB{ + MockGetAuthorization: func(ctx context.Context, id string) (*Authorization, error) { + return nil, errors.New("force") + }, + }}, "", true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &Order{ + AuthorizationIDs: tt.fields.AuthorizationIDs, + } + got, err := o.getAuthorizationFingerprint(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("Order.getAuthorizationFingerprint() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Order.getAuthorizationFingerprint() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/authority/policy.go b/authority/policy.go index d3078e10..38a57bec 100644 --- a/authority/policy.go +++ b/authority/policy.go @@ -248,7 +248,7 @@ func isAllowed(engine authPolicy.X509Policy, sans []string) error { if isNamePolicyError && policyErr.Reason == policy.NotAllowed { return &PolicyError{ Typ: AdminLockOut, - Err: fmt.Errorf("the provided policy would lock out %s from the CA. Please update your policy to include %s as an allowed name", sans, sans), + Err: fmt.Errorf("the provided policy would lock out %s from the CA. Please create an x509 policy to include %s as an allowed DNS name", sans, sans), } } return &PolicyError{ diff --git a/authority/policy_test.go b/authority/policy_test.go index 8e2e0df4..672ca489 100644 --- a/authority/policy_test.go +++ b/authority/policy_test.go @@ -80,7 +80,7 @@ func TestAuthority_checkPolicy(t *testing.T) { }, err: &PolicyError{ Typ: AdminLockOut, - Err: errors.New("the provided policy would lock out [step] from the CA. Please update your policy to include [step] as an allowed name"), + Err: errors.New("the provided policy would lock out [step] from the CA. Please create an x509 policy to include [step] as an allowed DNS name"), }, } }, @@ -127,7 +127,7 @@ func TestAuthority_checkPolicy(t *testing.T) { }, err: &PolicyError{ Typ: AdminLockOut, - Err: errors.New("the provided policy would lock out [otherAdmin] from the CA. Please update your policy to include [otherAdmin] as an allowed name"), + Err: errors.New("the provided policy would lock out [otherAdmin] from the CA. Please create an x509 policy to include [otherAdmin] as an allowed DNS name"), }, } }, diff --git a/authority/provisioner/oidc.go b/authority/provisioner/oidc.go index ad1e5174..01881de6 100644 --- a/authority/provisioner/oidc.go +++ b/authority/provisioner/oidc.go @@ -230,7 +230,7 @@ func (o *OIDC) ValidatePayload(p openIDPayload) error { } } if !found { - return errs.Unauthorized("validatePayload: failed to validate oidc token payload: email is not allowed") + return errs.Unauthorized("validatePayload: failed to validate oidc token payload: email %q is not allowed", p.Email) } } diff --git a/authority/provisioner/oidc_test.go b/authority/provisioner/oidc_test.go index ebd8e5a4..913c8a2b 100644 --- a/authority/provisioner/oidc_test.go +++ b/authority/provisioner/oidc_test.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" "go.step.sm/crypto/jose" "github.com/smallstep/assert" @@ -221,39 +222,37 @@ func TestOIDC_authorizeToken(t *testing.T) { args args code int wantIssuer string - wantErr bool + expErr error }{ - {"ok1", p1, args{t1}, http.StatusOK, issuer, false}, - {"ok tenantid", p2, args{t2}, http.StatusOK, tenantIssuer, false}, - {"ok admin", p3, args{t3}, http.StatusOK, issuer, false}, - {"ok domain", p3, args{t4}, http.StatusOK, issuer, false}, - {"ok no email", p3, args{t5}, http.StatusOK, issuer, false}, - {"fail-domain", p3, args{failDomain}, http.StatusUnauthorized, "", true}, - {"fail-key", p1, args{failKey}, http.StatusUnauthorized, "", true}, - {"fail-token", p1, args{failTok}, http.StatusUnauthorized, "", true}, - {"fail-claims", p1, args{failClaims}, http.StatusUnauthorized, "", true}, - {"fail-issuer", p1, args{failIss}, http.StatusUnauthorized, "", true}, - {"fail-audience", p1, args{failAud}, http.StatusUnauthorized, "", true}, - {"fail-signature", p1, args{failSig}, http.StatusUnauthorized, "", true}, - {"fail-expired", p1, args{failExp}, http.StatusUnauthorized, "", true}, - {"fail-not-before", p1, args{failNbf}, http.StatusUnauthorized, "", true}, + {"ok1", p1, args{t1}, http.StatusOK, issuer, nil}, + {"ok tenantid", p2, args{t2}, http.StatusOK, tenantIssuer, nil}, + {"ok admin", p3, args{t3}, http.StatusOK, issuer, nil}, + {"ok domain", p3, args{t4}, http.StatusOK, issuer, nil}, + {"ok no email", p3, args{t5}, http.StatusOK, issuer, nil}, + {"fail-domain", p3, args{failDomain}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken: validatePayload: failed to validate oidc token payload: email "name@example.com" is not allowed`)}, + {"fail-key", p1, args{failKey}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken; cannot validate oidc token`)}, + {"fail-token", p1, args{failTok}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken; error parsing oidc token: invalid character '~' looking for beginning of value`)}, + {"fail-claims", p1, args{failClaims}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken; error parsing oidc token claims: invalid character '~' looking for beginning of value`)}, + {"fail-issuer", p1, args{failIss}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken: validatePayload: failed to validate oidc token payload: square/go-jose/jwt: validation failed, invalid issuer claim (iss)`)}, + {"fail-audience", p1, args{failAud}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken: validatePayload: failed to validate oidc token payload: square/go-jose/jwt: validation failed, invalid audience claim (aud)`)}, + {"fail-signature", p1, args{failSig}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken; cannot validate oidc token`)}, + {"fail-expired", p1, args{failExp}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken: validatePayload: failed to validate oidc token payload: square/go-jose/jwt: validation failed, token is expired (exp)`)}, + {"fail-not-before", p1, args{failNbf}, http.StatusUnauthorized, "", errors.New(`oidc.AuthorizeToken: validatePayload: failed to validate oidc token payload: square/go-jose/jwt: validation failed, token not valid yet (nbf)`)}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := tt.prov.authorizeToken(tt.args.token) - if (err != nil) != tt.wantErr { - fmt.Println(tt) - t.Errorf("OIDC.Authorize() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil { + if tt.expErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.expErr.Error()) + var sc render.StatusCodedError - assert.Fatal(t, errors.As(err, &sc), "error does not implement StatusCodedError interface") - assert.Equals(t, sc.StatusCode(), tt.code) - assert.Nil(t, got) + require.ErrorAs(t, err, &sc, "error does not implement StatusCodedError interface") + require.Equal(t, tt.code, sc.StatusCode()) + require.Nil(t, got) } else { - assert.NotNil(t, got) - assert.Equals(t, got.Issuer, tt.wantIssuer) + require.NotNil(t, got) + require.Equal(t, tt.wantIssuer, got.Issuer) } }) } diff --git a/authority/tls.go b/authority/tls.go index e64bb5fa..b7531ce3 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -786,7 +786,7 @@ func (a *Authority) GenerateCertificateRevocationList() error { // Note that this is currently using the port 443 by default. if b, err := marshalDistributionPoint(fullName, false); err == nil { revocationList.ExtraExtensions = []pkix.Extension{ - {Id: oidExtensionIssuingDistributionPoint, Value: b}, + {Id: oidExtensionIssuingDistributionPoint, Critical: true, Value: b}, } } diff --git a/ca/ca.go b/ca/ca.go index 880f7e46..33f81200 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -13,6 +13,7 @@ import ( "reflect" "strings" "sync" + "time" "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" @@ -126,13 +127,15 @@ type CA struct { insecureSrv *server.Server opts *options renewer *TLSRenewer + compactStop chan struct{} } // New creates and initializes the CA with the given configuration and options. func New(cfg *config.Config, opts ...Option) (*CA, error) { ca := &CA{ - config: cfg, - opts: new(options), + config: cfg, + opts: new(options), + compactStop: make(chan struct{}), } ca.opts.apply(opts) return ca.Init(cfg) @@ -370,6 +373,12 @@ func (ca *CA) Run() error { } } + wg.Add(1) + go func() { + defer wg.Done() + ca.runCompactJob() + }() + if ca.insecureSrv != nil { wg.Add(1) go func() { @@ -394,6 +403,7 @@ func (ca *CA) Run() error { // Stop stops the CA calling to the server Shutdown method. func (ca *CA) Stop() error { + close(ca.compactStop) ca.renewer.Stop() if err := ca.auth.Shutdown(); err != nil { log.Printf("error stopping ca.Authority: %+v\n", err) @@ -576,3 +586,39 @@ func (ca *CA) getConfigFileOutput() string { } return "loaded from token" } + +// runCompactJob will run the value log garbage collector if the nosql database +// supports it. +func (ca *CA) runCompactJob() { + caDB, ok := ca.auth.GetDatabase().(*db.DB) + if !ok { + return + } + compactor, ok := caDB.DB.(nosql.Compactor) + if !ok { + return + } + + // Compact database at start. + runCompact(compactor) + + // Compact database every minute. + ticker := time.NewTicker(time.Minute) + defer ticker.Stop() + + for { + select { + case <-ca.compactStop: + return + case <-ticker.C: + runCompact(compactor) + } + } +} + +// runCompact executes the compact job until it returns an error. +func runCompact(c nosql.Compactor) { + for err := error(nil); err == nil; { + err = c.Compact(0.7) + } +} diff --git a/cmd/step-awskms-init/main.go b/cmd/step-awskms-init/main.go deleted file mode 100644 index 81a91067..00000000 --- a/cmd/step-awskms-init/main.go +++ /dev/null @@ -1,248 +0,0 @@ -package main - -import ( - "context" - "crypto" - "crypto/rand" - "crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "flag" - "fmt" - "math/big" - "os" - "time" - - "go.step.sm/cli-utils/fileutil" - "go.step.sm/cli-utils/ui" - "go.step.sm/crypto/kms/apiv1" - "go.step.sm/crypto/kms/awskms" - "go.step.sm/crypto/pemutil" - "golang.org/x/crypto/ssh" -) - -func main() { - var credentialsFile, region string - var enableSSH bool - flag.StringVar(&credentialsFile, "credentials-file", "", "Path to the `file` containing the AWS KMS credentials.") - flag.StringVar(®ion, "region", "", "AWS KMS region name.") - flag.BoolVar(&enableSSH, "ssh", false, "Create SSH keys.") - flag.Usage = usage - flag.Parse() - - // Initialize windows terminal - ui.Init() - - ui.Println("⚠️ This command is deprecated and will be removed in future releases.") - ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.") - - c, err := awskms.New(context.Background(), apiv1.Options{ - Type: apiv1.AmazonKMS, - Region: region, - CredentialsFile: credentialsFile, - }) - if err != nil { - fatal(err) - } - - if err := createX509(c); err != nil { - fatal(err) - } - - if enableSSH { - ui.Println() - if err := createSSH(c); err != nil { - fatal(err) - } - } - - // Reset windows terminal - ui.Reset() -} - -func fatal(err error) { - fmt.Fprintln(os.Stderr, err) - ui.Reset() - os.Exit(1) -} - -func usage() { - fmt.Fprintln(os.Stderr, "Usage: step-awskms-init") - fmt.Fprintln(os.Stderr, ` -The step-awskms-init command initializes a public key infrastructure (PKI) -to be used by step-ca. - -This tool is experimental and in the future it will be integrated in step cli. - -OPTIONS`) - fmt.Fprintln(os.Stderr) - flag.PrintDefaults() - fmt.Fprintf(os.Stderr, ` -COPYRIGHT - - (c) 2018-%d Smallstep Labs, Inc. -`, time.Now().Year()) - os.Exit(1) -} - -func createX509(c *awskms.KMS) error { - ui.Println("Creating X.509 PKI ...") - - // Root Certificate - resp, err := c.CreateKey(&apiv1.CreateKeyRequest{ - Name: "root", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - - signer, err := c.CreateSigner(&resp.CreateSignerRequest) - if err != nil { - return err - } - - now := time.Now() - root := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 1, - MaxPathLenZero: false, - Issuer: pkix.Name{CommonName: "Smallstep Root"}, - Subject: pkix.Name{CommonName: "Smallstep Root"}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(resp.PublicKey), - AuthorityKeyId: mustSubjectKeyID(resp.PublicKey), - } - - b, err := x509.CreateCertificate(rand.Reader, root, root, resp.PublicKey, signer) - if err != nil { - return err - } - - if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - - ui.PrintSelected("Root Key", resp.Name) - ui.PrintSelected("Root Certificate", "root_ca.crt") - - root, err = pemutil.ReadCertificate("root_ca.crt") - if err != nil { - return err - } - - // Intermediate Certificate - resp, err = c.CreateKey(&apiv1.CreateKeyRequest{ - Name: "intermediate", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - - intermediate := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 0, - MaxPathLenZero: true, - Issuer: root.Subject, - Subject: pkix.Name{CommonName: "Smallstep Intermediate"}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(resp.PublicKey), - } - - b, err = x509.CreateCertificate(rand.Reader, intermediate, root, resp.PublicKey, signer) - if err != nil { - return err - } - - if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - - ui.PrintSelected("Intermediate Key", resp.Name) - ui.PrintSelected("Intermediate Certificate", "intermediate_ca.crt") - - return nil -} - -func createSSH(c *awskms.KMS) error { - ui.Println("Creating SSH Keys ...") - - // User Key - resp, err := c.CreateKey(&apiv1.CreateKeyRequest{ - Name: "ssh-user-key", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - - key, err := ssh.NewPublicKey(resp.PublicKey) - if err != nil { - return err - } - - if err := fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { - return err - } - - ui.PrintSelected("SSH User Public Key", "ssh_user_ca_key.pub") - ui.PrintSelected("SSH User Private Key", resp.Name) - - // Host Key - resp, err = c.CreateKey(&apiv1.CreateKeyRequest{ - Name: "ssh-host-key", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - - key, err = ssh.NewPublicKey(resp.PublicKey) - if err != nil { - return err - } - - if err := fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { - return err - } - - ui.PrintSelected("SSH Host Public Key", "ssh_host_ca_key.pub") - ui.PrintSelected("SSH Host Private Key", resp.Name) - - return nil -} - -func mustSerialNumber() *big.Int { - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - sn, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - panic(err) - } - return sn -} - -func mustSubjectKeyID(key crypto.PublicKey) []byte { - b, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - panic(err) - } - //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - hash := sha1.Sum(b) - return hash[:] -} diff --git a/cmd/step-cloudkms-init/main.go b/cmd/step-cloudkms-init/main.go deleted file mode 100644 index 6cc36adf..00000000 --- a/cmd/step-cloudkms-init/main.go +++ /dev/null @@ -1,286 +0,0 @@ -package main - -import ( - "context" - "crypto" - "crypto/rand" - "crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "flag" - "fmt" - "math/big" - "os" - "strings" - "time" - - "go.step.sm/cli-utils/fileutil" - "go.step.sm/cli-utils/ui" - "go.step.sm/crypto/kms/apiv1" - "go.step.sm/crypto/kms/cloudkms" - "go.step.sm/crypto/pemutil" - "golang.org/x/crypto/ssh" -) - -func main() { - var credentialsFile string - var project, location, ring string - var protectionLevelName string - var enableSSH bool - flag.StringVar(&credentialsFile, "credentials-file", "", "Path to the `file` containing the Google's Cloud KMS credentials.") - flag.StringVar(&project, "project", "", "Google Cloud Project ID.") - flag.StringVar(&location, "location", "global", "Cloud KMS location name.") - flag.StringVar(&ring, "ring", "pki", "Cloud KMS ring name.") - flag.StringVar(&protectionLevelName, "protection-level", "SOFTWARE", "Protection level to use, SOFTWARE or HSM.") - flag.BoolVar(&enableSSH, "ssh", false, "Create SSH keys.") - flag.Usage = usage - flag.Parse() - - switch { - case project == "": - usage() - case location == "": - fmt.Fprintln(os.Stderr, "flag `--location` is required") - os.Exit(1) - case ring == "": - fmt.Fprintln(os.Stderr, "flag `--ring` is required") - os.Exit(1) - case protectionLevelName == "": - fmt.Fprintln(os.Stderr, "flag `--protection-level` is required") - os.Exit(1) - } - - var protectionLevel apiv1.ProtectionLevel - switch strings.ToUpper(protectionLevelName) { - case "SOFTWARE": - protectionLevel = apiv1.Software - case "HSM": - protectionLevel = apiv1.HSM - default: - fmt.Fprintf(os.Stderr, "invalid value `%s` for flag `--protection-level`; options are `SOFTWARE` or `HSM`\n", protectionLevelName) - os.Exit(1) - } - - // Initialize windows terminal - ui.Init() - - ui.Println("⚠️ This command is deprecated and will be removed in future releases.") - ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.") - - c, err := cloudkms.New(context.Background(), apiv1.Options{ - Type: apiv1.CloudKMS, - CredentialsFile: credentialsFile, - }) - if err != nil { - fatal(err) - } - - if err := createPKI(c, project, location, ring, protectionLevel); err != nil { - fatal(err) - } - - if enableSSH { - ui.Println() - if err := createSSH(c, project, location, ring, protectionLevel); err != nil { - fatal(err) - } - } - - // Reset windows terminal - ui.Reset() -} - -func fatal(err error) { - fmt.Fprintln(os.Stderr, err) - ui.Reset() - os.Exit(1) -} - -func usage() { - fmt.Fprintln(os.Stderr, "Usage: step-cloudkms-init --project ") - fmt.Fprintln(os.Stderr, ` -The step-cloudkms-init command initializes a public key infrastructure (PKI) -to be used by step-ca. - -This tool is experimental and in the future it will be integrated in step cli. - -OPTIONS`) - fmt.Fprintln(os.Stderr) - flag.PrintDefaults() - fmt.Fprintf(os.Stderr, ` -COPYRIGHT - - (c) 2018-%d Smallstep Labs, Inc. -`, time.Now().Year()) - os.Exit(1) -} - -func createPKI(c *cloudkms.CloudKMS, project, location, keyRing string, protectionLevel apiv1.ProtectionLevel) error { - ui.Println("Creating PKI ...") - - parent := "projects/" + project + "/locations/" + location + "/keyRings/" + keyRing + "/cryptoKeys" - - // Root Certificate - resp, err := c.CreateKey(&apiv1.CreateKeyRequest{ - Name: parent + "/root", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - ProtectionLevel: protectionLevel, - }) - if err != nil { - return err - } - - signer, err := c.CreateSigner(&resp.CreateSignerRequest) - if err != nil { - return err - } - - now := time.Now() - root := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 1, - MaxPathLenZero: false, - Issuer: pkix.Name{CommonName: "Smallstep Root"}, - Subject: pkix.Name{CommonName: "Smallstep Root"}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(resp.PublicKey), - AuthorityKeyId: mustSubjectKeyID(resp.PublicKey), - } - - b, err := x509.CreateCertificate(rand.Reader, root, root, resp.PublicKey, signer) - if err != nil { - return err - } - - if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - - ui.PrintSelected("Root Key", resp.Name) - ui.PrintSelected("Root Certificate", "root_ca.crt") - - root, err = pemutil.ReadCertificate("root_ca.crt") - if err != nil { - return err - } - - // Intermediate Certificate - resp, err = c.CreateKey(&apiv1.CreateKeyRequest{ - Name: parent + "/intermediate", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - ProtectionLevel: protectionLevel, - }) - if err != nil { - return err - } - - intermediate := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 0, - MaxPathLenZero: true, - Issuer: root.Subject, - Subject: pkix.Name{CommonName: "Smallstep Intermediate"}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(resp.PublicKey), - } - - b, err = x509.CreateCertificate(rand.Reader, intermediate, root, resp.PublicKey, signer) - if err != nil { - return err - } - - if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - - ui.PrintSelected("Intermediate Key", resp.Name) - ui.PrintSelected("Intermediate Certificate", "intermediate_ca.crt") - - return nil -} - -func createSSH(c *cloudkms.CloudKMS, project, location, keyRing string, protectionLevel apiv1.ProtectionLevel) error { - ui.Println("Creating SSH Keys ...") - - parent := "projects/" + project + "/locations/" + location + "/keyRings/" + keyRing + "/cryptoKeys" - - // User Key - resp, err := c.CreateKey(&apiv1.CreateKeyRequest{ - Name: parent + "/ssh-user-key", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - ProtectionLevel: protectionLevel, - }) - if err != nil { - return err - } - - key, err := ssh.NewPublicKey(resp.PublicKey) - if err != nil { - return err - } - - if err := fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { - return err - } - - ui.PrintSelected("SSH User Public Key", "ssh_user_ca_key.pub") - ui.PrintSelected("SSH User Private Key", resp.Name) - - // Host Key - resp, err = c.CreateKey(&apiv1.CreateKeyRequest{ - Name: parent + "/ssh-host-key", - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - ProtectionLevel: protectionLevel, - }) - if err != nil { - return err - } - - key, err = ssh.NewPublicKey(resp.PublicKey) - if err != nil { - return err - } - - if err := fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil { - return err - } - - ui.PrintSelected("SSH Host Public Key", "ssh_host_ca_key.pub") - ui.PrintSelected("SSH Host Private Key", resp.Name) - - return nil -} - -func mustSerialNumber() *big.Int { - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - sn, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - panic(err) - } - return sn -} - -func mustSubjectKeyID(key crypto.PublicKey) []byte { - b, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - panic(err) - } - //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - hash := sha1.Sum(b) - return hash[:] -} diff --git a/cmd/step-pkcs11-init/main.go b/cmd/step-pkcs11-init/main.go deleted file mode 100644 index 30258cdd..00000000 --- a/cmd/step-pkcs11-init/main.go +++ /dev/null @@ -1,553 +0,0 @@ -package main - -import ( - "context" - "crypto" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "flag" - "fmt" - "math/big" - "os" - "runtime" - "time" - - "github.com/pkg/errors" - "go.step.sm/cli-utils/fileutil" - "go.step.sm/cli-utils/ui" - "go.step.sm/crypto/kms" - "go.step.sm/crypto/kms/apiv1" - "go.step.sm/crypto/kms/uri" - "go.step.sm/crypto/pemutil" - - // Enable pkcs11. - _ "go.step.sm/crypto/kms/pkcs11" -) - -// Config is a mapping of the cli flags. -type Config struct { - KMS string - GenerateRoot bool - RootObject string - RootKeyObject string - RootSubject string - RootPath string - CrtObject string - CrtPath string - CrtKeyObject string - CrtSubject string - CrtKeyPath string - SSHHostKeyObject string - SSHUserKeyObject string - RootFile string - KeyFile string - Pin string - PinFile string - NoCerts bool - EnableSSH bool - Force bool - Extractable bool -} - -// Validate checks the flags in the config. -func (c *Config) Validate() error { - switch { - case c.KMS == "": - return errors.New("flag `--kms` is required") - case c.CrtPath == "": - return errors.New("flag `--crt-cert-path` is required") - case c.RootFile != "" && c.KeyFile == "": - return errors.New("flag `--root-cert-file` requires flag `--root-key-file`") - case c.KeyFile != "" && c.RootFile == "": - return errors.New("flag `--root-key-file` requires flag `--root-cert-file`") - case c.RootFile == "" && c.RootObject == "": - return errors.New("one of flag `--root-cert-file` or `--root-cert-obj` is required") - case c.KeyFile == "" && c.RootKeyObject == "": - return errors.New("one of flag `--root-key-file` or `--root-key-obj` is required") - case c.CrtKeyPath == "" && c.CrtKeyObject == "": - return errors.New("one of flag `--crt-key-path` or `--crt-key-obj` is required") - case c.RootFile == "" && c.GenerateRoot && c.RootKeyObject == "": - return errors.New("flag `--root-gen` requires flag `--root-key-obj`") - case c.RootFile == "" && c.GenerateRoot && c.RootPath == "": - return errors.New("flag `--root-gen` requires `--root-cert-path`") - case c.Pin != "" && c.PinFile != "": - return errors.New("Only set one of pin and pin-file") - default: - if c.RootFile != "" { - c.GenerateRoot = false - c.RootObject = "" - c.RootKeyObject = "" - } - if c.CrtKeyPath != "" { - c.CrtObject = "" - c.CrtKeyObject = "" - } - if !c.EnableSSH { - c.SSHHostKeyObject = "" - c.SSHUserKeyObject = "" - } - return nil - } -} - -func main() { - var kmsuri string - switch runtime.GOOS { - case "darwin": - kmsuri = "pkcs11:module-path=/usr/local/lib/pkcs11/yubihsm_pkcs11.dylib;token=YubiHSM" - case "linux": - kmsuri = "pkcs11:module-path=/usr/lib/x86_64-linux-gnu/pkcs11/yubihsm_pkcs11.so;token=YubiHSM" - case "windows": - if home, err := os.UserHomeDir(); err == nil { - kmsuri = "pkcs11:module-path=" + home + "\\yubihsm2-sdk\\bin\\yubihsm_pkcs11.dll" + ";token=YubiHSM" - } - } - - var c Config - flag.StringVar(&c.KMS, "kms", kmsuri, "PKCS #11 URI with the module-path and token to connect to the module.") - flag.StringVar(&c.Pin, "pin", "", "PKCS #11 PIN") - flag.StringVar(&c.PinFile, "pin-file", "", "PKCS #11 PIN File") - // Option 1: Generate new root - flag.BoolVar(&c.GenerateRoot, "root-gen", true, "Enable the generation of a root key.") - flag.StringVar(&c.RootSubject, "root-name", "PKCS #11 Smallstep Root", "Subject and Issuer of the root certificate.") - flag.StringVar(&c.RootObject, "root-cert-obj", "pkcs11:id=7330;object=root-cert", "PKCS #11 URI with object id and label to store the root certificate.") - flag.StringVar(&c.RootKeyObject, "root-key-obj", "pkcs11:id=7330;object=root-key", "PKCS #11 URI with object id and label to store the root key.") - // Option 2: Read root from disk and sign intermediate - flag.StringVar(&c.RootFile, "root-cert-file", "", "Path to the root certificate to use.") - flag.StringVar(&c.KeyFile, "root-key-file", "", "Path to the root key to use.") - // Option 3: Generate certificate signing request - flag.StringVar(&c.CrtSubject, "crt-name", "PKCS #11 Smallstep Intermediate", "Subject of the intermediate certificate.") - flag.StringVar(&c.CrtObject, "crt-cert-obj", "pkcs11:id=7331;object=intermediate-cert", "PKCS #11 URI with object id and label to store the intermediate certificate.") - flag.StringVar(&c.CrtKeyObject, "crt-key-obj", "pkcs11:id=7331;object=intermediate-key", "PKCS #11 URI with object id and label to store the intermediate certificate.") - // SSH certificates - flag.BoolVar(&c.EnableSSH, "ssh", false, "Enable the creation of ssh keys.") - flag.StringVar(&c.SSHHostKeyObject, "ssh-host-key", "pkcs11:id=7332;object=ssh-host-key", "PKCS #11 URI with object id and label to store the key used to sign SSH host certificates.") - flag.StringVar(&c.SSHUserKeyObject, "ssh-user-key", "pkcs11:id=7333;object=ssh-user-key", "PKCS #11 URI with object id and label to store the key used to sign SSH user certificates.") - // Output files - flag.StringVar(&c.RootPath, "root-cert-path", "root_ca.crt", "Location to write the root certificate.") - flag.StringVar(&c.CrtPath, "crt-cert-path", "intermediate_ca.crt", "Location to write the intermediate certificate.") - flag.StringVar(&c.CrtKeyPath, "crt-key-path", "", "Location to write the intermediate private key.") - // Others - flag.BoolVar(&c.NoCerts, "no-certs", false, "Do not store certificates in the module.") - flag.BoolVar(&c.Force, "force", false, "Force the delete of previous keys.") - flag.BoolVar(&c.Extractable, "extractable", false, "Allow export of private keys under wrap.") - flag.Usage = usage - flag.Parse() - - if err := c.Validate(); err != nil { - fatal(err) - } - - u, err := uri.ParseWithScheme("pkcs11", c.KMS) - if err != nil { - fatal(err) - } - - // Initialize windows terminal - ui.Init() - - ui.Println("⚠️ This command is deprecated and will be removed in future releases.") - ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.") - - switch { - case u.Get("pin-value") != "": - case u.Get("pin-source") != "": - case c.Pin != "": - case c.PinFile != "": - content, err := os.ReadFile(c.PinFile) - if err != nil { - fatal(err) - } - c.Pin = string(content) - - default: - pin, err := ui.PromptPassword("What is the PKCS#11 PIN?") - if err != nil { - fatal(err) - } - c.Pin = string(pin) - } - - k, err := kms.New(context.Background(), apiv1.Options{ - Type: apiv1.PKCS11, - URI: c.KMS, - Pin: c.Pin, - }) - if err != nil { - fatal(err) - } - - defer func() { - _ = k.Close() - }() - - // Check if the slots are empty, fail if they are not - certUris := []string{ - c.RootObject, c.CrtObject, - } - keyUris := []string{ - c.RootKeyObject, c.CrtKeyObject, - c.SSHHostKeyObject, c.SSHUserKeyObject, - } - if !c.Force { - for _, u := range certUris { - if u != "" && !c.NoCerts { - checkObject(k, u) - checkCertificate(k, u) - } - } - for _, u := range keyUris { - if u != "" { - checkObject(k, u) - } - } - } else { - deleter, ok := k.(interface { - DeleteKey(uri string) error - DeleteCertificate(uri string) error - }) - if ok { - for _, u := range certUris { - if u != "" && !c.NoCerts { - // Some HSMs like Nitrokey will overwrite the key with the - // certificate label. - if err := deleter.DeleteKey(u); err != nil { - fatalClose(err, k) - } - if err := deleter.DeleteCertificate(u); err != nil { - fatalClose(err, k) - } - } - } - for _, u := range keyUris { - if u != "" { - if err := deleter.DeleteKey(u); err != nil { - fatalClose(err, k) - } - } - } - } - } - - if err := createPKI(k, c); err != nil { - fatalClose(err, k) - } - - // Reset windows terminal - ui.Reset() -} - -func fatal(err error) { - if os.Getenv("STEPDEBUG") == "1" { - fmt.Fprintf(os.Stderr, "%+v\n", err) - } else { - fmt.Fprintln(os.Stderr, err) - } - ui.Reset() - os.Exit(1) -} - -func fatalClose(err error, k kms.KeyManager) { - _ = k.Close() - fatal(err) -} - -func usage() { - fmt.Fprintln(os.Stderr, "Usage: step-pkcs11-init") - fmt.Fprintln(os.Stderr, ` -The step-pkcs11-init command initializes a public key infrastructure (PKI) -to be used by step-ca. - -This tool is experimental and in the future it will be integrated in step cli. - -OPTIONS`) - fmt.Fprintln(os.Stderr) - flag.PrintDefaults() - fmt.Fprintf(os.Stderr, ` -COPYRIGHT - - (c) 2018-%d Smallstep Labs, Inc. -`, time.Now().Year()) - os.Exit(1) -} - -func checkCertificate(k kms.KeyManager, rawuri string) { - if cm, ok := k.(kms.CertificateManager); ok { - if _, err := cm.LoadCertificate(&apiv1.LoadCertificateRequest{ - Name: rawuri, - }); err == nil { - fmt.Fprintf(os.Stderr, "⚠️ Your PKCS #11 module already has a certificate on %s.\n", rawuri) - fmt.Fprintln(os.Stderr, " If you want to delete it and start fresh, use `--force`.") - _ = k.Close() - os.Exit(1) - } - } -} - -func checkObject(k kms.KeyManager, rawuri string) { - if _, err := k.GetPublicKey(&apiv1.GetPublicKeyRequest{ - Name: rawuri, - }); err == nil { - fmt.Fprintf(os.Stderr, "⚠️ Your PKCS #11 module already has a key on %s.\n", rawuri) - fmt.Fprintln(os.Stderr, " If you want to delete it and start fresh, use `--force`.") - _ = k.Close() - os.Exit(1) - } -} - -func createPKI(k kms.KeyManager, c Config) error { - var err error - ui.Println("Creating PKI ...") - now := time.Now() - - // Root Certificate - var signer crypto.Signer - var root *x509.Certificate - switch { - case c.GenerateRoot: - resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ - Name: c.RootKeyObject, - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - Extractable: c.Extractable, - }) - if err != nil { - return err - } - - signer, err = k.CreateSigner(&resp.CreateSignerRequest) - if err != nil { - return err - } - - template := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 1, - MaxPathLenZero: false, - Issuer: pkix.Name{CommonName: c.RootSubject}, - Subject: pkix.Name{CommonName: c.RootSubject}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(resp.PublicKey), - AuthorityKeyId: mustSubjectKeyID(resp.PublicKey), - } - - b, err := x509.CreateCertificate(rand.Reader, template, template, resp.PublicKey, signer) - if err != nil { - return err - } - - root, err = x509.ParseCertificate(b) - if err != nil { - return errors.Wrap(err, "error parsing root certificate") - } - - if cm, ok := k.(kms.CertificateManager); ok && c.RootObject != "" && !c.NoCerts { - if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ - Name: c.RootObject, - Certificate: root, - Extractable: c.Extractable, - }); err != nil { - return err - } - } else { - c.RootObject = "" - } - - if err := fileutil.WriteFile(c.RootPath, pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - - ui.PrintSelected("Root Key", resp.Name) - ui.PrintSelected("Root Certificate", c.RootPath) - if c.RootObject != "" { - ui.PrintSelected("Root Certificate Object", c.RootObject) - } - case c.RootFile != "" && c.KeyFile != "": // Read Root From File - root, err = pemutil.ReadCertificate(c.RootFile) - if err != nil { - return err - } - - key, err := pemutil.Read(c.KeyFile) - if err != nil { - return err - } - - var ok bool - if signer, ok = key.(crypto.Signer); !ok { - return errors.Errorf("key type '%T' does not implement a signer", key) - } - } - - // Intermediate Certificate - var keyName string - var publicKey crypto.PublicKey - var intSigner crypto.Signer - if c.CrtKeyPath != "" { - priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - return errors.Wrap(err, "error creating intermediate key") - } - - pass, err := ui.PromptPasswordGenerate("What do you want your password to be? [leave empty and we'll generate one]", - ui.WithRichPrompt()) - if err != nil { - return err - } - - _, err = pemutil.Serialize(priv, pemutil.WithPassword(pass), pemutil.ToFile(c.CrtKeyPath, 0600)) - if err != nil { - return err - } - - publicKey = priv.Public() - intSigner = priv - } else { - resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ - Name: c.CrtKeyObject, - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - Extractable: c.Extractable, - }) - if err != nil { - return err - } - publicKey = resp.PublicKey - keyName = resp.Name - - intSigner, err = k.CreateSigner(&resp.CreateSignerRequest) - if err != nil { - return err - } - } - - if root != nil { - template := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 0, - MaxPathLenZero: true, - Issuer: root.Subject, - Subject: pkix.Name{CommonName: c.CrtSubject}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(publicKey), - } - - b, err := x509.CreateCertificate(rand.Reader, template, root, publicKey, signer) - if err != nil { - return err - } - - intermediate, err := x509.ParseCertificate(b) - if err != nil { - return errors.Wrap(err, "error parsing intermediate certificate") - } - - if cm, ok := k.(kms.CertificateManager); ok && c.CrtObject != "" && !c.NoCerts { - if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ - Name: c.CrtObject, - Certificate: intermediate, - Extractable: c.Extractable, - }); err != nil { - return err - } - } else { - c.CrtObject = "" - } - - if err := fileutil.WriteFile(c.CrtPath, pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - } else { - // No root available, generate CSR for external root. - csrTemplate := x509.CertificateRequest{ - Subject: pkix.Name{CommonName: c.CrtSubject}, - SignatureAlgorithm: x509.ECDSAWithSHA256, - } - // step: generate the csr request - csrCertificate, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, intSigner) - if err != nil { - return err - } - if err := fileutil.WriteFile(c.CrtPath, pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", - Bytes: csrCertificate, - }), 0600); err != nil { - return err - } - } - - if c.CrtKeyPath != "" { - ui.PrintSelected("Intermediate Key", c.CrtKeyPath) - } else { - ui.PrintSelected("Intermediate Key", keyName) - } - - if root != nil { - ui.PrintSelected("Intermediate Certificate", c.CrtPath) - if c.CrtObject != "" { - ui.PrintSelected("Intermediate Certificate Object", c.CrtObject) - } - } else { - ui.PrintSelected("Intermediate Certificate Request", c.CrtPath) - } - - if c.SSHHostKeyObject != "" { - resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ - Name: c.SSHHostKeyObject, - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - ui.PrintSelected("SSH Host Key", resp.Name) - } - - if c.SSHUserKeyObject != "" { - resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ - Name: c.SSHUserKeyObject, - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - ui.PrintSelected("SSH User Key", resp.Name) - } - - return nil -} - -func mustSerialNumber() *big.Int { - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - sn, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - panic(err) - } - return sn -} - -func mustSubjectKeyID(key crypto.PublicKey) []byte { - b, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - panic(err) - } - //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - hash := sha1.Sum(b) - return hash[:] -} diff --git a/cmd/step-yubikey-init/main.go b/cmd/step-yubikey-init/main.go deleted file mode 100644 index cd6018cf..00000000 --- a/cmd/step-yubikey-init/main.go +++ /dev/null @@ -1,355 +0,0 @@ -package main - -import ( - "context" - "crypto" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - "crypto/x509" - "crypto/x509/pkix" - "encoding/hex" - "encoding/pem" - "flag" - "fmt" - "math/big" - "os" - "time" - - "github.com/pkg/errors" - "go.step.sm/cli-utils/fileutil" - "go.step.sm/cli-utils/ui" - "go.step.sm/crypto/kms" - "go.step.sm/crypto/kms/apiv1" - "go.step.sm/crypto/pemutil" - - // Enable yubikey. - _ "go.step.sm/crypto/kms/yubikey" -) - -// Config is a mapping of the cli flags. -type Config struct { - RootOnly bool - RootSlot string - CrtSlot string - RootFile string - KeyFile string - Pin string - ManagementKey string - Force bool -} - -// Validate checks the flags in the config. -func (c *Config) Validate() error { - switch { - case c.ManagementKey != "" && len(c.ManagementKey) != 48: - return errors.New("flag `--management-key` must be 48 hexadecimal characters (24 bytes)") - case c.RootFile != "" && c.KeyFile == "": - return errors.New("flag `--root` requires flag `--key`") - case c.KeyFile != "" && c.RootFile == "": - return errors.New("flag `--key` requires flag `--root`") - case c.RootOnly && c.RootFile != "": - return errors.New("flag `--root-only` is incompatible with flag `--root`") - case c.RootSlot == c.CrtSlot: - return errors.New("flag `--root-slot` and flag `--crt-slot` cannot be the same") - case c.RootFile == "" && c.RootSlot == "": - return errors.New("one of flag `--root` or `--root-slot` is required") - default: - if c.RootFile != "" { - c.RootSlot = "" - } - if c.RootOnly { - c.CrtSlot = "" - } - if c.ManagementKey != "" { - if _, err := hex.DecodeString(c.ManagementKey); err != nil { - return errors.Wrap(err, "flag `--management-key` is not valid") - } - } - return nil - } -} - -func main() { - var c Config - flag.StringVar(&c.ManagementKey, "management-key", "", `Management key to use in hexadecimal format. (default "010203040506070801020304050607080102030405060708")`) - flag.BoolVar(&c.RootOnly, "root-only", false, "Slot only the root certificate and sign and intermediate.") - flag.StringVar(&c.RootSlot, "root-slot", "9a", "Slot to store the root certificate.") - flag.StringVar(&c.CrtSlot, "crt-slot", "9c", "Slot to store the intermediate certificate.") - flag.StringVar(&c.RootFile, "root", "", "Path to the root certificate to use.") - flag.StringVar(&c.KeyFile, "key", "", "Path to the root key to use.") - flag.BoolVar(&c.Force, "force", false, "Force the delete of previous keys.") - flag.Usage = usage - flag.Parse() - - if err := c.Validate(); err != nil { - fatal(err) - } - - // Initialize windows terminal - ui.Init() - - ui.Println("⚠️ This command is deprecated and will be removed in future releases.") - ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.") - - pin, err := ui.PromptPassword("What is the YubiKey PIN?") - if err != nil { - fatal(err) - } - c.Pin = string(pin) - - k, err := kms.New(context.Background(), apiv1.Options{ - Type: apiv1.YubiKey, - Pin: c.Pin, - ManagementKey: c.ManagementKey, - }) - if err != nil { - fatal(err) - } - - // Check if the slots are empty, fail if they are not - if !c.Force { - switch { - case c.RootSlot != "": - checkSlot(k, c.RootSlot) - case c.CrtSlot != "": - checkSlot(k, c.CrtSlot) - } - } - - if err := createPKI(k, c); err != nil { - fatal(err) - } - - defer func() { - _ = k.Close() - }() - - // Reset windows terminal - ui.Reset() -} - -func fatal(err error) { - if os.Getenv("STEPDEBUG") == "1" { - fmt.Fprintf(os.Stderr, "%+v\n", err) - } else { - fmt.Fprintln(os.Stderr, err) - } - ui.Reset() - os.Exit(1) -} - -func usage() { - fmt.Fprintln(os.Stderr, "Usage: step-yubikey-init") - fmt.Fprintln(os.Stderr, ` -The step-yubikey-init command initializes a public key infrastructure (PKI) -to be used by step-ca. - -This tool is experimental and in the future it will be integrated in step cli. - -OPTIONS`) - fmt.Fprintln(os.Stderr) - flag.PrintDefaults() - fmt.Fprintf(os.Stderr, ` -COPYRIGHT - - (c) 2018-%d Smallstep Labs, Inc. -`, time.Now().Year()) - os.Exit(1) -} - -func checkSlot(k kms.KeyManager, slot string) { - if _, err := k.GetPublicKey(&apiv1.GetPublicKeyRequest{ - Name: slot, - }); err == nil { - fmt.Fprintf(os.Stderr, "⚠️ Your YubiKey already has a key in the slot %s.\n", slot) - fmt.Fprintln(os.Stderr, " If you want to delete it and start fresh, use `--force`.") - os.Exit(1) - } -} - -func createPKI(k kms.KeyManager, c Config) error { - var err error - ui.Println("Creating PKI ...") - now := time.Now() - - // Root Certificate - var signer crypto.Signer - var root *x509.Certificate - if c.RootFile != "" && c.KeyFile != "" { - root, err = pemutil.ReadCertificate(c.RootFile) - if err != nil { - return err - } - - key, err := pemutil.Read(c.KeyFile) - if err != nil { - return err - } - - var ok bool - if signer, ok = key.(crypto.Signer); !ok { - return errors.Errorf("key type '%T' does not implement a signer", key) - } - } else { - resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ - Name: c.RootSlot, - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - - signer, err = k.CreateSigner(&resp.CreateSignerRequest) - if err != nil { - return err - } - - template := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 1, - MaxPathLenZero: false, - Issuer: pkix.Name{CommonName: "YubiKey Smallstep Root"}, - Subject: pkix.Name{CommonName: "YubiKey Smallstep Root"}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(resp.PublicKey), - AuthorityKeyId: mustSubjectKeyID(resp.PublicKey), - } - - b, err := x509.CreateCertificate(rand.Reader, template, template, resp.PublicKey, signer) - if err != nil { - return err - } - - root, err = x509.ParseCertificate(b) - if err != nil { - return errors.Wrap(err, "error parsing root certificate") - } - - if cm, ok := k.(kms.CertificateManager); ok { - if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ - Name: c.RootSlot, - Certificate: root, - }); err != nil { - return err - } - } - - if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - - ui.PrintSelected("Root Key", resp.Name) - ui.PrintSelected("Root Certificate", "root_ca.crt") - } - - // Intermediate Certificate - var keyName string - var publicKey crypto.PublicKey - if c.RootOnly { - priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - return errors.Wrap(err, "error creating intermediate key") - } - - pass, err := ui.PromptPasswordGenerate("What do you want your password to be? [leave empty and we'll generate one]", - ui.WithRichPrompt()) - if err != nil { - return err - } - - _, err = pemutil.Serialize(priv, pemutil.WithPassword(pass), pemutil.ToFile("intermediate_ca_key", 0600)) - if err != nil { - return err - } - - publicKey = priv.Public() - } else { - resp, err := k.CreateKey(&apiv1.CreateKeyRequest{ - Name: c.CrtSlot, - SignatureAlgorithm: apiv1.ECDSAWithSHA256, - }) - if err != nil { - return err - } - publicKey = resp.PublicKey - keyName = resp.Name - } - - template := &x509.Certificate{ - IsCA: true, - NotBefore: now, - NotAfter: now.Add(time.Hour * 24 * 365 * 10), - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - BasicConstraintsValid: true, - MaxPathLen: 0, - MaxPathLenZero: true, - Issuer: root.Subject, - Subject: pkix.Name{CommonName: "YubiKey Smallstep Intermediate"}, - SerialNumber: mustSerialNumber(), - SubjectKeyId: mustSubjectKeyID(publicKey), - } - - b, err := x509.CreateCertificate(rand.Reader, template, root, publicKey, signer) - if err != nil { - return err - } - - intermediate, err := x509.ParseCertificate(b) - if err != nil { - return errors.Wrap(err, "error parsing intermediate certificate") - } - - if cm, ok := k.(kms.CertificateManager); ok { - if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{ - Name: c.CrtSlot, - Certificate: intermediate, - }); err != nil { - return err - } - } - - if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: b, - }), 0600); err != nil { - return err - } - - if c.RootOnly { - ui.PrintSelected("Intermediate Key", "intermediate_ca_key") - } else { - ui.PrintSelected("Intermediate Key", keyName) - } - - ui.PrintSelected("Intermediate Certificate", "intermediate_ca.crt") - - return nil -} - -func mustSerialNumber() *big.Int { - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - sn, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - panic(err) - } - return sn -} - -func mustSubjectKeyID(key crypto.PublicKey) []byte { - b, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - panic(err) - } - //nolint:gosec // used to create the Subject Key Identifier by RFC 5280 - hash := sha1.Sum(b) - return hash[:] -} diff --git a/commands/app.go b/commands/app.go index 31d62f87..4435cfe2 100644 --- a/commands/app.go +++ b/commands/app.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "path/filepath" + "strconv" "strings" "unicode" @@ -29,7 +30,7 @@ var AppCommand = cli.Command{ Action: appAction, UsageText: `**step-ca** [**--password-file**=] [**--ssh-host-password-file**=] [**--ssh-user-password-file**=] -[**--issuer-password-file**=] [**--resolver**=]`, +[**--issuer-password-file**=] [**--pidfile**=] [**--resolver**=]`, Flags: []cli.Flag{ cli.StringFlag{ Name: "password-file", @@ -82,6 +83,10 @@ Requires **--insecure** flag.`, Usage: `the used on tls-alpn-01 challenges. It can be changed for testing purposes. Requires **--insecure** flag.`, }, + cli.StringFlag{ + Name: "pidfile", + Usage: "that path to the to write the process ID.", + }, cli.BoolFlag{ Name: "insecure", Usage: "enable insecure flags.", @@ -89,6 +94,8 @@ Requires **--insecure** flag.`, }, } +var pidfile string + // AppAction is the action used when the top command runs. func appAction(ctx *cli.Context) error { passFile := ctx.String("password-file") @@ -141,6 +148,13 @@ func appAction(ctx *cli.Context) error { cfg, err := config.LoadConfiguration(configFile) if err != nil && token == "" { + var pathErr *os.PathError + if errors.As(err, &pathErr) { + fmt.Println("step-ca can't find or open the configuration file for your CA.") + fmt.Println("You may need to create a CA first by running `step ca init`.") + fmt.Println("Documentation: https://u.step.sm/docs/ca") + os.Exit(1) + } fatal(err) } @@ -213,6 +227,15 @@ To get a linked authority token: issuerPassword = bytes.TrimRightFunc(issuerPassword, unicode.IsSpace) } + if filename := ctx.String("pidfile"); filename != "" { + pid := []byte(strconv.Itoa(os.Getpid()) + "\n") + //nolint:gosec // 0644 (-rw-r--r--) are common permissions for a pid file + if err := os.WriteFile(filename, pid, 0644); err != nil { + fatal(errors.Wrap(err, "error writing pidfile")) + } + pidfile = filename + } + // replace resolver if requested if resolver != "" { net.DefaultResolver.PreferGo = true @@ -237,6 +260,11 @@ To get a linked authority token: if err = srv.Run(); err != nil && !errors.Is(err, http.ErrServerClosed) { fatal(err) } + + if pidfile != "" { + os.Remove(pidfile) + } + return nil } @@ -269,5 +297,8 @@ func fatal(err error) { } else { fmt.Fprintln(os.Stderr, err) } + if pidfile != "" { + os.Remove(pidfile) + } os.Exit(2) } diff --git a/docker/Dockerfile.step-ca b/docker/Dockerfile similarity index 74% rename from docker/Dockerfile.step-ca rename to docker/Dockerfile index 8cf918df..00fa9c0e 100644 --- a/docker/Dockerfile.step-ca +++ b/docker/Dockerfile @@ -5,13 +5,14 @@ COPY . . RUN apk add --no-cache curl git make RUN make V=1 download -RUN make V=1 bin/step-ca bin/step-awskms-init bin/step-cloudkms-init +RUN make V=1 bin/step-ca + +FROM smallstep/step-kms-plugin-cloud:latest AS kms FROM smallstep/step-cli:latest COPY --from=builder /src/bin/step-ca /usr/local/bin/step-ca -COPY --from=builder /src/bin/step-awskms-init /usr/local/bin/step-awskms-init -COPY --from=builder /src/bin/step-cloudkms-init /usr/local/bin/step-cloudkms-init +COPY --from=kms /usr/local/bin/step-kms-plugin /usr/local/bin/step-kms-plugin USER root RUN apk add --no-cache libcap && setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/step-ca diff --git a/docker/Dockerfile.step-ca.hsm b/docker/Dockerfile.hsm similarity index 71% rename from docker/Dockerfile.step-ca.hsm rename to docker/Dockerfile.hsm index 8f413cd7..05c1ef82 100644 --- a/docker/Dockerfile.step-ca.hsm +++ b/docker/Dockerfile.hsm @@ -8,18 +8,18 @@ RUN apk add --no-cache gcc musl-dev pkgconf pcsc-lite-dev RUN make V=1 download RUN make V=1 GOFLAGS="" build +FROM smallstep/step-kms-plugin:latest AS kms FROM smallstep/step-cli:latest COPY --from=builder /src/bin/step-ca /usr/local/bin/step-ca -COPY --from=builder /src/bin/step-awskms-init /usr/local/bin/step-awskms-init -COPY --from=builder /src/bin/step-cloudkms-init /usr/local/bin/step-cloudkms-init -COPY --from=builder /src/bin/step-pkcs11-init /usr/local/bin/step-pkcs11-init -COPY --from=builder /src/bin/step-yubikey-init /usr/local/bin/step-yubikey-init +COPY --from=kms /usr/local/bin/step-kms-plugin /usr/local/bin/step-kms-plugin USER root RUN apk add --no-cache libcap && setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/step-ca RUN apk add --no-cache pcsc-lite pcsc-lite-libs +RUN mkdir -p /run/pcscd +RUN chown step:step /run/pcscd USER step ENV CONFIGPATH="/home/step/config/ca.json" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 91133dea..93312ca8 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -36,6 +36,7 @@ function generate_password () { function step_ca_init () { DOCKER_STEPCA_INIT_PROVISIONER_NAME="${DOCKER_STEPCA_INIT_PROVISIONER_NAME:-admin}" DOCKER_STEPCA_INIT_ADMIN_SUBJECT="${DOCKER_STEPCA_INIT_ADMIN_SUBJECT:-step}" + DOCKER_STEPCA_INIT_ADDRESS="${DOCKER_STEPCA_INIT_ADDRESS:-:9000}" local -a setup_args=( --name "${DOCKER_STEPCA_INIT_NAME}" @@ -43,7 +44,7 @@ function step_ca_init () { --provisioner "${DOCKER_STEPCA_INIT_PROVISIONER_NAME}" --password-file "${STEPPATH}/password" --provisioner-password-file "${STEPPATH}/provisioner_password" - --address ":9000" + --address "${DOCKER_STEPCA_INIT_ADDRESS}" ) if [ -n "${DOCKER_STEPCA_INIT_PASSWORD}" ]; then echo "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" diff --git a/go.mod b/go.mod index 305dd00c..6a2f85ad 100644 --- a/go.mod +++ b/go.mod @@ -3,66 +3,67 @@ module github.com/smallstep/certificates go 1.18 require ( - cloud.google.com/go v0.107.0 // indirect - cloud.google.com/go/longrunning v0.4.0 - cloud.google.com/go/security v1.11.0 - github.com/Azure/azure-sdk-for-go v67.0.0+incompatible // indirect + cloud.google.com/go v0.110.0 // indirect + cloud.google.com/go/longrunning v0.4.1 + cloud.google.com/go/security v1.12.0 + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.28 // indirect - github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect + github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Masterminds/sprig/v3 v3.2.3 github.com/ThalesIgnite/crypto11 v1.2.5 // indirect - github.com/aws/aws-sdk-go v1.44.132 // indirect + github.com/aws/aws-sdk-go v1.44.210 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/fatih/color v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.4.0 github.com/go-chi/chi v4.1.2+incompatible github.com/go-kit/kit v0.10.0 // indirect github.com/go-piv/piv-go v1.10.0 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect 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/googleapis/gax-go/v2 v2.7.0 - github.com/hashicorp/vault/api v1.8.3 - github.com/hashicorp/vault/api/auth/approle v0.3.0 - github.com/hashicorp/vault/api/auth/kubernetes v0.3.0 - github.com/jhump/protoreflect v1.12.0 // indirect - github.com/kr/pretty v0.3.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 + github.com/hashicorp/vault/api v1.9.0 + github.com/hashicorp/vault/api/auth/approle v0.4.0 + github.com/hashicorp/vault/api/auth/kubernetes v0.4.0 + github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.13 // indirect github.com/micromdm/scep/v2 v2.1.0 - github.com/newrelic/go-agent/v3 v3.20.3 + github.com/newrelic/go-agent/v3 v3.20.4 github.com/pkg/errors v0.9.1 github.com/rs/xid v1.4.0 github.com/ryboe/q v1.0.17 github.com/sirupsen/logrus v1.9.0 github.com/slackhq/nebula v1.6.1 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 - github.com/smallstep/nosql v0.5.0 - github.com/stretchr/testify v1.8.1 + github.com/smallstep/nosql v0.6.0 + github.com/stretchr/testify v1.8.2 github.com/urfave/cli v1.22.12 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.7.5 - go.step.sm/crypto v0.23.1 + go.step.sm/crypto v0.26.0 go.step.sm/linkedca v0.19.0 - golang.org/x/crypto v0.5.0 - golang.org/x/net v0.5.0 - golang.org/x/sys v0.4.0 // indirect - golang.org/x/time v0.3.0 // indirect - google.golang.org/api v0.108.0 - google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect - google.golang.org/grpc v1.52.0 - google.golang.org/protobuf v1.28.1 + golang.org/x/crypto v0.7.0 + golang.org/x/net v0.8.0 + golang.org/x/sys v0.6.0 // indirect + golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect + google.golang.org/api v0.112.0 + google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect + google.golang.org/grpc v1.53.0 + google.golang.org/protobuf v1.29.0 gopkg.in/square/go-jose.v2 v2.6.0 ) +require github.com/google/go-attestation v0.4.3 + require ( - cloud.google.com/go/compute v1.14.0 // indirect + cloud.google.com/go/compute v1.18.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.8.0 // indirect - cloud.google.com/go/kms v1.6.0 // indirect + cloud.google.com/go/iam v0.12.0 // indirect + cloud.google.com/go/kms v1.8.0 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -74,11 +75,9 @@ require ( github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect - github.com/armon/go-metrics v0.3.9 // indirect - github.com/armon/go-radix v1.0.0 // indirect github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -94,37 +93,27 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/certificate-transparency-go v1.1.4 // indirect - github.com/google/go-attestation v0.4.3 // indirect github.com/google/go-tspi v0.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v0.16.2 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.5 // indirect github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect - github.com/hashicorp/go-version v1.2.0 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/vault/sdk v0.7.0 // indirect - github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.13.0 // indirect + github.com/jackc/pgconn v1.14.0 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.1 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect - github.com/jackc/pgtype v1.12.0 // indirect - github.com/jackc/pgx/v4 v4.17.2 // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + 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/kr/text v0.2.0 // indirect @@ -133,13 +122,10 @@ require ( github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/oklog/run v1.0.0 // indirect - github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.6.1 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect @@ -147,11 +133,10 @@ require ( github.com/spf13/cast v1.4.1 // indirect github.com/thales-e-security/pool v0.0.2 // indirect github.com/x448/float16 v0.8.4 // indirect - go.etcd.io/bbolt v1.3.6 // indirect + go.etcd.io/bbolt v1.3.7 // indirect go.opencensus.io v0.24.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -164,4 +149,4 @@ require ( // 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-20221024180420-e1aab68dda05 +replace go.mozilla.org/pkcs7 => github.com/smallstep/pkcs7 v0.0.0-20230302202335-4c094085c948 diff --git a/go.sum b/go.sum index 749d05e9..683da771 100644 --- a/go.sum +++ b/go.sum @@ -13,34 +13,34 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP 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.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= 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.14.0 h1:hfm2+FfxVmnRlh6LpB7cg1ZNU+5edAHmW679JePztk0= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= 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 v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/kms v1.6.0 h1:OWRZzrPmOZUzurjI2FBGtgY2mB1WaJkqhw6oIwSj0Yg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/longrunning v0.4.0 h1:v+X4EwhHl6xE+TG1XgXj4T1XpKKs7ZevcAJ3FOu0YmY= -cloud.google.com/go/longrunning v0.4.0/go.mod h1:eF3Qsw58iX/bkKtVjMTYpH0LRjQ2goDkjkNQTlzq/ZM= +cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/kms v1.8.0 h1:VrJLOsMRzW7IqTTYn+OYupqF3iKSE060Nrn+PECrYjg= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= 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.11.0 h1:155BmlBUj4940GUlvV4rS4VTxXZWDkOSW3GnXc211Cs= -cloud.google.com/go/security v1.11.0/go.mod h1:qL8hSHb3MqXtsVRgSPOt/igsHrs5pWAy0nrP1zl4j5I= +cloud.google.com/go/security v1.12.0 h1:WIyVxhrdex1geaAV0pC/4yXy/sZdurjHXLzMopcjers= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= 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= @@ -52,8 +52,8 @@ 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-sdk-for-go v67.0.0+incompatible h1:SVBwznSETB0Sipd0uyGJr7khLhJOFRUEUb+0JgkCvDo= -github.com/Azure/azure-sdk-for-go v67.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= @@ -61,8 +61,8 @@ github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwG github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= @@ -81,7 +81,6 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= 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= @@ -110,25 +109,20 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy 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/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/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/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-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 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.23.20/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.44.132 h1:+IjL9VoR0OXScQ5gyme9xjcolwUkd3uaH144f4Ao+4s= -github.com/aws/aws-sdk-go v1.44.132/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.210 h1:/cqRMHSSgzLEKILIDGwhaX2hiIpyRurw7MRy6aaSufg= +github.com/aws/aws-sdk-go v1.44.210/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 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= @@ -144,21 +138,17 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA 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= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= 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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/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= @@ -212,28 +202,18 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s 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.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.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/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= 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/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= 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/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= -github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= -github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= 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/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= 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= @@ -245,7 +225,6 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 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/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= 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-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= @@ -256,8 +235,8 @@ github.com/go-piv/piv-go v1.10.0/go.mod h1:NZ2zmjVkfFaL/CF8cVQ/pXdXtuj110zEKGdJM github.com/go-redis/redis v6.15.8+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.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -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-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= @@ -333,6 +312,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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.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-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI= @@ -343,6 +323,7 @@ github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51B 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 h1:AFlmenDrIe0WU5AvpbfGFOLprTJTg/fCwmTyFdDEjbM= github.com/google/go-tpm-tools v0.3.1/go.mod h1:PSg+r5hSZI5tP3X7LBQx2sW1VSZUqZHBSrKyDqrB21U= github.com/google/go-tspi v0.2.1-0.20190423175329-115dea689aad/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI= github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus= @@ -364,12 +345,12 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ 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/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= 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/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= 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/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -389,7 +370,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/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.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= @@ -397,75 +377,49 @@ github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN 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= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 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.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 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-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 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-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= -github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= 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/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 h1:cCRo8gK7oq6A2L6LICkUZ+/a5rLiRXFMf1Qd4xSwxTc= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= 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-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= 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-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= 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/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 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.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= -github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= -github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= -github.com/hashicorp/vault/api/auth/approle v0.3.0 h1:Ib0oCNXsCq/QZhPYtXPzJEbGS5WR/KoZf8c84QoFdkU= -github.com/hashicorp/vault/api/auth/approle v0.3.0/go.mod h1:hm51TbjzUkPO0Y17wkrpwOpvyyMRpXJNueTHiG04t3k= -github.com/hashicorp/vault/api/auth/kubernetes v0.3.0 h1:HkaCmTKzcgLa2tjdiAid1rbmyQNmQGHfnmvIIM2WorY= -github.com/hashicorp/vault/api/auth/kubernetes v0.3.0/go.mod h1:l1B4MGtLc+P37MabBQiIhP3qd9agj0vqhETmaQjjC/Y= -github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= -github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg= -github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/vault/api v1.9.0 h1:ab7dI6W8DuCY7yCU8blo0UCYl2oHre/dloCmzMWg9w8= +github.com/hashicorp/vault/api v1.9.0/go.mod h1:lloELQP4EyhjnCQhF8agKvWIVTmxbpEJj70b98959sM= +github.com/hashicorp/vault/api/auth/approle v0.4.0 h1:tjJHoUkPx8zRoFlFy86uvgg/1gpTnDPp0t0BYWTKjjw= +github.com/hashicorp/vault/api/auth/approle v0.4.0/go.mod h1:D2gEpR0aS/F/MEcSjmhUlOsuK1RMVZojsnIQAEf0EV0= +github.com/hashicorp/vault/api/auth/kubernetes v0.4.0 h1:f6OIOF9012JIdqYvOeeewxhtQdJosnog2CHzh33j41s= +github.com/hashicorp/vault/api/auth/kubernetes v0.4.0/go.mod h1:tMewM2hPyFNKP1EXdWbc0dUHHoS5V/0qS04BEaxuy78= 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= @@ -491,9 +445,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= +github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= +github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -509,40 +462,28 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= -github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= -github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= +github.com/jackc/pgx/v4 v4.18.0 h1:Ltaa1ePvc7msFGALnCrqKJVEByu/qYh5jJBYcDtAno4= +github.com/jackc/pgx/v4 v4.18.0/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= 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.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= -github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= -github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= -github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= -github.com/jhump/protoreflect v1.9.0 h1:npqHz788dryJiR/l6K/RUQAyh2SwV91+d1dnh4RjO9w= -github.com/jhump/protoreflect v1.9.0/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= -github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= -github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= 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= @@ -553,7 +494,6 @@ github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB 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/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= @@ -572,8 +512,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB 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.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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= @@ -631,8 +571,6 @@ github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HK 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 v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= 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= @@ -661,12 +599,10 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE 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.20.3 h1:hUBAMq/Y2Y9as5/yxQbf0zNde/X7w58cWZkm2flZIaw= -github.com/newrelic/go-agent/v3 v3.20.3/go.mod h1:rT6ZUxJc5rQbWLyCtjqQCOcfb01lKRFbc1yMQkcboWM= +github.com/newrelic/go-agent/v3 v3.20.4 h1:fkxr0oUEYrPeXyfJC0D0BwDs1FYMe4NgUSqnzqPESI0= +github.com/newrelic/go-agent/v3 v3.20.4/go.mod h1:rT6ZUxJc5rQbWLyCtjqQCOcfb01lKRFbc1yMQkcboWM= 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 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= 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= @@ -688,15 +624,12 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= 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/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= 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/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/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= -github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -711,7 +644,6 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod 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.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 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= @@ -724,7 +656,6 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 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/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= @@ -739,8 +670,8 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= @@ -773,13 +704,12 @@ github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0 github.com/sirupsen/logrus v1.9.0/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-20180720014142-de77670473b5/go.mod h1:TC9A4+RjIOS+HyTH7wG17/gSqVv95uDw2J64dQZx7RE= 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/nosql v0.5.0 h1:1BPyHy8bha8qSaxgULGEdqhXpNFXimAfudnauFVqmxw= -github.com/smallstep/nosql v0.5.0/go.mod h1:yKZT5h7cdIVm6wEKM9+jN5dgK80Hljpuy8HNsnI7Gzo= -github.com/smallstep/pkcs7 v0.0.0-20221024180420-e1aab68dda05 h1:nVZXaJTwrUcfPUSZknkOidfITqOXSO0wE8pkOUTOdSM= -github.com/smallstep/pkcs7 v0.0.0-20221024180420-e1aab68dda05/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +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/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -810,7 +740,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= 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= @@ -821,8 +750,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 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= @@ -830,7 +760,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1 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/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -851,9 +780,8 @@ github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxt 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 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -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.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -865,20 +793,17 @@ 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.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.step.sm/cli-utils v0.7.5 h1:jyp6X8k8mN1B0uWJydTid0C++8tQhm2kaaAdXKQQzdk= go.step.sm/cli-utils v0.7.5/go.mod h1:taSsY8haLmXoXM3ZkywIyRmVij/4Aj0fQbNTlJvv71I= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= -go.step.sm/crypto v0.23.1 h1:Yr9vlzjGqIKVi88KcpZtEcNTcpDkt1nVR7tumW4h+CU= -go.step.sm/crypto v0.23.1/go.mod h1:djAhDYpNAuWF2LkzbCVcf0JDy1UWgrxR3eQ7pQ8EQ/w= +go.step.sm/crypto v0.26.0 h1:mWie6FVOkhwJtyOA1EFCOZntx5e2cbM3FfwALu2goY0= +go.step.sm/crypto v0.26.0/go.mod h1:4pUEuZ+4OAf2f70RgW5oRv/rJudibcAAWQg5prC3DT8= go.step.sm/linkedca v0.19.0 h1:xuagkR35wrJI2gnu6FAM+q3VmjwsHScvGcJsfZ0GdsI= go.step.sm/linkedca v0.19.0/go.mod h1:b7vWPrHfYLEOTSUZitFEcztVCpTc+ileIN85CwEAluM= 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.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 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= @@ -909,8 +834,10 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= 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= @@ -945,7 +872,6 @@ golang.org/x/mod v0.3.0/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-20180530234432-1e491301e022/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= @@ -989,15 +915,17 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx 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.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/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-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-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= 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= @@ -1055,7 +983,6 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1065,21 +992,24 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/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-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-20211031064116-611d5d643895/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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-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.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= @@ -1089,18 +1019,17 @@ golang.org/x/text v0.3.4/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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.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.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1149,11 +1078,9 @@ golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roY 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-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.1.1/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= @@ -1179,8 +1106,8 @@ google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ 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.108.0 h1:WVBc/faN0DkKtR43Q/7+tPny9ZoLZdIiAyG5Q9vFClg= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.112.0 h1:iDmzvZ4C086R3+en4nSyIf07HlQKMOX1Xx2dmia/+KQ= +google.golang.org/api v0.112.0/go.mod h1:737UfWHNsOq4F3REUTmb+GN9pugkgNLCayLTfoIKpPc= 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.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1219,13 +1146,12 @@ google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfG 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-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-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= 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/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1244,13 +1170,9 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 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.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= 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= @@ -1261,12 +1183,11 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= +google.golang.org/protobuf v1.29.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= diff --git a/pki/pki.go b/pki/pki.go index d6c15c9e..971c189b 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -812,6 +812,11 @@ func (p *PKI) GenerateConfig(opt ...ConfigOption) (*authconfig.Config, error) { Templates: p.getTemplates(), } + // Disable the database when WithNoDB() option is passed. + if p.options.noDB { + cfg.DB = nil + } + // Add linked as a deployment type to detect it on start and provide a // message if the token is not given. if p.options.deploymentType == LinkedDeployment { diff --git a/scripts/install-step-ra.sh b/scripts/install-step-ra.sh index 74aa1914..07875601 100644 --- a/scripts/install-step-ra.sh +++ b/scripts/install-step-ra.sh @@ -188,7 +188,7 @@ CA_VERSION=$(curl -s https://api.github.com/repos/smallstep/certificates/release curl -sLO https://github.com/smallstep/certificates/releases/download/$CA_VERSION/step-ca_linux_${CA_VERSION:1}_$arch.tar.gz tar -xf step-ca_linux_${CA_VERSION:1}_$arch.tar.gz -install -m 0755 -t /usr/bin step-ca_${CA_VERSION:1}/bin/step-ca +install -m 0755 -t /usr/bin step-ca_${CA_VERSION:1}/step-ca setcap CAP_NET_BIND_SERVICE=+eip $(which step-ca) rm step-ca_linux_${CA_VERSION:1}_$arch.tar.gz rm -rf step-ca_${CA_VERSION:1}