diff --git a/.github/actions/changed-files/action.yml b/.github/actions/changed-files/action.yml
index 3d0a1efacf..d36c450877 100644
--- a/.github/actions/changed-files/action.yml
+++ b/.github/actions/changed-files/action.yml
@@ -53,7 +53,7 @@ runs:
checkout_ref='${{ github.ref }}'
fi
echo "ref=${checkout_ref}" | tee -a "$GITHUB_OUTPUT"
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: ${{ github.repository }}
path: "changed-files"
diff --git a/.github/actions/checkout/action.yml b/.github/actions/checkout/action.yml
index 312763f5c1..8b92628f9b 100644
--- a/.github/actions/checkout/action.yml
+++ b/.github/actions/checkout/action.yml
@@ -70,7 +70,7 @@ runs:
echo "ref=${checkout_ref}"
echo "depth=${fetch_depth}"
} | tee -a "$GITHUB_OUTPUT"
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
path: ${{ inputs.path }}
fetch-depth: ${{ steps.ref.outputs.depth }}
diff --git a/.github/actions/install-external-tools/action.yml b/.github/actions/install-external-tools/action.yml
index 315f4f4d86..47472bfb85 100644
--- a/.github/actions/install-external-tools/action.yml
+++ b/.github/actions/install-external-tools/action.yml
@@ -21,15 +21,15 @@ runs:
- uses: ./.github/actions/set-up-staticcheck
# We assume that the Go toolchain will be managed by the caller workflow so we don't set one
# up here.
- - run: go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
+ - run: ./.github/scripts/retry-command.sh go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
shell: bash
- - run: go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
+ - run: ./.github/scripts/retry-command.sh go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.4.0
shell: bash
- - run: go install github.com/favadi/protoc-go-inject-tag@latest
+ - run: ./.github/scripts/retry-command.sh go install github.com/favadi/protoc-go-inject-tag@latest
shell: bash
- - run: go install golang.org/x/tools/cmd/goimports@latest
+ - run: ./.github/scripts/retry-command.sh go install golang.org/x/tools/cmd/goimports@latest
shell: bash
- - run: go install github.com/golangci/revgrep/cmd/revgrep@latest
+ - run: ./.github/scripts/retry-command.sh go install github.com/golangci/revgrep/cmd/revgrep@latest
shell: bash
- - run: go install github.com/loggerhead/enumer@latest
+ - run: ./.github/scripts/retry-command.sh go install github.com/loggerhead/enumer@latest
shell: bash
diff --git a/.github/actions/metadata/action.yml b/.github/actions/metadata/action.yml
index 53eff3d62c..f88c7a305a 100644
--- a/.github/actions/metadata/action.yml
+++ b/.github/actions/metadata/action.yml
@@ -102,10 +102,11 @@ runs:
if [ '${{ github.event_name }}' = 'pull_request' ]; then
is_draft='${{ github.event.pull_request.draft }}'
- # Determine our labels. If our event type is pull_request this is rather straight forward. If
- # our even_type is push (merge) we'll need to look up the pull request associated with the
- # commit and get the labels. This will return the label names as an array.
- labels=$(jq -rc <<< '${{ toJSON(github.event.pull_request.labels.*.name) }}')
+ # Determine our pull request labels. We specifically look them up via the pulls API
+ # because at some point they stopped being reliable in the
+ # github.event.pull_request.labels.*.name context.
+
+ labels=$(gh api "/repos/${{ github.repository }}/issues/${{ github.event.number }}/labels" | jq -erc '. | map(.name)')
else
is_draft='false'
diff --git a/.github/actions/set-up-buf/action.yml b/.github/actions/set-up-buf/action.yml
index a9cd3656a1..229f5704b6 100644
--- a/.github/actions/set-up-buf/action.yml
+++ b/.github/actions/set-up-buf/action.yml
@@ -34,7 +34,7 @@ runs:
env:
GH_TOKEN: ${{ github.token }}
run: |
- VERSION=$(gh release list -R bufbuild/buf --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
+ VERSION=$(./.github/scripts/retry-command.sh gh release list -R bufbuild/buf --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
@@ -60,7 +60,7 @@ runs:
fi
mkdir -p tmp
- gh release download "$VERSION" -p "buf-${OS}-${ARCH}.tar.gz" -O tmp/buf.tgz -R bufbuild/buf
+ ./.github/scripts/retry-command.sh gh release download "$VERSION" --clobber -p "buf-${OS}-${ARCH}.tar.gz" -O tmp/buf.tgz -R bufbuild/buf
pushd tmp && tar -xvf buf.tgz && popd
mv tmp/buf/bin/buf "$DESTINATION"
rm -rf tmp
diff --git a/.github/actions/set-up-gofumpt/action.yml b/.github/actions/set-up-gofumpt/action.yml
index d763656fc4..1e307f7633 100644
--- a/.github/actions/set-up-gofumpt/action.yml
+++ b/.github/actions/set-up-gofumpt/action.yml
@@ -34,7 +34,7 @@ runs:
env:
GH_TOKEN: ${{ github.token }}
run: |
- VERSION=$(gh release list -R mvdan/gofumpt --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
+ VERSION=$(./.github/scripts/retry-command.sh gh release list -R mvdan/gofumpt --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
@@ -56,6 +56,6 @@ runs:
export OS="darwin"
fi
- gh release download "$VERSION" -p "gofumpt_*_${OS}_${ARCH}" -O gofumpt -R mvdan/gofumpt
+ ./.github/scripts/retry-command.sh gh release download "$VERSION" --clobber -p "gofumpt_*_${OS}_${ARCH}" -O gofumpt -R mvdan/gofumpt
chmod +x gofumpt
mv gofumpt "$DESTINATION"
diff --git a/.github/actions/set-up-gosimports/action.yml b/.github/actions/set-up-gosimports/action.yml
index 97602498b3..7563c2e3b3 100644
--- a/.github/actions/set-up-gosimports/action.yml
+++ b/.github/actions/set-up-gosimports/action.yml
@@ -34,7 +34,7 @@ runs:
env:
GH_TOKEN: ${{ github.token }}
run: |
- VERSION=$(gh release list -R rinchsan/gosimports --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
+ VERSION=$(./.github/scripts/retry-command.sh gh release list -R rinchsan/gosimports --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
@@ -57,7 +57,7 @@ runs:
fi
mkdir -p tmp
- gh release download "$VERSION" -p "gosimports_*_${OS}_${ARCH}.tar.gz" -O tmp/gosimports.tgz -R rinchsan/gosimports
+ ./.github/scripts/retry-command.sh gh release download "$VERSION" --clobber -p "gosimports_*_${OS}_${ARCH}.tar.gz" -O tmp/gosimports.tgz -R rinchsan/gosimports
pushd tmp && tar -xvf gosimports.tgz && popd
mv tmp/gosimports "$DESTINATION"
rm -rf tmp
diff --git a/.github/actions/set-up-gotestsum/action.yml b/.github/actions/set-up-gotestsum/action.yml
index 9d0147313a..97ceb91742 100644
--- a/.github/actions/set-up-gotestsum/action.yml
+++ b/.github/actions/set-up-gotestsum/action.yml
@@ -34,7 +34,7 @@ runs:
env:
GH_TOKEN: ${{ github.token }}
run: |
- VERSION=$(gh release list -R gotestyourself/gotestsum --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
+ VERSION=$(./.github/scripts/retry-command.sh gh release list -R gotestyourself/gotestsum --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
@@ -54,7 +54,7 @@ runs:
fi
mkdir -p tmp
- gh release download "$VERSION" -p "*${OS}_${ARCH}.tar.gz" -O tmp/gotestsum.tgz -R gotestyourself/gotestsum
+ ./.github/scripts/retry-command.sh gh release download "$VERSION" --clobber -p "*${OS}_${ARCH}.tar.gz" -O tmp/gotestsum.tgz -R gotestyourself/gotestsum
pushd tmp && tar -xvf gotestsum.tgz && popd
mv tmp/gotestsum "$DESTINATION"
rm -rf tmp
diff --git a/.github/actions/set-up-misspell/action.yml b/.github/actions/set-up-misspell/action.yml
index d6101bf073..f57ab97f31 100644
--- a/.github/actions/set-up-misspell/action.yml
+++ b/.github/actions/set-up-misspell/action.yml
@@ -34,7 +34,7 @@ runs:
env:
GH_TOKEN: ${{ github.token }}
run: |
- VERSION=$(gh release list -R golangci/misspell --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
+ VERSION=$(./.github/scripts/retry-command.sh gh release list -R golangci/misspell --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
@@ -57,7 +57,7 @@ runs:
fi
mkdir -p tmp
- gh release download "$VERSION" -p "misspell_*_${OS}_${ARCH}.tar.gz" -O tmp/misspell.tgz -R golangci/misspell
+ ./.github/scripts/retry-command.sh gh release download "$VERSION" --clobber -p "misspell_*_${OS}_${ARCH}.tar.gz" -O tmp/misspell.tgz -R golangci/misspell
pushd tmp && tar -xvf misspell.tgz && popd
- mv tmp/misspell "$DESTINATION"
+ mv tmp/misspell_"$(echo "$VERSION" | tr -d v)"_${OS}_${ARCH}/misspell "$DESTINATION"
rm -rf tmp
diff --git a/.github/actions/set-up-staticcheck/action.yml b/.github/actions/set-up-staticcheck/action.yml
index cce079618f..3ec7ac2ae6 100644
--- a/.github/actions/set-up-staticcheck/action.yml
+++ b/.github/actions/set-up-staticcheck/action.yml
@@ -34,7 +34,7 @@ runs:
env:
GH_TOKEN: ${{ github.token }}
run: |
- VERSION=$(gh release list -R dominikh/go-tools --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -d " " -f2)
+ VERSION=$(./.github/scripts/retry-command.sh gh release list -R dominikh/go-tools --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -d " " -f2)
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
@@ -57,7 +57,7 @@ runs:
fi
mkdir -p tmp
- gh release download "$VERSION" -p "staticcheck_${OS}_${ARCH}.tar.gz" -O tmp/staticcheck.tgz -R dominikh/go-tools
+ ./.github/scripts/retry-command.sh gh release download "$VERSION" --clobber -p "staticcheck_${OS}_${ARCH}.tar.gz" -O tmp/staticcheck.tgz -R dominikh/go-tools
pushd tmp && tar -xvf staticcheck.tgz && popd
mv tmp/staticcheck/staticcheck "$DESTINATION"
rm -rf tmp
diff --git a/.github/docs/pull_request_template.md b/.github/docs/pull_request_template.md
new file mode 100644
index 0000000000..6b9d11b9a1
--- /dev/null
+++ b/.github/docs/pull_request_template.md
@@ -0,0 +1,8 @@
+### Description
+Why is this docs change needed?
+
+### TODO
+- [ ] Preview the changes you made either locally or in the Vercel deployment
+ and make sure it looks correct.
+- [ ] If you've added a new link to the sidebar navigation, make sure it's
+ sorted correctly.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..4257adb67e
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,17 @@
+### Description
+What does this PR do?
+
+### TODO only if you're a HashiCorp employee
+- [ ] **Backport Labels:** If this PR is in the ENT repo and needs to be backported, backport
+ to N, N-1, and N-2, using the `backport/ent/x.x.x+ent` labels. If this PR is in the CE repo, you should only backport to N, using the `backport/x.x.x` label, not the enterprise labels.
+ - [ ] If this fixes a critical security vulnerability or [severity 1](https://www.hashicorp.com/customer-success/enterprise-support) bug, it will also need to be backported to the current [LTS versions](https://developer.hashicorp.com/vault/docs/enterprise/lts#why-is-there-a-risk-to-updating-to-a-non-lts-vault-enterprise-version) of Vault. To ensure this, use **all** available enterprise labels.
+- [ ] **ENT Breakage:** If this PR either 1) removes a public function OR 2) changes the signature
+ of a public function, even if that change is in a CE file, _double check_ that
+ applying the patch for this PR to the ENT repo and running tests doesn't
+ break any tests. Sometimes ENT only tests rely on public functions in CE
+ files.
+- [ ] **Jira:** If this change has an associated Jira, it's referenced either
+ in the PR description, commit message, or branch name.
+- [ ] **RFC:** If this change has an associated RFC, please link it in the description.
+- [ ] **ENT PR:** If this change has an associated ENT PR, please link it in the
+ description. Also, make sure the changelog is in this PR, _not_ in your ENT PR.
diff --git a/.github/scripts/retry-command.sh b/.github/scripts/retry-command.sh
new file mode 100755
index 0000000000..76f0c902ba
--- /dev/null
+++ b/.github/scripts/retry-command.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+set -uo pipefail
+
+tries=5
+count=0
+
+until "$@"
+do
+ if [ $count -eq $tries ]; then
+ echo "tried $count times, exiting"
+ exit 1
+ fi
+ ((count++))
+ echo "trying again, attempt $count"
+ sleep $count
+done
diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml
index 38d2b167ff..1b8dcd89af 100644
--- a/.github/workflows/actionlint.yml
+++ b/.github/workflows/actionlint.yml
@@ -14,7 +14,7 @@ jobs:
actionlint:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: "Check workflow files"
uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint@sha256:93834930f56ca380be3e9a3377670d7aa5921be251b9c774891a39b3629b83b8
with:
diff --git a/.github/workflows/backport-ce.yml b/.github/workflows/backport-ce.yml
new file mode 100644
index 0000000000..ef684918fa
--- /dev/null
+++ b/.github/workflows/backport-ce.yml
@@ -0,0 +1,37 @@
+---
+name: Backport Assistant Runner (for OSS & ENT)
+
+on:
+ pull_request_target:
+ types:
+ - closed
+ - labeled
+ repository_dispatch:
+ types: [ent-backport]
+
+jobs:
+ backport-targeted-release-branch:
+ if: github.event.pull_request.merged && github.repository == 'hashicorp/vault'
+ runs-on: ubuntu-latest
+ container: hashicorpdev/backport-assistant:0.4.3
+ steps:
+ - name: Backport changes to targeted release branch
+ run: |
+ backport-assistant backport -merge-method=squash -gh-automerge
+ env:
+ BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+\\.[+\\w]+)"
+ BACKPORT_TARGET_TEMPLATE: "release/{{.target}}"
+ BACKPORT_MERGE_COMMIT: true
+ GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
+ ENABLE_VERSION_MANIFESTS: true
+ backport-ent:
+ if: github.event.pull_request.merged && contains(join(github.event.pull_request.labels.*.name), 'backport/ent')
+ runs-on: ubuntu-latest
+ steps:
+ - name: Trigger backport for Enterprise
+ uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0
+ with:
+ token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
+ repository: hashicorp/vault-enterprise
+ event-type: ent-backport
+ client-payload: ${{ toJson(github.event) }}
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
deleted file mode 100644
index f78464a8c8..0000000000
--- a/.github/workflows/backport.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-name: Backport Assistant Runner (for OSS & ENT)
-
-on:
- pull_request_target:
- types:
- - closed
- - labeled
-
-jobs:
- backport-targeted-release-branch:
- if: github.event.pull_request.merged
- runs-on: ubuntu-latest
- container: hashicorpdev/backport-assistant:0.3.3
- steps:
- - name: Backport changes to targeted release branch
- run: |
- backport-assistant backport -merge-method=squash -gh-automerge
- env:
- BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+\\.[+\\w]+)"
- BACKPORT_TARGET_TEMPLATE: "release/{{.target}}"
- BACKPORT_MERGE_COMMIT: true
- GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
diff --git a/.github/workflows/build-artifacts-ce.yml b/.github/workflows/build-artifacts-ce.yml
index 8e6233a403..c413ca1ac4 100644
--- a/.github/workflows/build-artifacts-ce.yml
+++ b/.github/workflows/build-artifacts-ce.yml
@@ -98,7 +98,7 @@ jobs:
runs-on: ${{ fromJSON(inputs.compute-build) }}
name: (${{ matrix.goos }}, ${{ matrix.goarch }})
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ inputs.checkout-ref }}
- uses: ./.github/actions/build-vault
@@ -200,7 +200,7 @@ jobs:
name: (${{ matrix.goos }}, ${{ matrix.goarch }}${{ matrix.goarm && ' ' || '' }}${{ matrix.goarm }})
runs-on: ${{ fromJSON(inputs.compute-build) }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ inputs.checkout-ref }}
- uses: ./.github/actions/build-vault
@@ -228,7 +228,7 @@ jobs:
- core
- extended
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ inputs.checkout-ref }}
- name: Determine status
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 10c720ac22..8a0e2bb055 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -105,7 +105,7 @@ jobs:
workflow-trigger: ${{ steps.metadata.outputs.workflow-trigger }}
steps:
# Run the changed-files action to determine what Git reference we should check out
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/changed-files
id: changed-files
- uses: ./.github/actions/checkout
@@ -159,7 +159,7 @@ jobs:
outputs:
cache-key: ui-${{ steps.ui-hash.outputs.ui-hash }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ needs.setup.outputs.checkout-ref }}
- name: Get UI hash
@@ -291,7 +291,7 @@ jobs:
- test
- test-containers
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- id: status
name: Determine status
run: |
@@ -387,7 +387,7 @@ jobs:
with:
version: ${{ needs.setup.outputs.vault-version-metadata }}
product: ${{ needs.setup.outputs.vault-binary-name }}
- - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
if: steps.generate-metadata-file.outcome == 'success' # upload our metadata if we created it
with:
name: metadata.json
diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml
index 034a8657ee..23ab8246a7 100644
--- a/.github/workflows/changelog-checker.yml
+++ b/.github/workflows/changelog-checker.yml
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0 # by default the checkout action doesn't checkout all branches
@@ -48,8 +48,8 @@ jobs:
echo "Not found."
echo ""
echo "Did not find a changelog entry named ${expected_changelog_file}"
- echo "If your changelog file is correct, skip this check with the 'pr/no-changelog' label"
- echo "Reference - https://github.com/hashicorp/vault/pull/10363 and https://github.com/hashicorp/vault/pull/11894"
+ echo "If your changelog file is correct, or this change does not need a changelog, skip this check with the 'pr/no-changelog' label"
+ echo "Reference - https://github.com/hashicorp/vault/blob/main/CONTRIBUTING.md#changelog-entries"
exit 1
fi
@@ -76,6 +76,12 @@ jobs:
elif grep -q ':fix$' "$changelog_files"; then
echo "Found invalid type (fix) in changelog - did you mean bug?"
exit 1
+ elif grep -q ':feature$' "$changelog_files"; then
+ if ! grep -q '^\*\*' "$changelog_files"; then
+ echo "Feature changelogs must be formatted like the following:"
+ echo "**Feature Name**: Feature description"
+ exit 1
+ fi
elif ! grep -q '```release-note:' "$changelog_files"; then
# People often make changelog files like ```changelog:, which is incorrect.
echo "Changelog file did not contain 'release-note' heading - check formatting."
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cd3b8fe544..81654f48be 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -33,7 +33,7 @@ jobs:
ui-changed: ${{ steps.changed-files.outputs.ui-changed }}
workflow-trigger: ${{ steps.metadata.outputs.workflow-trigger }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/changed-files
id: changed-files
- uses: ./.github/actions/checkout
@@ -146,7 +146,7 @@ jobs:
contents: read
runs-on: ${{ fromJSON(needs.setup.outputs.compute-test-ui) }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
name: status
with:
ref: ${{ needs.setup.outputs.checkout-ref }}
@@ -164,7 +164,10 @@ jobs:
node-version-file: './ui/package.json'
cache: yarn
cache-dependency-path: ui/yarn.lock
- - uses: browser-actions/setup-chrome@9683066f53b47e92c4104e1bd5535aff208c3530 # v1.6.2
+ - uses: browser-actions/setup-chrome@db1b524c26f20a8d1a10f7fc385c92387e2d0477 # v1.7.1
+ with:
+ # Temporarily pin our Chrome version while we sort out a broken test on latest
+ chrome-version: 1314712
- name: ui-dependencies
working-directory: ./ui
run: |
@@ -204,12 +207,12 @@ jobs:
mkdir -p test-results/qunit
yarn ${{ needs.setup.outputs.is-enterprise == 'true' && 'test' || 'test:oss' }}
- if: always()
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: test-results-ui
path: ui/test-results
- if: always()
- uses: test-summary/action@032c8a9cec6aaa3c20228112cae6ca10a3b29336 # v2.3
+ uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4
with:
paths: "ui/test-results/qunit/results.xml"
show: "fail"
@@ -226,7 +229,7 @@ jobs:
runs-on: ${{ github.repository == 'hashicorp/vault' && 'ubuntu-latest' || fromJSON('["self-hosted","linux","small"]') }}
permissions: write-all # Ensure we have id-token:write access for vault-auth.
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
# Determine the overall status of our required test jobs.
- name: Determine status
id: status
diff --git a/.github/workflows/code-checker.yml b/.github/workflows/code-checker.yml
index c40e53d718..0e4ff173e6 100644
--- a/.github/workflows/code-checker.yml
+++ b/.github/workflows/code-checker.yml
@@ -17,7 +17,7 @@ jobs:
name: Setup
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Ensure Go modules are cached
uses: ./.github/actions/set-up-go
with:
@@ -30,7 +30,7 @@ jobs:
needs: setup
if: github.base_ref == 'main'
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- uses: ./.github/actions/set-up-go
@@ -46,7 +46,7 @@ jobs:
needs: setup
if: github.base_ref == 'main'
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- uses: ./.github/actions/set-up-go
@@ -66,7 +66,7 @@ jobs:
runs-on: ubuntu-latest
needs: setup
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/set-up-go
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
@@ -79,7 +79,7 @@ jobs:
runs-on: ubuntu-latest
needs: setup
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/install-external-tools # for buf and gofumpt
- uses: ./.github/actions/set-up-go
with:
@@ -97,6 +97,6 @@ jobs:
container:
image: returntocorp/semgrep@sha256:cfad18cfb6536aa48ad5a71017207a10320b4e17e3b2bd7b7de27b42dc9651e7 #v1.58
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Run Semgrep Rules
run: semgrep ci --include '*.go' --config 'tools/semgrep/ci'
diff --git a/.github/workflows/copywrite.yml b/.github/workflows/copywrite.yml
index 8d978b5cba..da5f251d10 100644
--- a/.github/workflows/copywrite.yml
+++ b/.github/workflows/copywrite.yml
@@ -12,7 +12,7 @@ jobs:
copywrite:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: hashicorp/setup-copywrite@32638da2d4e81d56a0764aa1547882fc4d209636 # v1.1.3
name: Setup Copywrite
with:
diff --git a/.github/workflows/do-not-merge-checker.yml b/.github/workflows/do-not-merge-checker.yml
new file mode 100644
index 0000000000..5cff45f5cd
--- /dev/null
+++ b/.github/workflows/do-not-merge-checker.yml
@@ -0,0 +1,22 @@
+# This workflow fails if a 'do-not-merge' label is applied to the PR.
+name: Check do-not-merge
+
+on:
+ pull_request:
+ types: [reopened, labeled, unlabeled]
+ # Runs on PRs to main and release branches
+ branches:
+ - main
+ - release/**
+
+jobs:
+ # checks that a do-not-merge label is not present for a PR
+ do-not-merge-check:
+ # If there is a `do-not-merge` label we ignore this check
+ if: ${{ contains(github.event.pull_request.labels.*.name, 'do-not-merge') }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: Fail if do-not-merge label is applied
+ run: |
+ echo "Cannot merge with do-not-merge label applied."
+ exit 1
diff --git a/.github/workflows/enos-lint.yml b/.github/workflows/enos-lint.yml
index 39d4a620f3..65bb2377b7 100644
--- a/.github/workflows/enos-lint.yml
+++ b/.github/workflows/enos-lint.yml
@@ -17,7 +17,7 @@ jobs:
runs-on: ${{ steps.metadata.outputs.runs-on }}
version: ${{ steps.metadata.outputs.version }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- id: set-product-version
uses: hashicorp/actions-set-product-version@v2
- id: metadata
@@ -37,11 +37,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
ENOS_VAR_tfc_api_token: ${{ secrets.TF_API_TOKEN }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: hashicorp/setup-terraform@v3
with:
terraform_wrapper: false
- terraform_version: "1.7.5" # Pin until 1.8.x crash has been resolved
- uses: hashicorp/action-setup-enos@v1
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
diff --git a/.github/workflows/enos-release-testing-oss.yml b/.github/workflows/enos-release-testing-oss.yml
index 3ce6b6ab53..c648d5d2a9 100644
--- a/.github/workflows/enos-release-testing-oss.yml
+++ b/.github/workflows/enos-release-testing-oss.yml
@@ -15,7 +15,7 @@ jobs:
vault-version: ${{ github.event.client_payload.payload.version }}
vault-version-package: ${{ steps.get-metadata.outputs.vault-version-package }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
# Check out the repository at the same Git SHA that was used to create
# the artifacts to get the correct metadata.
@@ -64,7 +64,7 @@ jobs:
secrets: inherit
save-metadata:
- runs-on: linux
+ runs-on: ubuntu-latest
if: always()
needs: test
steps:
diff --git a/.github/workflows/enos-run-k8s.yml b/.github/workflows/enos-run-k8s.yml
index 440eb87ad9..fc5fd51f45 100644
--- a/.github/workflows/enos-run-k8s.yml
+++ b/.github/workflows/enos-run-k8s.yml
@@ -31,14 +31,13 @@ jobs:
GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
steps:
- name: Checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Terraform
uses: hashicorp/setup-terraform@v3
with:
# the Terraform wrapper will break Terraform execution in Enos because
# it changes the output to text when we expect it to be JSON.
terraform_wrapper: false
- terraform_version: "1.7.5" # Pin until 1.8.x crash has been resolved
- name: Set up Enos
uses: hashicorp/action-setup-enos@v1
with:
diff --git a/.github/workflows/oss.yml b/.github/workflows/oss.yml
index 9dedca7fbc..ae7c5c750d 100644
--- a/.github/workflows/oss.yml
+++ b/.github/workflows/oss.yml
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- if: github.event.pull_request != null
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- if: github.event.pull_request != null
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
@@ -68,7 +68,7 @@ jobs:
- if: github.event.pull_request != null && steps.changes.outputs.ui == 'true'
run: echo "PROJECT=171" >> "$GITHUB_ENV"
- - uses: actions/add-to-project@9bfe908f2eaa7ba10340b31e314148fcfe6a2458 # v1.0.1
+ - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2
with:
project-url: https://github.com/orgs/hashicorp/projects/${{ env.PROJECT }}
github-token: ${{ secrets.TRIAGE_GITHUB_TOKEN }}
diff --git a/.github/workflows/plugin-update-check.yml b/.github/workflows/plugin-update-check.yml
index 9d2407bfeb..36bc0d27e7 100644
--- a/.github/workflows/plugin-update-check.yml
+++ b/.github/workflows/plugin-update-check.yml
@@ -23,13 +23,13 @@ jobs:
RUN_ID: "${{github.run_id}}"
steps:
- run: echo "Branch $PLUGIN_BRANCH of $PLUGIN_REPO"
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
# We don't use the default token so that checks are executed on the resulting PR
# https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
- - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
+ - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
cache: false # save cache space for vault builds: https://github.com/hashicorp/vault/pull/21764
go-version-file: .go-version
diff --git a/.github/workflows/plugin-update.yml b/.github/workflows/plugin-update.yml
index 26c85ec2b3..55469104f0 100644
--- a/.github/workflows/plugin-update.yml
+++ b/.github/workflows/plugin-update.yml
@@ -8,6 +8,10 @@ on:
description: 'Full name of the plugin, e.g., vault-plugin-auth-kubernetes'
required: true
type: string
+ branch:
+ description: 'Git branch name to use'
+ required: true
+ type: string
version:
description: 'Version of the plugin with *NO* "v", e.g., 1.2.3'
required: true
@@ -21,16 +25,16 @@ jobs:
plugin-update:
runs-on: ubuntu-latest
env:
- VAULT_BRANCH: "update/${{ inputs.plugin }}/v${{ inputs.version }}"
+ VAULT_BRANCH: ${{ inputs.branch }}
REVIEWER: ${{ inputs.reviewer || github.actor }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
# We don't use the default token so that checks are executed on the resulting PR
# https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
- - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
+ - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
cache: false # save cache space for vault builds: https://github.com/hashicorp/vault/pull/21764
go-version-file: .go-version
diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml
index 9b8872e8ae..2ca6fcf599 100644
--- a/.github/workflows/security-scan.yml
+++ b/.github/workflows/security-scan.yml
@@ -15,17 +15,18 @@ on:
jobs:
scan:
- runs-on: ${{ fromJSON(vars.RUNNER_XL) }}
+ runs-on: ${{ github.repository == 'hashicorp/vault' && 'ubuntu-latest' || fromJSON('["self-hosted","ondemand","os=linux","type=c6a.4xlarge"]') }}
# The first check ensures this doesn't run on community-contributed PRs, who
# won't have the permissions to run this job.
- if: ${{ (github.repository != 'hashicorp/vault' || (github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name))
- && (github.actor != 'dependabot[bot]') && ( github.actor != 'hc-github-team-secure-vault-core') }}
-
+ if: |
+ (startsWith(github.repository, 'hashicorp/vault') || (github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name)) &&
+ github.actor != 'dependabot[bot]' &&
+ github.actor != 'hc-github-team-secure-vault-core'
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Go
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
+ uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
cache: false # save cache space for vault builds: https://github.com/hashicorp/vault/pull/21764
go-version-file: .go-version
@@ -36,7 +37,7 @@ jobs:
python-version: 3.x
- name: Clone Security Scanner repo
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: hashicorp/security-scanner
token: ${{ secrets.HASHIBOT_PRODSEC_GITHUB_TOKEN }}
diff --git a/.github/workflows/stable-website.yaml b/.github/workflows/stable-website.yaml
index e18a02ffbb..89a468bad3 100644
--- a/.github/workflows/stable-website.yaml
+++ b/.github/workflows/stable-website.yaml
@@ -15,7 +15,7 @@ jobs:
name: Cherry pick to stable-website branch
steps:
- name: Checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: stable-website
- run: |
diff --git a/.github/workflows/test-ci-bootstrap.yml b/.github/workflows/test-ci-bootstrap.yml
index 0a0222b567..9d030408cb 100644
--- a/.github/workflows/test-ci-bootstrap.yml
+++ b/.github/workflows/test-ci-bootstrap.yml
@@ -29,11 +29,9 @@ jobs:
TF_VAR_aws_ssh_public_key: ${{ secrets.SSH_KEY_PUBLIC_CI }}
TF_TOKEN_app_terraform_io: ${{ secrets.TF_API_TOKEN }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Terraform
uses: hashicorp/setup-terraform@v3
- with:
- terraform_version: "1.7.5" # Pin until 1.8.x crash has been resolved
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
diff --git a/.github/workflows/test-ci-cleanup.yml b/.github/workflows/test-ci-cleanup.yml
index c94d28fb4a..697ad2cca6 100644
--- a/.github/workflows/test-ci-cleanup.yml
+++ b/.github/workflows/test-ci-cleanup.yml
@@ -49,7 +49,7 @@ jobs:
role-skip-session-tagging: true
role-duration-seconds: 3600
mask-aws-account-id: false
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Configure
run: |
cp enos/ci/aws-nuke.yml .
diff --git a/.github/workflows/test-enos-scenario-ui.yml b/.github/workflows/test-enos-scenario-ui.yml
index 40009f1d84..7a8e9ce5f6 100644
--- a/.github/workflows/test-enos-scenario-ui.yml
+++ b/.github/workflows/test-enos-scenario-ui.yml
@@ -40,7 +40,7 @@ jobs:
runs-on: ${{ steps.get-metadata.outputs.runs-on }}
vault_edition: ${{ steps.get-metadata.outputs.vault_edition }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- id: get-metadata
env:
IS_ENT: ${{ startsWith(github.event.repository.name, 'vault-enterprise' ) }}
@@ -72,7 +72,7 @@ jobs:
GOPRIVATE: github.com/hashicorp
steps:
- name: Checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/set-up-go
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
@@ -90,7 +90,6 @@ jobs:
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
terraform_wrapper: false
- terraform_version: "1.7.5" # Pin until 1.8.x crash has been resolved
- name: Prepare scenario dependencies
run: |
mkdir -p ./enos/support/terraform-plugin-cache
@@ -109,7 +108,7 @@ jobs:
sudo apt install -y libnss3-dev libgdk-pixbuf2.0-dev libgtk-3-dev libxss-dev libasound2
- name: Install Chrome
if: steps.chrome-check.outputs.chrome-version == 'not-installed'
- uses: browser-actions/setup-chrome@9683066f53b47e92c4104e1bd5535aff208c3530 # v1.6.2
+ uses: browser-actions/setup-chrome@db1b524c26f20a8d1a10f7fc385c92387e2d0477 # v1.7.1
- name: Installed Chrome Version
run: |
echo "Installed Chrome Version = [$(chrome --version 2> /dev/null || google-chrome --version 2> /dev/null || google-chrome-stable --version 2> /dev/null)]"
diff --git a/.github/workflows/test-go.yml b/.github/workflows/test-go.yml
index c3a5d8ceae..67be67784f 100644
--- a/.github/workflows/test-go.yml
+++ b/.github/workflows/test-go.yml
@@ -95,7 +95,7 @@ jobs:
matrix: ${{ steps.build.outputs.matrix }}
matrix_ids: ${{ steps.build.outputs.matrix_ids }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ inputs.checkout-ref }}
- uses: ./.github/actions/set-up-go
@@ -230,7 +230,7 @@ jobs:
go-test-results-download-pattern: ${{ steps.metadata.outputs.go-test-results-download-pattern }}
data-race-log-download-pattern: ${{ steps.metadata.outputs.data-race-log-download-pattern }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ inputs.checkout-ref }}
- uses: ./.github/actions/set-up-go
@@ -421,8 +421,9 @@ jobs:
package_parallelism="-p 2"
fi
- # If running Go Test 32bit nightly tests, add a flag to rerun failed tests
- if [[ "${{inputs.name}}" == 'i386' ]]; then
+ # If running Go tests on the enterprise repo, add a flag to rerun failed tests.
+ # This is to address the issues with flaky tests affecting the reliability of CI.
+ if [[ "${{github.repository}}" == 'hashicorp/vault-enterprise' ]]; then
RERUN_FAILS="--rerun-fails"
fi
@@ -477,7 +478,7 @@ jobs:
run: |
tar -cvf '${{ steps.metadata.outputs.go-test-log-archive-name }}' -C "${{ steps.metadata.outputs.go-test-log-dir }}" .
- name: Upload test logs archives
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: ${{ steps.metadata.outputs.go-test-log-archive-name }}
path: ${{ steps.metadata.outputs.go-test-log-archive-name }}
@@ -485,7 +486,7 @@ jobs:
if: success() || failure()
- name: Upload test results
if: success() || failure()
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: ${{ steps.metadata.outputs.go-test-results-upload-key }}
path: |
@@ -525,7 +526,7 @@ jobs:
if: |
(success() || failure()) &&
steps.data-race-check.outputs.data-race-result == 'failure'
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: ${{ steps.metadata.outputs.data-race-log-upload-key }}
path: ${{ steps.metadata.outputs.go-test-dir }}/${{ steps.metadata.outputs.data-race-log-file }}
@@ -598,7 +599,7 @@ jobs:
'${{ steps.metadata.outputs.gotestsum-timing-events }}' \
>> '${{ steps.metadata.outputs.failure-summary-file-name }}'
- name: Upload failure summary
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
if: success() || failure()
with:
name: ${{ steps.metadata.outputs.failure-summary-file-name }}
diff --git a/.github/workflows/test-run-acc-tests-for-path.yml b/.github/workflows/test-run-acc-tests-for-path.yml
index 372647a1fe..7385905a26 100644
--- a/.github/workflows/test-run-acc-tests-for-path.yml
+++ b/.github/workflows/test-run-acc-tests-for-path.yml
@@ -20,12 +20,12 @@ jobs:
go-test:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/set-up-go
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
- run: go test -v ./${{ inputs.path }}/... 2>&1 | tee ${{ inputs.name }}.txt
- - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: ${{ inputs.name }}-output
path: ${{ inputs.name }}.txt
diff --git a/.github/workflows/test-run-enos-scenario-matrix.yml b/.github/workflows/test-run-enos-scenario-matrix.yml
index 15d80fad72..7b24738629 100644
--- a/.github/workflows/test-run-enos-scenario-matrix.yml
+++ b/.github/workflows/test-run-enos-scenario-matrix.yml
@@ -49,7 +49,7 @@ jobs:
sample: ${{ steps.metadata.outputs.sample }}
vault-version: ${{ steps.metadata.outputs.vault-version }}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ inputs.vault-revision }}
- uses: hashicorp/action-setup-enos@v1
@@ -58,7 +58,7 @@ jobs:
- id: metadata
run: |
build_date=$(make ci-get-date)
- sample_seed=$(date +%s%N)
+ sample_seed=$(date +%s)
sample=$(enos scenario sample observe "${{ inputs.sample-name }}" --chdir ./enos --min 1 --max "${{ inputs.sample-max }}" --seed "${sample_seed}" --format json | jq -c ".observation.elements")
if [[ "${{ inputs.vault-edition }}" == "ce" ]]; then
vault_version="${{ inputs.vault-version }}"
@@ -96,10 +96,16 @@ jobs:
ENOS_VAR_vault_build_date: ${{ needs.metadata.outputs.build-date }}
ENOS_VAR_vault_product_version: ${{ needs.metadata.outputs.vault-version }}
ENOS_VAR_vault_revision: ${{ inputs.vault-revision }}
+ ENOS_VAR_consul_license_path: ./support/consul.hclic
ENOS_VAR_vault_license_path: ./support/vault.hclic
+ ENOS_VAR_distro_version_amzz: ${{ matrix.attributes.distro_version_amzn }}
+ ENOS_VAR_distro_version_leap: ${{ matrix.attributes.distro_version_leap }}
+ ENOS_VAR_distro_version_rhel: ${{ matrix.attributes.distro_version_rhel }}
+ ENOS_VAR_distro_version_sles: ${{ matrix.attributes.distro_version_sles }}
+ ENOS_VAR_distro_version_ubuntu: ${{ matrix.attributes.distro_version_ubuntu }}
ENOS_DEBUG_DATA_ROOT_DIR: /tmp/enos-debug-data
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ inputs.vault-revision }}
- uses: hashicorp/setup-terraform@v3
@@ -107,7 +113,6 @@ jobs:
# the Terraform wrapper will break Terraform execution in Enos because
# it changes the output to text when we expect it to be JSON.
terraform_wrapper: false
- terraform_version: "1.7.5" # Pin until 1.8.x crash has been resolved
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_CI }}
@@ -134,6 +139,11 @@ jobs:
- if: contains(inputs.sample-name, 'ent')
name: Configure Vault license
run: echo "${{ secrets.VAULT_LICENSE }}" > ./enos/support/vault.hclic || true
+ - if: contains(matrix.scenario.id.filter, 'consul_edition:ent')
+ name: Configure Consul license
+ run: |
+ echo "matrix.scenario.id.filter: ${{ matrix.scenario.id.filter }}"
+ echo "${{ secrets.CONSUL_LICENSE }}" > ./enos/support/consul.hclic || true
- id: launch
name: enos scenario launch ${{ matrix.scenario.id.filter }}
# Continue once and retry to handle occasional blips when creating infrastructure.
@@ -145,7 +155,7 @@ jobs:
run: enos scenario launch --timeout 60m0s --chdir ./enos ${{ matrix.scenario.id.filter }}
- name: Upload Debug Data
if: failure()
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
# The name of the artifact is the same as the matrix scenario name with the spaces replaced with underscores and colons replaced by equals.
name: ${{ steps.prepare_scenario.outputs.debug_data_artifact_name }}
@@ -175,28 +185,28 @@ jobs:
# https://api.slack.com/apps/A05E31CH1LG/incoming-webhooks
- if: ${{ always() && ! cancelled() }}
name: Notify launch failed
- uses: hashicorp/actions-slack-status@v2
+ uses: hashicorp/actions-slack-status@v2.0.1
with:
failure-message: "enos scenario launch ${{ matrix.scenario.id.filter}} failed. \nTriggering event: `${{ github.event_name }}` \nActor: `${{ github.actor }}`"
status: ${{ steps.launch.outcome }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
- if: ${{ always() && ! cancelled() }}
name: Notify retry launch failed
- uses: hashicorp/actions-slack-status@v2
+ uses: hashicorp/actions-slack-status@v2.0.1
with:
failure-message: "retry enos scenario launch ${{ matrix.scenario.id.filter}} failed. \nTriggering event: `${{ github.event_name }}` \nActor: `${{ github.actor }}`"
status: ${{ steps.launch_retry.outcome }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
- if: ${{ always() && ! cancelled() }}
name: Notify destroy failed
- uses: hashicorp/actions-slack-status@v2
+ uses: hashicorp/actions-slack-status@v2.0.1
with:
failure-message: "enos scenario destroy ${{ matrix.scenario.id.filter}} failed. \nTriggering event: `${{ github.event_name }}` \nActor: `${{ github.actor }}`"
status: ${{ steps.destroy.outcome }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
- if: ${{ always() && ! cancelled() }}
name: Notify retry destroy failed
- uses: hashicorp/actions-slack-status@v2
+ uses: hashicorp/actions-slack-status@v2.0.1
with:
failure-message: "retry enos scenario destroy ${{ matrix.scenario.id.filter}} failed. \nTriggering event: `${{ github.event_name }}` \nActor: `${{ github.actor }}`"
status: ${{ steps.destroy_retry.outcome }}
diff --git a/.go-version b/.go-version
index 6fee2fedb0..da9594fd66 100644
--- a/.go-version
+++ b/.go-version
@@ -1 +1 @@
-1.22.2
+1.22.5
diff --git a/.release/versions.hcl b/.release/versions.hcl
new file mode 100644
index 0000000000..f1db6233a6
--- /dev/null
+++ b/.release/versions.hcl
@@ -0,0 +1,18 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+# This manifest file describes active releases and is consumed by the backport tooling.
+
+schema = 1
+active_versions {
+ version "1.17.x" {
+ ce_active = true
+ }
+ version "1.16.x" {
+ ce_active = false
+ lts = true
+ }
+ version "1.15.x" {
+ ce_active = false
+ }
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04ef632a15..284825c4af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,445 @@
- [v1.0.0 - v1.9.10](CHANGELOG-pre-v1.10.md)
- [v0.11.6 and earlier](CHANGELOG-v0.md)
+## 1.17.3
+### August 07, 2024
+
+CHANGES:
+
+* auth/cf: Update plugin to v0.18.0 [[GH-27724](https://github.com/hashicorp/vault/pull/27724)]
+
+IMPROVEMENTS:
+
+* audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success. [[GH-27809](https://github.com/hashicorp/vault/pull/27809)]
+* audit: Internal implementation changes to the audit subsystem which improve performance. [[GH-27952](https://github.com/hashicorp/vault/pull/27952)]
+* audit: sinks (file, socket, syslog) will attempt to log errors to the server operational
+log before returning (if there are errors to log, and the context is done). [[GH-27859](https://github.com/hashicorp/vault/pull/27859)]
+* auth/cert: Cache full list of role trust information separately to avoid
+eviction, and avoid duplicate loading during multiple simultaneous logins on
+the same role. [[GH-27902](https://github.com/hashicorp/vault/pull/27902)]
+* license utilization reporting (enterprise): Auto-roll billing start date. [[GH-27656](https://github.com/hashicorp/vault/pull/27656)]
+* website/docs: Added API documentation for Azure Secrets Engine delete role [[GH-27883](https://github.com/hashicorp/vault/pull/27883)]
+
+BUG FIXES:
+
+* auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors [[GH-27696](https://github.com/hashicorp/vault/pull/27696)]
+* core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured. [[GH-27939](https://github.com/hashicorp/vault/pull/27939)]
+* core/identity: Fixed an issue where deleted/reassigned entity-aliases were not removed from in-memory database. [[GH-27750](https://github.com/hashicorp/vault/pull/27750)]
+* proxy/cache (enterprise): Fixed an issue where Proxy would not correctly update KV secrets when talking to a perf standby. Proxy will now attempt to forward requests to update secrets triggered by events to the active node. Note that this requires `allow_forwarding_via_header` to be configured on the cluster. [[GH-27891](https://github.com/hashicorp/vault/pull/27891)]
+* proxy/cache (enterprise): Fixed an issue where cached static secrets could fail to update if the secrets belonged to a non-root namespace. [[GH-27730](https://github.com/hashicorp/vault/pull/27730)]
+* raft/autopilot: Fixed panic that may occur during shutdown [[GH-27726](https://github.com/hashicorp/vault/pull/27726)]
+* secrets-sync (enterprise): Destination set/remove operations will no longer be blocked as "purge in progress" after a purge job ended in failure.
+* secrets-sync (enterprise): Normalize custom_tag keys and values for recoverable invalid characters.
+* secrets-sync (enterprise): Normalize secret key names before storing the external_name in a secret association.
+* secrets-sync (enterprise): Patching github sync destination credentials will properly update and save the new credentials.
+* secrets-sync (enterprise): Return an error immediately on destination creation when providing invalid custom_tags based on destination type.
+* secrets/identity (enterprise): Fix a bug that can cause DR promotion to fail in rare cases where a PR secondary has inconsistent alias information in storage.
+* sys: Fix a bug where mounts of external plugins that were registered before Vault v1.0.0 could not be tuned to
+use versioned plugins. [[GH-27881](https://github.com/hashicorp/vault/pull/27881)]
+* ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER. [[GH-27569](https://github.com/hashicorp/vault/pull/27569)]
+* ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call. [[GH-27742](https://github.com/hashicorp/vault/pull/27742)]
+* ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default. [[GH-27728](https://github.com/hashicorp/vault/pull/27728)]
+
+
+## 1.17.2
+### July 10, 2024
+
+CHANGES:
+
+* core: Bump Go version to 1.22.5
+* secrets/azure: Update plugin to v0.19.2 [[GH-27652](https://github.com/hashicorp/vault/pull/27652)]
+
+FEATURES:
+
+* **AWS secrets engine STS session tags support**: Adds support for setting STS
+session tags when generating temporary credentials using the AWS secrets
+engine. [[GH-27620](https://github.com/hashicorp/vault/pull/27620)]
+
+BUG FIXES:
+
+* cli: Fixed issue with `vault hcp connect` where HCP resources with uppercase letters were inaccessible when entering the correct project name. [[GH-27694](https://github.com/hashicorp/vault/pull/27694)]
+* core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme. [[GH-27660](https://github.com/hashicorp/vault/pull/27660)]
+* core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`,
+which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection. [[GH-27589](https://github.com/hashicorp/vault/pull/27589)]
+* core: Fixed an issue with performance standbys not being able to handle rotate root requests. [[GH-27631](https://github.com/hashicorp/vault/pull/27631)]
+* secrets/transit (enterprise): Fix an issue that caused input data be returned as part of generated CMAC values.
+* ui: Display an error and force a timeout when TOTP passcode is incorrect [[GH-27574](https://github.com/hashicorp/vault/pull/27574)]
+* ui: Ensure token expired banner displays when batch token expires [[GH-27479](https://github.com/hashicorp/vault/pull/27479)]
+
+## 1.17.1
+### June 26, 2024
+
+CHANGES:
+
+* auth/jwt: Update plugin to v0.21.0 [[GH-27498](https://github.com/hashicorp/vault/pull/27498)]
+
+IMPROVEMENTS:
+
+* storage/raft: Improve autopilot logging on startup to show config values clearly and avoid spurious logs [[GH-27464](https://github.com/hashicorp/vault/pull/27464)]
+* ui/secrets-sync: Hide Secrets Sync from the sidebar nav if user does not have access to the feature. [[GH-27262](https://github.com/hashicorp/vault/pull/27262)]
+
+BUG FIXES:
+
+* agent: Fixed an issue causing excessive CPU usage during normal operation [[GH-27518](https://github.com/hashicorp/vault/pull/27518)]
+* config: Vault TCP listener config now correctly supports the documented proxy_protocol_behavior
+setting of 'deny_unauthorized' [[GH-27459](https://github.com/hashicorp/vault/pull/27459)]
+* core/audit: Audit logging a Vault request/response checks if the existing context
+is cancelled and will now use a new context with a 5 second timeout.
+If the existing context is cancelled a new context, will be used. [[GH-27531](https://github.com/hashicorp/vault/pull/27531)]
+* helper/pkcs7: Fix parsing certain messages containing only certificates [[GH-27435](https://github.com/hashicorp/vault/pull/27435)]
+* proxy: Fixed an issue causing excessive CPU usage during normal operation [[GH-27518](https://github.com/hashicorp/vault/pull/27518)]
+* replication (enterprise): fix cache invalidation issue leading to namespace custom metadata not being shown correctly on performance secondaries
+* secrets-sync (enterprise): Properly remove tags from secrets in AWS when they are removed from the source association
+* secrets-sync (enterprise): Return more accurate error code for invalid connection details
+* secrets-sync (enterprise): Skip invalid GitHub repository names when creating destinations
+* storage/azure: Fix invalid account name initialization bug [[GH-27563](https://github.com/hashicorp/vault/pull/27563)]
+* storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses. [[GH-27474](https://github.com/hashicorp/vault/pull/27474)]
+* ui: Allow creation of session_token type roles for AWS secret backend [[GH-27424](https://github.com/hashicorp/vault/pull/27424)]
+
+## 1.17.0
+### June 12, 2024
+
+SECURITY:
+
+* auth/jwt: Update plugin to v0.20.3 that resolves a security issue with validing JWTs [[GH-26890](https://github.com/hashicorp/vault/pull/26890), [HCSEC-2024-11](https://discuss.hashicorp.com/t/hcsec-2024-11-vault-incorrectly-validated-json-web-tokens-jwt-audience-claims/67770)]
+
+CHANGES:
+
+* api: Upgrade from github.com/go-jose/go-jose/v3 v3.0.3 to github.com/go-jose/go-jose/v4 v4.0.1. [[GH-26527](https://github.com/hashicorp/vault/pull/26527)]
+* audit: breaking change - Vault now allows audit logs to contain 'correlation-id' and 'x-correlation-id' headers when they
+are present in the incoming request. By default they are not HMAC'ed (but can be configured to HMAC by Vault Operators). [[GH-26777](https://github.com/hashicorp/vault/pull/26777)]
+* auth/alicloud: Update plugin to v0.18.0 [[GH-27133](https://github.com/hashicorp/vault/pull/27133)]
+* auth/azure: Update plugin to v0.18.0 [[GH-27146](https://github.com/hashicorp/vault/pull/27146)]
+* auth/centrify: Remove the deprecated Centrify auth method plugin [[GH-27130](https://github.com/hashicorp/vault/pull/27130)]
+* auth/cf: Update plugin to v0.17.0 [[GH-27161](https://github.com/hashicorp/vault/pull/27161)]
+* auth/gcp: Update plugin to v0.18.0 [[GH-27140](https://github.com/hashicorp/vault/pull/27140)]
+* auth/jwt: Update plugin to v0.20.2 [[GH-26291](https://github.com/hashicorp/vault/pull/26291)]
+* auth/kerberos: Update plugin to v0.12.0 [[GH-27177](https://github.com/hashicorp/vault/pull/27177)]
+* auth/kubernetes: Update plugin to v0.19.0 [[GH-27186](https://github.com/hashicorp/vault/pull/27186)]
+* auth/oci: Update plugin to v0.16.0 [[GH-27142](https://github.com/hashicorp/vault/pull/27142)]
+* core (enterprise): Seal High Availability (HA) must be enabled by `enable_multiseal` in configuration.
+* core/identity: improve performance for secondary nodes receiving identity related updates through replication [[GH-27184](https://github.com/hashicorp/vault/pull/27184)]
+* core: Bump Go version to 1.22.4
+* core: return an additional "invalid token" error message in 403 response when the provided request token is expired,
+exceeded the number of uses, or is a bogus value [[GH-25953](https://github.com/hashicorp/vault/pull/25953)]
+* database/couchbase: Update plugin to v0.11.0 [[GH-27145](https://github.com/hashicorp/vault/pull/27145)]
+* database/elasticsearch: Update plugin to v0.15.0 [[GH-27136](https://github.com/hashicorp/vault/pull/27136)]
+* database/mongodbatlas: Update plugin to v0.12.0 [[GH-27143](https://github.com/hashicorp/vault/pull/27143)]
+* database/redis-elasticache: Update plugin to v0.4.0 [[GH-27139](https://github.com/hashicorp/vault/pull/27139)]
+* database/redis: Update plugin to v0.3.0 [[GH-27117](https://github.com/hashicorp/vault/pull/27117)]
+* database/snowflake: Update plugin to v0.11.0 [[GH-27132](https://github.com/hashicorp/vault/pull/27132)]
+* sdk: String templates now have a maximum size of 100,000 characters. [[GH-26110](https://github.com/hashicorp/vault/pull/26110)]
+* secrets/ad: Update plugin to v0.18.0 [[GH-27172](https://github.com/hashicorp/vault/pull/27172)]
+* secrets/alicloud: Update plugin to v0.17.0 [[GH-27134](https://github.com/hashicorp/vault/pull/27134)]
+* secrets/azure: Update plugin to v0.17.1 [[GH-26528](https://github.com/hashicorp/vault/pull/26528)]
+* secrets/azure: Update plugin to v0.19.0 [[GH-27141](https://github.com/hashicorp/vault/pull/27141)]
+* secrets/gcp: Update plugin to v0.19.0 [[GH-27164](https://github.com/hashicorp/vault/pull/27164)]
+* secrets/gcpkms: Update plugin to v0.17.0 [[GH-27163](https://github.com/hashicorp/vault/pull/27163)]
+* secrets/keymgmt (enterprise): Removed `namespace` label on the `vault.kmse.key.count` metric.
+* secrets/kmip (enterprise): Update plugin to v0.15.0
+* secrets/kubernetes: Update plugin to v0.8.0 [[GH-27187](https://github.com/hashicorp/vault/pull/27187)]
+* secrets/kv: Update plugin to v0.18.0 [[GH-26877](https://github.com/hashicorp/vault/pull/26877)]
+* secrets/kv: Update plugin to v0.19.0 [[GH-27159](https://github.com/hashicorp/vault/pull/27159)]
+* secrets/mongodbatlas: Update plugin to v0.12.0 [[GH-27149](https://github.com/hashicorp/vault/pull/27149)]
+* secrets/openldap: Update plugin to v0.13.0 [[GH-27137](https://github.com/hashicorp/vault/pull/27137)]
+* secrets/pki: sign-intermediate API will truncate notAfter if calculated to go beyond the signing issuer's notAfter. Previously the notAfter was permitted to go beyond leading to invalid chains. [[GH-26796](https://github.com/hashicorp/vault/pull/26796)]
+* secrets/terraform: Update plugin to v0.8.0 [[GH-27147](https://github.com/hashicorp/vault/pull/27147)]
+* ui/kubernetes: Update the roles filter-input to use explicit search. [[GH-27178](https://github.com/hashicorp/vault/pull/27178)]
+* ui: Update dependencies including D3 libraries [[GH-26346](https://github.com/hashicorp/vault/pull/26346)]
+* ui: Upgrade Ember data from 4.11.3 to 4.12.4 [[GH-25272](https://github.com/hashicorp/vault/pull/25272)]
+* ui: Upgrade Ember to version 5.4 [[GH-26708](https://github.com/hashicorp/vault/pull/26708)]
+* ui: deleting a nested secret will no longer redirect you to the nearest path segment [[GH-26845](https://github.com/hashicorp/vault/pull/26845)]
+* ui: flash messages render on right side of page [[GH-25459](https://github.com/hashicorp/vault/pull/25459)]
+
+FEATURES:
+
+* **PKI Certificate Metadata (enterprise)**: Add Certificate Metadata Functionality to Record and Return Client Information about a Certificate.
+* **Adaptive Overload Protection (enterprise)**: Adds Adaptive Overload Protection
+for write requests as a Beta feature (disabled by default). This automatically
+prevents overloads caused by too many write requests while maintaining optimal
+throughput for the hardware configuration and workload.
+* **Audit Filtering (enterprise)** : Audit devices support expression-based filter rules (powered by go-bexpr) to determine which entries are written to the audit log.
+* **LDAP Secrets engine hierarchical path support**: Hierarchical path handling is now supported for role and set APIs. [[GH-27203](https://github.com/hashicorp/vault/pull/27203)]
+* **Plugin Identity Tokens**: Adds secret-less configuration of AWS auth engine using web identity federation. [[GH-26507](https://github.com/hashicorp/vault/pull/26507)]
+* **Plugin Workload Identity** (enterprise): Vault can generate identity tokens for plugins to use in workload identity federation auth flows.
+* **Transit AES-CMAC (enterprise)**: Added support to create and verify AES backed cipher-based message authentication codes
+
+IMPROVEMENTS:
+
+* activity (enterprise): Change minimum retention window in activity log to 48 months
+* agent: Added a new config option, `lease_renewal_threshold`, that controls the refresh rate of non-renewable leases in Agent's template engine. [[GH-25212](https://github.com/hashicorp/vault/pull/25212)]
+* agent: Agent will re-trigger auto auth if token used for rendering templates has been revoked, has exceeded the number of uses, or is a bogus value. [[GH-26172](https://github.com/hashicorp/vault/pull/26172)]
+* api: Move CLI token helper functions to importable packages in `api` module. [[GH-25744](https://github.com/hashicorp/vault/pull/25744)]
+* audit: timestamps across multiple audit devices for an audit entry will now match. [[GH-26088](https://github.com/hashicorp/vault/pull/26088)]
+* auth/aws: Add inferred_hostname metadata for IAM AWS authentication method. [[GH-25418](https://github.com/hashicorp/vault/pull/25418)]
+* auth/aws: add canonical ARN as entity alias option [[GH-22460](https://github.com/hashicorp/vault/pull/22460)]
+* auth/aws: add support for external_ids in AWS assume-role [[GH-26628](https://github.com/hashicorp/vault/pull/26628)]
+* auth/cert: Adds support for TLS certificate authenticaion through a reverse proxy that terminates the SSL connection [[GH-17272](https://github.com/hashicorp/vault/pull/17272)]
+* cli: Add events subscriptions commands
+* command/server: Removed environment variable requirement to generate pprof
+files using SIGUSR2. Added CPU profile support. [[GH-25391](https://github.com/hashicorp/vault/pull/25391)]
+* core (enterprise): persist seal rewrap status, so rewrap status API is consistent on secondary nodes.
+* core/activity: Include ACME client metrics to precomputed queries [[GH-26519](https://github.com/hashicorp/vault/pull/26519)]
+* core/activity: Include ACME clients in activity log responses [[GH-26020](https://github.com/hashicorp/vault/pull/26020)]
+* core/activity: Include ACME clients in vault operator usage response [[GH-26525](https://github.com/hashicorp/vault/pull/26525)]
+* core/config: reload service registration configuration on SIGHUP [[GH-17598](https://github.com/hashicorp/vault/pull/17598)]
+* core: add deadlock detection in barrier and sealwrap
+* license utilization reporting (enterprise): Add retention months to license utilization reports.
+* proxy/cache (enterprise): Support new configuration parameter for static secret caching, `static_secret_token_capability_refresh_behavior`, to control the behavior when the capability refresh request receives an error from Vault.
+* proxy: Proxy will re-trigger auto auth if the token used for requests has been revoked, has exceeded the number of uses,
+or is an otherwise invalid value. [[GH-26307](https://github.com/hashicorp/vault/pull/26307)]
+* raft/snapshotagent (enterprise): upgrade raft-snapshotagent to v0.0.0-20221104090112-13395acd02c5
+* replication (enterprise): Add replication heartbeat metric to telemetry
+* replication (enterprise): Periodically write current time on the primary to storage, use that downstream to measure replication lag in time, expose that in health and replication status endpoints. [[GH-26406](https://github.com/hashicorp/vault/pull/26406)]
+* sdk/decompression: DecompressWithCanary will now chunk the decompression in memory to prevent loading it all at once. [[GH-26464](https://github.com/hashicorp/vault/pull/26464)]
+* sdk/helper/testcluster: add some new helpers, improve some error messages. [[GH-25329](https://github.com/hashicorp/vault/pull/25329)]
+* sdk/helper/testhelpers: add namespace helpers [[GH-25270](https://github.com/hashicorp/vault/pull/25270)]
+* secrets-sync (enterprise): Added global config path to the administrative namespace.
+* secrets/pki (enterprise): Disable warnings about unknown parameters to the various CIEPS endpoints
+* secrets/pki: Add a new ACME configuration parameter that allows increasing the maximum TTL for ACME leaf certificates [[GH-26797](https://github.com/hashicorp/vault/pull/26797)]
+* secrets/transform (enterprise): Add delete by token and delete by plaintext operations to Tokenization.
+* storage/azure: Perform validation on Azure account name and container name [[GH-26135](https://github.com/hashicorp/vault/pull/26135)]
+* storage/raft (enterprise): add support for separate entry size limit for mount
+and namespace table paths in storage to allow increased mount table size without
+allowing other user storage entries to become larger. [[GH-25992](https://github.com/hashicorp/vault/pull/25992)]
+* storage/raft: panic on unknown Raft operations [[GH-25991](https://github.com/hashicorp/vault/pull/25991)]
+* ui (enterprise): Allow HVD users to access Secrets Sync. [[GH-26841](https://github.com/hashicorp/vault/pull/26841)]
+* ui (enterprise): Update dashboard to make activity log query using the same start time as the metrics overview [[GH-26729](https://github.com/hashicorp/vault/pull/26729)]
+* ui (enterprise): Update filters on the custom messages list view. [[GH-26653](https://github.com/hashicorp/vault/pull/26653)]
+* ui: Allow users to wrap inputted data again instead of resetting form [[GH-27289](https://github.com/hashicorp/vault/pull/27289)]
+* ui: Display ACME clients on a separate page in the UI. [[GH-26020](https://github.com/hashicorp/vault/pull/26020)]
+* ui: Hide dashboard client count card if user does not have permission to view clients. [[GH-26848](https://github.com/hashicorp/vault/pull/26848)]
+* ui: Show computed values from `sys/internal/ui/mounts` endpoint for auth mount configuration view [[GH-26663](https://github.com/hashicorp/vault/pull/26663)]
+* ui: Update PGP display and show error for Generate Operation Token flow with PGP [[GH-26993](https://github.com/hashicorp/vault/pull/26993)]
+* ui: Update language in Transit secret engine to reflect that not all keys are for encyryption [[GH-27346](https://github.com/hashicorp/vault/pull/27346)]
+* ui: Update userpass user form to allow setting `password_hash` field. [[GH-26577](https://github.com/hashicorp/vault/pull/26577)]
+* ui: fixes cases where inputs did not have associated labels [[GH-26263](https://github.com/hashicorp/vault/pull/26263)]
+* ui: show banner instead of permission denied error when batch token is expired [[GH-26396](https://github.com/hashicorp/vault/pull/26396)]
+* website/docs: Add note about eventual consietency with the MongoDB Atlas database secrets engine [[GH-24152](https://github.com/hashicorp/vault/pull/24152)]
+
+DEPRECATIONS:
+
+* Request Limiter Beta(enterprise): This Beta feature added in 1.16 has been
+superseded by Adaptive Overload Protection and will be removed.
+* secrets/azure: Deprecate field "password_policy" as we are not able to set it anymore with the new MS Graph API. [[GH-25637](https://github.com/hashicorp/vault/pull/25637)]
+
+BUG FIXES:
+
+* activity (enterprise): fix read-only storage error on upgrades
+* agent: Correctly constructs kv-v2 secret paths in nested namespaces. [[GH-26863](https://github.com/hashicorp/vault/pull/26863)]
+* agent: Fixes a high Vault load issue, by restarting the Conusl template server after backing off instead of immediately. [[GH-25497](https://github.com/hashicorp/vault/pull/25497)]
+* agent: `vault.namespace` no longer gets incorrectly overridden by `auto_auth.namespace`, if set [[GH-26427](https://github.com/hashicorp/vault/pull/26427)]
+* api: fixed a bug where LifetimeWatcher routines weren't respecting exponential backoff in the presence of unexpected errors [[GH-26383](https://github.com/hashicorp/vault/pull/26383)]
+* audit: Operator changes to configured audit headers (via `/sys/config/auditing`)
+will now force invalidation and be reloaded from storage when data is replicated
+to other nodes.
+* auth/ldap: Fix login error for group search anonymous bind. [[GH-26200](https://github.com/hashicorp/vault/pull/26200)]
+* auth/ldap: Fix login error missing entity alias attribute value. [[GH-26200](https://github.com/hashicorp/vault/pull/26200)]
+* auto-auth: Addressed issue where having no permissions to renew a renewable token caused auto-auth to attempt to renew constantly with no backoff [[GH-26844](https://github.com/hashicorp/vault/pull/26844)]
+* cli/debug: Fix resource leak in CLI debug command. [[GH-26167](https://github.com/hashicorp/vault/pull/26167)]
+* cli: fixed a bug where the Vault CLI would error out if
+HOME was not set. [[GH-26243](https://github.com/hashicorp/vault/pull/26243)]
+* core (enterprise): Fix 403s returned when forwarding invalid token to active node from secondary.
+* core (enterprise): Fix an issue that prevented the seal re-wrap status from reporting that a re-wrap is in progress for up to a second.
+* core (enterprise): fix bug where raft followers disagree with the seal type after returning to one seal from two. [[GH-26523](https://github.com/hashicorp/vault/pull/26523)]
+* core (enterprise): fix issue where the Seal HA rewrap system may remain running when an active node steps down.
+* core/audit: Audit logging a Vault request/response will now use a minimum 5 second context timeout.
+If the existing context deadline occurs later than 5s in the future, it will be used, otherwise a
+new context, separate from the original will be used. [[GH-26616](https://github.com/hashicorp/vault/pull/26616)]
+* core/metrics: store cluster name in unencrypted storage to prevent blank cluster name [[GH-26878](https://github.com/hashicorp/vault/pull/26878)]
+* core/namespace (enterprise): Privileged namespace paths provided in the `administrative_namespace_path` config will now be canonicalized.
+* core/seal: During a seal reload through SIGHUP, only write updated seal barrier on an active node [[GH-26381](https://github.com/hashicorp/vault/pull/26381)]
+* core/seal: allow overriding of VAULT_GCPCKMS_SEAL_KEY_RING and VAULT_GCPCKMS_SEAL_CRYPTO_KEY environment keys in seal-ha
+* core: Add missing field delegated_auth_accessors to GET /sys/mounts/:path API response [[GH-26876](https://github.com/hashicorp/vault/pull/26876)]
+* core: Address a data race updating a seal's last seen healthy time attribute [[GH-27014](https://github.com/hashicorp/vault/pull/27014)]
+* core: Fix `redact_version` listener parameter being ignored for some OpenAPI related endpoints. [[GH-26607](https://github.com/hashicorp/vault/pull/26607)]
+* core: Only reload seal configuration when enable_multiseal is set to true. [[GH-26166](https://github.com/hashicorp/vault/pull/26166)]
+* core: when listener configuration `chroot_namespace` is active, Vault will no longer report that the configuration is invalid when Vault is sealed
+* events (enterprise): Fix bug preventing subscribing and receiving events within a namepace.
+* events (enterprise): Terminate WebSocket connection when token is revoked.
+* openapi: Fixing approle reponse duration types [[GH-25510](https://github.com/hashicorp/vault/pull/25510)]
+* openapi: added the missing migrate parameter for the unseal endpoint in vault/logical_system_paths.go [[GH-25550](https://github.com/hashicorp/vault/pull/25550)]
+* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)]
+* plugin/wif: fix a bug where the namespace was not set for external plugins using workload identity federation [[GH-26384](https://github.com/hashicorp/vault/pull/26384)]
+* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster
+* replication (enterprise): fixed data integrity issue with the processing of identity aliases causing duplicates to occur in rare cases
+* router: Fix missing lock in MatchingSystemView. [[GH-25191](https://github.com/hashicorp/vault/pull/25191)]
+* secret/database: Fixed race condition where database mounts may leak connections [[GH-26147](https://github.com/hashicorp/vault/pull/26147)]
+* secrets-sync (enterprise): Fixed an issue with syncing to target projects in GCP
+* secrets/azure: Update vault-plugin-secrets-azure to 0.17.2 to include a bug fix for azure role creation [[GH-26896](https://github.com/hashicorp/vault/pull/26896)]
+* secrets/pki (enterprise): cert_role parameter within authenticators.cert EST configuration handler could not be set
+* secrets/pki: fixed validation bug which rejected ldap schemed URLs in crl_distribution_points. [[GH-26477](https://github.com/hashicorp/vault/pull/26477)]
+* secrets/transform (enterprise): Fix a bug preventing the use of alternate schemas on PostgreSQL token stores.
+* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)]
+* storage/raft (enterprise): Fix a bug where autopilot automated upgrades could fail due to using the wrong upgrade version
+* storage/raft (enterprise): Fix a regression introduced in 1.15.8 that causes
+autopilot to fail to discover new server versions and so not trigger an upgrade. [[GH-27277](https://github.com/hashicorp/vault/pull/27277)]
+* storage/raft: prevent writes from impeding leader transfers, e.g. during automated upgrades [[GH-25390](https://github.com/hashicorp/vault/pull/25390)]
+* transform (enterprise): guard against a panic looking up a token in exportable mode with barrier storage.
+* ui: Do not show resultant-ACL banner when ancestor namespace grants wildcard access. [[GH-27263](https://github.com/hashicorp/vault/pull/27263)]
+* ui: Fix KVv2 cursor jumping inside json editor after initial input. [[GH-27120](https://github.com/hashicorp/vault/pull/27120)]
+* ui: Fix KVv2 json editor to allow null values. [[GH-27094](https://github.com/hashicorp/vault/pull/27094)]
+* ui: Fix a bug where disabling TTL on the AWS credential form would still send TTL value [[GH-27366](https://github.com/hashicorp/vault/pull/27366)]
+* ui: Fix broken help link in console for the web command. [[GH-26858](https://github.com/hashicorp/vault/pull/26858)]
+* ui: Fix configuration link from Secret Engine list view for Ember engines. [[GH-27131](https://github.com/hashicorp/vault/pull/27131)]
+* ui: Fix link to v2 generic secrets engine from secrets list page. [[GH-27019](https://github.com/hashicorp/vault/pull/27019)]
+* ui: Prevent perpetual loading screen when Vault needs initialization [[GH-26985](https://github.com/hashicorp/vault/pull/26985)]
+* ui: Refresh model within a namespace on the Secrets Sync overview page. [[GH-26790](https://github.com/hashicorp/vault/pull/26790)]
+* ui: Remove possibility of returning an undefined timezone from date-format helper [[GH-26693](https://github.com/hashicorp/vault/pull/26693)]
+* ui: Resolved accessibility issues with Web REPL. Associated label and help text with input, added a conditional to show the console/ui-panel only when toggled open, added keyboard focus trap. [[GH-26872](https://github.com/hashicorp/vault/pull/26872)]
+* ui: fix issue where a month without new clients breaks the client count dashboard [[GH-27352](https://github.com/hashicorp/vault/pull/27352)]
+* ui: fixed a bug where the replication pages did not update display when navigating between DR and performance [[GH-26325](https://github.com/hashicorp/vault/pull/26325)]
+* ui: fixes undefined start time in filename for downloaded client count attribution csv [[GH-26485](https://github.com/hashicorp/vault/pull/26485)]
+
+## 1.16.7 Enterprise
+### August 07, 2024
+
+**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release.
+
+CHANGES:
+
+* auth/cf: Update plugin to v0.18.0 [[GH-27724](https://github.com/hashicorp/vault/pull/27724)]
+
+IMPROVEMENTS:
+
+* audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success. [[GH-27809](https://github.com/hashicorp/vault/pull/27809)]
+* audit: Internal implementation changes to the audit subsystem which improve performance. [[GH-27952](https://github.com/hashicorp/vault/pull/27952)]
+* audit: sinks (file, socket, syslog) will attempt to log errors to the server operational
+log before returning (if there are errors to log, and the context is done). [[GH-27859](https://github.com/hashicorp/vault/pull/27859)]
+* auth/cert: Cache full list of role trust information separately to avoid
+eviction, and avoid duplicate loading during multiple simultaneous logins on
+the same role. [[GH-27902](https://github.com/hashicorp/vault/pull/27902)]
+* license utilization reporting (enterprise): Auto-roll billing start date. [[GH-27656](https://github.com/hashicorp/vault/pull/27656)]
+
+BUG FIXES:
+
+* auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors [[GH-27696](https://github.com/hashicorp/vault/pull/27696)]
+* cli: Fixed issue with `vault hcp connect` where HCP resources with uppercase letters were inaccessible when entering the correct project name. [[GH-27694](https://github.com/hashicorp/vault/pull/27694)]
+* core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured. [[GH-27939](https://github.com/hashicorp/vault/pull/27939)]
+* core/identity: Fixed an issue where deleted/reassigned entity-aliases were not removed from in-memory database. [[GH-27750](https://github.com/hashicorp/vault/pull/27750)]
+* proxy/cache (enterprise): Fixed an issue where Proxy would not correctly update KV secrets when talking to a perf standby. Proxy will now attempt to forward requests to update secrets triggered by events to the active node. Note that this requires `allow_forwarding_via_header` to be configured on the cluster. [[GH-27891](https://github.com/hashicorp/vault/pull/27891)]
+* raft/autopilot: Fixed panic that may occur during shutdown [[GH-27726](https://github.com/hashicorp/vault/pull/27726)]
+* secrets-sync (enterprise): Destination set/remove operations will no longer be blocked as "purge in progress" after a purge job ended in failure.
+* secrets-sync (enterprise): Normalize custom_tag keys and values for recoverable invalid characters.
+* secrets-sync (enterprise): Normalize secret key names before storing the external_name in a secret association.
+* secrets-sync (enterprise): Patching github sync destination credentials will properly update and save the new credentials.
+* secrets-sync (enterprise): Return an error immediately on destination creation when providing invalid custom_tags based on destination type.
+* secrets/identity (enterprise): Fix a bug that can cause DR promotion to fail in rare cases where a PR secondary has inconsistent alias information in storage.
+* sys: Fix a bug where mounts of external plugins that were registered before Vault v1.0.0 could not be tuned to
+use versioned plugins. [[GH-27881](https://github.com/hashicorp/vault/pull/27881)]
+* ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER. [[GH-27569](https://github.com/hashicorp/vault/pull/27569)]
+* ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call. [[GH-27742](https://github.com/hashicorp/vault/pull/27742)]
+* ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default. [[GH-27728](https://github.com/hashicorp/vault/pull/27728)]
+
+
+## 1.16.6 Enterprise
+### July 10, 2024
+
+**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release.
+
+CHANGES:
+
+* core: Bump Go version to 1.22.5.
+* auth/jwt: Revert [GH-295](https://github.com/hashicorp/vault-plugin-auth-jwt/pull/295) which changed the way JWT `aud` claims were validated.
+
+BUG FIXES:
+
+* agent: Correctly constructs kv-v2 secret paths in nested namespaces. [[GH-26863](https://github.com/hashicorp/vault/pull/26863)]
+* core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme. [[GH-27660](https://github.com/hashicorp/vault/pull/27660)]
+* core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`,
+which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection. [[GH-27589](https://github.com/hashicorp/vault/pull/27589)]
+* core: Fixed an issue with performance standbys not being able to handle rotate root requests. [[GH-27631](https://github.com/hashicorp/vault/pull/27631)]
+* ui: Display an error and force a timeout when TOTP passcode is incorrect [[GH-27574](https://github.com/hashicorp/vault/pull/27574)]
+* ui: Ensure token expired banner displays when batch token expires [[GH-27479](https://github.com/hashicorp/vault/pull/27479)]
+
+## 1.16.5 Enterprise
+### June 26, 2024
+
+**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release.
+
+BUG FIXES:
+
+* cli/debug: Fix resource leak in CLI debug command. [[GH-26167](https://github.com/hashicorp/vault/pull/26167)]
+* config: Vault TCP listener config now correctly supports the documented proxy_protocol_behavior
+setting of 'deny_unauthorized' [[GH-27459](https://github.com/hashicorp/vault/pull/27459)]
+* core/audit: Audit logging a Vault request/response checks if the existing context
+is cancelled and will now use a new context with a 5 second timeout.
+If the existing context is cancelled a new context, will be used. [[GH-27531](https://github.com/hashicorp/vault/pull/27531)]
+* helper/pkcs7: Fix parsing certain messages containing only certificates [[GH-27435](https://github.com/hashicorp/vault/pull/27435)]
+* replication (enterprise): fix cache invalidation issue leading to namespace custom metadata not being shown correctly on performance secondaries
+* secrets-sync (enterprise): Properly remove tags from secrets in AWS when they are removed from the source association
+* secrets-sync (enterprise): Return more accurate error code for invalid connection details
+* secrets-sync (enterprise): Skip invalid GitHub repository names when creating destinations
+* storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses. [[GH-27474](https://github.com/hashicorp/vault/pull/27474)]
+* ui: Allow creation of session_token type roles for AWS secret backend [[GH-27424](https://github.com/hashicorp/vault/pull/27424)]
+
+## 1.16.4 Enterprise
+### June 12, 2024
+
+**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release.
+
+CHANGES:
+
+* core: Bump Go version to 1.22.4.
+* ui/kubernetes: Update the roles filter-input to use explicit search. [[GH-27178](https://github.com/hashicorp/vault/pull/27178)]
+
+IMPROVEMENTS:
+
+* ui: Allow users to wrap inputted data again instead of resetting form [[GH-27289](https://github.com/hashicorp/vault/pull/27289)]
+* ui: Update language in Transit secret engine to reflect that not all keys are for encyryption [[GH-27346](https://github.com/hashicorp/vault/pull/27346)]
+
+BUG FIXES:
+
+* secrets/transform (enterprise): Fix a bug preventing the use of alternate schemas on PostgreSQL token stores.
+* storage/raft (enterprise): Fix a regression introduced in 1.15.8 that causes
+autopilot to fail to discover new server versions and so not trigger an upgrade. [[GH-27277](https://github.com/hashicorp/vault/pull/27277)]
+* ui: Do not show resultant-ACL banner when ancestor namespace grants wildcard access. [[GH-27263](https://github.com/hashicorp/vault/pull/27263)]
+* ui: Fix a bug where disabling TTL on the AWS credential form would still send TTL value [[GH-27366](https://github.com/hashicorp/vault/pull/27366)]
+* ui: fix issue where a month with total clients but no new clients breaks the client count dashboard [[GH-5962](https://github.com/hashicorp/vault/pull/5962)]
+
+## 1.16.3
+### May 30, 2024
+
+**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release.
+
+SECURITY:
+
+* auth/jwt: Update plugin to v0.20.3 that resolves a security issue with validing JWTs [[GH-26890](https://github.com/hashicorp/vault/pull/26890), [HCSEC-2024-11](https://discuss.hashicorp.com/t/hcsec-2024-11-vault-incorrectly-validated-json-web-tokens-jwt-audience-claims/67770)]
+
+CHANGES:
+
+* core/identity: improve performance for secondary nodes receiving identity related updates through replication [[GH-27184](https://github.com/hashicorp/vault/pull/27184)]
+* core: Bump Go version to 1.22.2.
+
+IMPROVEMENTS:
+
+* secrets/pki (enterprise): Disable warnings about unknown parameters to the various CIEPS endpoints
+* ui: Update PGP display and show error for Generate Operation Token flow with PGP [[GH-26993](https://github.com/hashicorp/vault/pull/26993)]
+
+BUG FIXES:
+
+* activity (enterprise): fix read-only storage error on upgrades
+* auto-auth: Addressed issue where having no permissions to renew a renewable token caused auto-auth to attempt to renew constantly with no backoff [[GH-26844](https://github.com/hashicorp/vault/pull/26844)]
+* core (enterprise): Fix an issue that prevented the seal re-wrap status from reporting that a re-wrap is in progress for up to a second.
+* core/audit: Audit logging a Vault request/response will now use a minimum 5 second context timeout.
+If the existing context deadline occurs later than 5s in the future, it will be used, otherwise a new context, separate from the original will be used. [[GH-26616](https://github.com/hashicorp/vault/pull/26616)]
+* core: Add missing field delegated_auth_accessors to GET /sys/mounts/:path API response [[GH-26876](https://github.com/hashicorp/vault/pull/26876)]
+* core: Address a data race updating a seal's last seen healthy time attribute [[GH-27014](https://github.com/hashicorp/vault/pull/27014)]
+* core: Fix `redact_version` listener parameter being ignored for some OpenAPI related endpoints. [[GH-26607](https://github.com/hashicorp/vault/pull/26607)]
+* events (enterprise): Fix bug preventing subscribing and receiving events within a namepace.
+* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)]
+* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster
+* secrets-sync (enterprise): Secondary nodes in a cluster now properly check activation-flags values.
+* secrets/azure: Update vault-plugin-secrets-azure to 0.17.2 to include a bug fix for azure role creation [[GH-26896](https://github.com/hashicorp/vault/pull/26896)]
+* secrets/pki (enterprise): cert_role parameter within authenticators.cert EST configuration handler could not be set
+* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)]
+* ui: Fix KVv2 cursor jumping inside json editor after initial input. [[GH-27120](https://github.com/hashicorp/vault/pull/27120)]
+* ui: Fix KVv2 json editor to allow null values. [[GH-27094](https://github.com/hashicorp/vault/pull/27094)]
+* ui: Fix broken help link in console for the web command. [[GH-26858](https://github.com/hashicorp/vault/pull/26858)]
+* ui: Fix link to v2 generic secrets engine from secrets list page. [[GH-27019](https://github.com/hashicorp/vault/pull/27019)]
+* ui: Prevent perpetual loading screen when Vault needs initialization [[GH-26985](https://github.com/hashicorp/vault/pull/26985)]
+* ui: Refresh model within a namespace on the Secrets Sync overview page. [[GH-26790](https://github.com/hashicorp/vault/pull/26790)]
+
## 1.16.2
### April 24, 2024
@@ -415,6 +854,97 @@ leading to failure to complete merkle sync without a full re-index. [[GH-23013](
* ui: remove user_lockout_config settings for unsupported methods [[GH-25867](https://github.com/hashicorp/vault/pull/25867)]
* ui: show error from API when seal fails [[GH-23921](https://github.com/hashicorp/vault/pull/23921)]
+## 1.15.13 Enterprise
+### August 07, 2024
+
+CHANGES:
+
+* auth/cf: Update plugin to v0.18.0 [[GH-27724](https://github.com/hashicorp/vault/pull/27724)]
+
+IMPROVEMENTS:
+
+* audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success. [[GH-27809](https://github.com/hashicorp/vault/pull/27809)]
+* auth/cert: Cache full list of role trust information separately to avoid
+eviction, and avoid duplicate loading during multiple simultaneous logins on
+the same role. [[GH-27902](https://github.com/hashicorp/vault/pull/27902)]
+
+BUG FIXES:
+
+* auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors [[GH-27696](https://github.com/hashicorp/vault/pull/27696)]
+* core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured. [[GH-27939](https://github.com/hashicorp/vault/pull/27939)]
+* raft/autopilot: Fixed panic that may occur during shutdown [[GH-27726](https://github.com/hashicorp/vault/pull/27726)]
+* secrets/identity (enterprise): Fix a bug that can cause DR promotion to fail in rare cases where a PR secondary has inconsistent alias information in storage.
+* ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER. [[GH-27569](https://github.com/hashicorp/vault/pull/27569)]
+* ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call. [[GH-27742](https://github.com/hashicorp/vault/pull/27742)]
+* ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default. [[GH-27728](https://github.com/hashicorp/vault/pull/27728)]
+
+
+## 1.15.12 Enterprise
+### July 10, 2024
+
+CHANGES:
+
+* core: Bump Go version to 1.22.5.
+* auth/jwt: Revert [GH-295](https://github.com/hashicorp/vault-plugin-auth-jwt/pull/295) which changed the way JWT `aud` claims were validated.
+
+BUG FIXES:
+
+* core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme. [[GH-27660](https://github.com/hashicorp/vault/pull/27660)]
+* core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`,
+which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection. [[GH-27589](https://github.com/hashicorp/vault/pull/27589)]
+* core: Fixed an issue with performance standbys not being able to handle rotate root requests. [[GH-27631](https://github.com/hashicorp/vault/pull/27631)]
+* ui: Display an error and force a timeout when TOTP passcode is incorrect [[GH-27574](https://github.com/hashicorp/vault/pull/27574)]
+* ui: Ensure token expired banner displays when batch token expires [[GH-27479](https://github.com/hashicorp/vault/pull/27479)]
+
+## 1.15.11 Enterprise
+### June 26, 2024
+
+BUG FIXES:
+
+* cli/debug: Fix resource leak in CLI debug command. [[GH-26167](https://github.com/hashicorp/vault/pull/26167)]
+* helper/pkcs7: Fix parsing certain messages containing only certificates [[GH-27435](https://github.com/hashicorp/vault/pull/27435)]
+* replication (enterprise): fix cache invalidation issue leading to namespace custom metadata not being shown correctly on performance secondaries
+* storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses. [[GH-27474](https://github.com/hashicorp/vault/pull/27474)]
+
+## 1.15.10 Enterprise
+### June 12, 2024
+
+CHANGES:
+
+* core: Bump Go version to 1.22.4.
+
+IMPROVEMENTS:
+
+* ui: Allow users to wrap inputted data again instead of resetting form [[GH-27289](https://github.com/hashicorp/vault/pull/27289)]
+* ui: Update language in Transit secret engine to reflect that not all keys are for encyryption [[GH-27346](https://github.com/hashicorp/vault/pull/27346)]
+
+BUG FIXES:
+
+* secrets/transform (enterprise): Fix a bug preventing the use of alternate schemas on PostgreSQL token stores.
+* storage/raft (enterprise): Fix a regression introduced in 1.15.8 that causes
+autopilot to fail to discover new server versions and so not trigger an upgrade. [[GH-27277](https://github.com/hashicorp/vault/pull/27277)]
+* ui: Do not show resultant-ACL banner when ancestor namespace grants wildcard access. [[GH-27263](https://github.com/hashicorp/vault/pull/27263)]
+* ui: Fix a bug where disabling TTL on the AWS credential form would still send TTL value [[GH-27366](https://github.com/hashicorp/vault/pull/27366)]
+
+## 1.15.9 Enterprise
+### May 30, 2024
+
+CHANGES:
+* auth/jwt: Update plugin to v0.17.3 [[GH-27063](https://github.com/hashicorp/vault/pull/27063)]
+* core: Bump Go version to 1.22.2.
+
+IMPROVEMENTS:
+* secrets/pki (enterprise): Disable warnings about unknown parameters to the various CIEPS endpoints
+* website/docs: Add note about eventual consietency with the MongoDB Atlas database secrets engine [[GH-24152](https://github.com/hashicorp/vault/pull/24152)]
+
+BUG FIXES:
+* activity (enterprise): fix read-only storage error on upgrades
+* core: Address a data race updating a seal's last seen healthy time attribute [[GH-27014](https://github.com/hashicorp/vault/pull/27014)]
+* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)]
+* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster
+* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)]
+* ui: Fix KVv2 cursor jumping inside json editor after initial input. [[GH-27120](https://github.com/hashicorp/vault/pull/27120)]
+
## 1.15.8 Enterprise
### April 24, 2024
@@ -949,6 +1479,21 @@ sdk/ldaputil: use EscapeLDAPValue implementation from cap/ldap [[GH-22249](https
* ui: fixes model defaults overwriting input value when user tries to clear form input [[GH-22458](https://github.com/hashicorp/vault/pull/22458)]
* ui: fixes text readability issue in revoke token confirmation dialog [[GH-22390](https://github.com/hashicorp/vault/pull/22390)]
+## 1.14.13 Enterprise
+### May 30, 2024
+CHANGES:
+* auth/jwt: Update plugin to v0.16.1 [[GH-27122](https://github.com/hashicorp/vault/pull/27122)]
+* core: Bump Go version to 1.22.2.
+
+IMPROVEMENTS:
+* website/docs: Add note about eventual consietency with the MongoDB Atlas database secrets engine [[GH-24152](https://github.com/hashicorp/vault/pull/24152)]
+
+BUG FIXES:
+* activity (enterprise): fix read-only storage error on upgrades
+* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)]
+* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster
+* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)]
+
## 1.14.12 Enterprise
### April 24, 2024
diff --git a/Dockerfile b/Dockerfile
index 3799f778dd..a457b1633a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: BUSL-1.1
## DOCKERHUB DOCKERFILE ##
-FROM alpine:3.18 as default
+FROM alpine:3 as default
ARG BIN_NAME
# NAME and PRODUCT_VERSION are the name of the software in releases.hashicorp.com
@@ -24,7 +24,8 @@ LABEL name="Vault" \
summary="Vault is a tool for securely accessing secrets." \
description="Vault is a tool for securely accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, and more. Vault provides a unified interface to any secret, while providing tight access control and recording a detailed audit log."
-COPY LICENSE /licenses/mozilla.txt
+# Copy the license file as per Legal requirement
+COPY LICENSE /usr/share/doc/$NAME/LICENSE.txt
# Set ARGs as ENV so that they can be used in ENTRYPOINT/CMD
ENV NAME=$NAME
@@ -74,7 +75,7 @@ CMD ["server", "-dev"]
## UBI DOCKERFILE ##
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9 as ubi
+FROM registry.access.redhat.com/ubi8/ubi-minimal as ubi
ARG BIN_NAME
# PRODUCT_VERSION is the version built dist/$TARGETOS/$TARGETARCH/$BIN_NAME,
@@ -95,7 +96,8 @@ LABEL name="Vault" \
summary="Vault is a tool for securely accessing secrets." \
description="Vault is a tool for securely accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, and more. Vault provides a unified interface to any secret, while providing tight access control and recording a detailed audit log."
-COPY LICENSE /licenses/mozilla.txt
+# Copy the license file as per Legal requirement
+COPY LICENSE /usr/share/doc/$NAME/LICENSE.txt
# Set ARGs as ENV so that they can be used in ENTRYPOINT/CMD
ENV NAME=$NAME
diff --git a/Makefile b/Makefile
index d3443a0e8b..ba499ad740 100644
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,12 @@ ifneq ($(FDB_ENABLED), )
BUILD_TAGS+=foundationdb
endif
+# Set BUILD_MINIMAL to a non-empty value to build a minimal version of Vault with only core features.
+BUILD_MINIMAL ?=
+ifneq ($(strip $(BUILD_MINIMAL)),)
+ BUILD_TAGS+=minimal
+endif
+
default: dev
# bin generates the releasable binaries for Vault
diff --git a/README.md b/README.md
index 109570940e..8139fa6d75 100644
--- a/README.md
+++ b/README.md
@@ -21,8 +21,7 @@ A modern system requires access to a multitude of secrets: database credentials,
The key features of Vault are:
-* **Secure Secret Storage**: Arbitrary key/value secrets can be stored
- in Vault. Vault encrypts these secrets prior to writing them to persistent
+* **Secure Secret Storage**: Vault can store arbitrary key/value pairs. Vault encrypts data before writing it to persistent
storage, so gaining access to the raw storage isn't enough to access
your secrets. Vault can write to disk, [Consul](https://www.consul.io),
and more.
@@ -39,8 +38,8 @@ The key features of Vault are:
developers to store encrypted data in a location such as a SQL database without
having to design their own encryption methods.
-* **Leasing and Renewal**: All secrets in Vault have a _lease_ associated
- with them. At the end of the lease, Vault will automatically revoke that
+* **Leasing and Renewal**: Vault associates a **lease** with each secret.
+ At the end of the lease, Vault automatically revokes the
secret. Clients are able to renew leases via built-in renew APIs.
* **Revocation**: Vault has built-in support for secret revocation. Vault
@@ -73,9 +72,12 @@ If you wish to work on Vault itself or any of its built-in systems, you'll
first need [Go](https://www.golang.org) installed on your machine.
For local dev first make sure Go is properly installed, including setting up a
-[GOPATH](https://golang.org/doc/code.html#GOPATH). Ensure that `$GOPATH/bin` is in
-your path as some distributions bundle the old version of build tools. Next, clone this
-repository. Vault uses [Go Modules](https://github.com/golang/go/wiki/Modules),
+[GOPATH](https://golang.org/doc/code.html#GOPATH), then setting the
+[GOBIN](https://pkg.go.dev/cmd/go#hdr-Environment_variables) variable to `$GOPATH/bin`.
+Ensure that `$GOPATH/bin` is in your path as some distributions bundle the old version
+of build tools.
+
+Next, clone this repository. Vault uses [Go Modules](https://github.com/golang/go/wiki/Modules),
so it is recommended that you clone the repository ***outside*** of the GOPATH.
You can then download any required build tools by bootstrapping your environment:
@@ -121,6 +123,15 @@ $ make test TEST=./vault
...
```
+### Troubleshooting
+
+If you encounter an error like `could not read Username for 'https://github.com'` you may need to adjust your git config like so:
+
+```sh
+$ git config --global --add url."git@github.com:".insteadOf "https://github.com/"
+```
+
+
### Importing Vault
This repository publishes two libraries that may be imported by other projects:
diff --git a/api/auth/approle/go.mod b/api/auth/approle/go.mod
index 0c52b49435..f5451d11f0 100644
--- a/api/auth/approle/go.mod
+++ b/api/auth/approle/go.mod
@@ -1,5 +1,28 @@
module github.com/hashicorp/vault/api/auth/approle
-go 1.16
+go 1.21
-require github.com/hashicorp/vault/api v1.12.0
+toolchain go1.22.2
+
+require github.com/hashicorp/vault/api v1.14.0
+
+require (
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // 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/hcl v1.0.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
+)
diff --git a/api/auth/approle/go.sum b/api/auth/approle/go.sum
index 8645312630..00d28f0404 100644
--- a/api/auth/approle/go.sum
+++ b/api/auth/approle/go.sum
@@ -5,29 +5,27 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
-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/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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
@@ -39,17 +37,14 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
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/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
-github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
+github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
+github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -64,73 +59,20 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/api/auth/aws/go.mod b/api/auth/aws/go.mod
index a4fe80a7bd..507089ff64 100644
--- a/api/auth/aws/go.mod
+++ b/api/auth/aws/go.mod
@@ -1,11 +1,40 @@
module github.com/hashicorp/vault/api/auth/aws
-go 1.16
+go 1.21
+
+toolchain go1.22.2
require (
github.com/aws/aws-sdk-go v1.49.22
- github.com/hashicorp/go-hclog v0.16.2
+ github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6
github.com/hashicorp/go-uuid v1.0.2
- github.com/hashicorp/vault/api v1.12.0
+ github.com/hashicorp/vault/api v1.14.0
+)
+
+require (
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/fatih/color v1.16.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // 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/hcl v1.0.0 // indirect
+ github.com/jmespath/go-jmespath v0.4.0 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/sys v0.20.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
)
diff --git a/api/auth/aws/go.sum b/api/auth/aws/go.sum
index 96afd5f25d..71ff425d86 100644
--- a/api/auth/aws/go.sum
+++ b/api/auth/aws/go.sum
@@ -9,30 +9,30 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
-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/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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
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/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA=
@@ -48,8 +48,8 @@ github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2I
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
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/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
-github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
+github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
+github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
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=
@@ -62,13 +62,19 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -86,76 +92,37 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
diff --git a/api/auth/azure/azure.go b/api/auth/azure/azure.go
index b682195701..ecca535b43 100644
--- a/api/auth/azure/azure.go
+++ b/api/auth/azure/azure.go
@@ -7,7 +7,7 @@ import (
"context"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"time"
@@ -175,7 +175,7 @@ func (a *AzureAuth) getJWT() (string, error) {
}
defer resp.Body.Close()
- responseBytes, err := ioutil.ReadAll(resp.Body)
+ responseBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("error reading response body from Azure token endpoint: %w", err)
}
@@ -222,7 +222,7 @@ func getMetadata() (metadataJSON, error) {
}
defer resp.Body.Close()
- responseBytes, err := ioutil.ReadAll(resp.Body)
+ responseBytes, err := io.ReadAll(resp.Body)
if err != nil {
return metadataJSON{}, fmt.Errorf("error reading response body from metadata endpoint: %w", err)
}
diff --git a/api/auth/azure/go.mod b/api/auth/azure/go.mod
index 5fc1e6716e..d5c6d2856e 100644
--- a/api/auth/azure/go.mod
+++ b/api/auth/azure/go.mod
@@ -1,5 +1,28 @@
module github.com/hashicorp/vault/api/auth/azure
-go 1.16
+go 1.21
-require github.com/hashicorp/vault/api v1.12.0
+toolchain go1.22.2
+
+require github.com/hashicorp/vault/api v1.14.0
+
+require (
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // 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/hcl v1.0.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
+)
diff --git a/api/auth/azure/go.sum b/api/auth/azure/go.sum
index 8645312630..00d28f0404 100644
--- a/api/auth/azure/go.sum
+++ b/api/auth/azure/go.sum
@@ -5,29 +5,27 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
-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/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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
@@ -39,17 +37,14 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
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/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
-github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
+github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
+github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -64,73 +59,20 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/api/auth/gcp/gcp.go b/api/auth/gcp/gcp.go
index 2d6ef842a4..7f4f222c0c 100644
--- a/api/auth/gcp/gcp.go
+++ b/api/auth/gcp/gcp.go
@@ -7,7 +7,7 @@ import (
"context"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"time"
@@ -181,7 +181,7 @@ func (a *GCPAuth) getJWTFromMetadataService(vaultAddress string) (string, error)
defer resp.Body.Close()
// get jwt from response
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
jwt := string(body)
if err != nil {
return "", fmt.Errorf("error reading response from metadata service: %w", err)
diff --git a/api/auth/gcp/go.mod b/api/auth/gcp/go.mod
index 977ebec0a4..1a75214a2f 100644
--- a/api/auth/gcp/go.mod
+++ b/api/auth/gcp/go.mod
@@ -1,11 +1,57 @@
module github.com/hashicorp/vault/api/auth/gcp
-go 1.16
+go 1.21
+
+toolchain go1.22.2
require (
- cloud.google.com/go/compute/metadata v0.2.3
- cloud.google.com/go/iam v0.13.0
- github.com/hashicorp/vault/api v1.12.0
- google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1
- google.golang.org/grpc v1.56.3 // indirect
+ cloud.google.com/go/compute/metadata v0.3.0
+ cloud.google.com/go/iam v1.1.8
+ github.com/hashicorp/vault/api v1.14.0
+ google.golang.org/genproto v0.0.0-20240604185151-ef581f913117
+)
+
+require (
+ cloud.google.com/go/auth v0.3.0 // indirect
+ cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/go-logr/logr v1.4.1 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
+ github.com/google/s2a-go v0.1.7 // indirect
+ github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
+ github.com/googleapis/gax-go/v2 v2.12.3 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // 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/hcl v1.0.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ go.opencensus.io v0.24.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
+ go.opentelemetry.io/otel v1.24.0 // indirect
+ go.opentelemetry.io/otel/metric v1.24.0 // indirect
+ go.opentelemetry.io/otel/trace v1.24.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/oauth2 v0.19.0 // indirect
+ golang.org/x/sync v0.7.0 // indirect
+ golang.org/x/sys v0.20.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
+ google.golang.org/api v0.177.0 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
+ google.golang.org/grpc v1.64.0 // indirect
+ google.golang.org/protobuf v1.34.1 // indirect
)
diff --git a/api/auth/gcp/go.sum b/api/auth/gcp/go.sum
index 2a07728611..cb03d6d969 100644
--- a/api/auth/gcp/go.sum
+++ b/api/auth/gcp/go.sum
@@ -1,807 +1,84 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
-cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
-cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
-cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
-cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
-cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
-cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
-cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
-cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
-cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
-cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
-cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
-cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
-cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
-cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
-cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
-cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
-cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
-cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
-cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
-cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
-cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
-cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
-cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
-cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
-cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
-cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
-cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
-cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
-cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
-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/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
-cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
-cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
-cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o=
-cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE=
-cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM=
-cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ=
-cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
-cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
-cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg=
-cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ=
-cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k=
-cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw=
-cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
-cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4=
-cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M=
-cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE=
-cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE=
-cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk=
-cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc=
-cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8=
-cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc=
-cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04=
-cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8=
-cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY=
-cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM=
-cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc=
-cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU=
-cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI=
-cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8=
-cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno=
-cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak=
-cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84=
-cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A=
-cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E=
-cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4=
-cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0=
-cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY=
-cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k=
-cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ=
-cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk=
-cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0=
-cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc=
-cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI=
-cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ=
-cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI=
-cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08=
-cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o=
-cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s=
-cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0=
-cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ=
-cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY=
-cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo=
-cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg=
-cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw=
-cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY=
-cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw=
-cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI=
-cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo=
-cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0=
-cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E=
-cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0=
-cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8=
-cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8=
-cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM=
-cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU=
-cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc=
-cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI=
-cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss=
-cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE=
-cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE=
-cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g=
-cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4=
-cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8=
-cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM=
-cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU=
-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/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA=
-cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw=
-cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc=
-cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E=
-cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac=
-cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q=
-cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU=
-cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY=
-cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s=
-cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI=
-cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y=
-cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss=
-cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc=
-cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM=
-cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI=
-cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0=
-cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk=
-cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q=
-cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg=
-cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590=
-cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8=
-cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk=
-cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk=
-cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE=
-cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU=
-cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U=
-cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA=
-cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M=
-cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg=
-cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s=
-cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM=
-cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk=
-cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA=
-cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY=
-cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI=
-cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4=
-cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI=
-cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y=
-cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs=
-cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
-cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
-cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
-cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
-cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
-cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
-cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
-cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
-cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
-cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE=
-cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo=
-cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA=
-cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
-cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
-cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
-cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
-cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
-cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
-cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
-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/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
-cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
-cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
-cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg=
-cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo=
-cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4=
-cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM=
-cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA=
-cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
-cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4=
-cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI=
-cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s=
-cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0=
-cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs=
-cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc=
-cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE=
-cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM=
-cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M=
-cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0=
-cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8=
-cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM=
-cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ=
-cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE=
-cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo=
-cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE=
-cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0=
-cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA=
-cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE=
-cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38=
-cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w=
-cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8=
-cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I=
-cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ=
-cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM=
-cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA=
-cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A=
-cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ=
-cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs=
-cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s=
-cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI=
-cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4=
-cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo=
-cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA=
-cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c=
-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/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM=
-cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c=
-cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo=
-cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ=
-cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g=
-cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4=
-cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs=
-cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww=
-cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c=
-cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s=
-cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI=
-cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ=
-cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4=
-cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0=
-cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8=
-cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek=
-cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0=
-cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM=
-cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4=
-cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE=
-cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM=
-cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q=
-cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4=
-cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU=
-cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU=
-cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k=
-cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4=
-cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM=
-cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs=
-cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y=
-cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg=
-cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE=
-cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk=
-cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w=
-cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc=
-cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY=
-cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU=
-cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI=
-cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8=
-cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M=
-cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc=
-cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw=
-cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw=
-cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY=
-cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w=
-cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI=
-cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs=
-cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg=
-cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE=
-cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk=
-cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg=
-cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY=
-cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08=
-cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw=
-cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA=
-cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c=
-cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM=
-cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA=
-cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w=
-cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM=
-cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0=
-cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60=
-cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo=
-cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg=
-cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o=
-cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A=
-cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw=
-cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0=
-cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0=
-cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E=
-cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw=
-cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA=
-cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI=
-cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y=
-cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
-cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM=
-cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o=
-cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo=
-cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c=
-cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
-cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
-cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
-cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
-cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE=
-cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY=
-cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY=
-cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=
-cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
-cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
-cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
-cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk=
-cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo=
-cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74=
-cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM=
-cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY=
-cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4=
-cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs=
-cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g=
-cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o=
-cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE=
-cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA=
-cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg=
-cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0=
-cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg=
-cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w=
-cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24=
-cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI=
-cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
-cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
-cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE=
-cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8=
-cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY=
-cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
-cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08=
-cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo=
-cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw=
-cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M=
-cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE=
-cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc=
-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/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE=
-cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM=
-cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA=
-cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI=
-cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw=
-cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY=
-cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4=
-cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w=
-cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I=
-cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE=
-cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM=
-cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA=
-cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY=
-cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM=
-cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY=
-cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s=
-cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8=
-cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI=
-cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo=
-cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk=
-cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4=
-cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w=
-cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw=
-cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA=
-cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o=
-cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM=
-cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8=
-cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E=
-cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM=
-cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8=
-cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4=
-cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY=
-cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ=
-cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU=
-cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k=
-cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU=
-cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY=
-cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34=
-cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA=
-cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0=
-cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE=
-cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ=
-cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4=
-cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs=
-cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI=
-cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA=
-cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk=
-cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ=
-cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE=
-cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc=
-cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc=
-cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs=
-cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg=
-cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo=
-cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw=
-cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw=
-cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E=
-cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU=
-cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70=
-cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo=
-cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs=
-cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0=
-cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA=
-cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk=
-cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg=
-cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE=
-cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw=
-cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc=
-cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0=
-cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI=
-cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg=
-cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs=
-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.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI=
-cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0=
-cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8=
-cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4=
-cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg=
-cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k=
-cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM=
-cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4=
-cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o=
-cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk=
-cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo=
-cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE=
-cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U=
-cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA=
-cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c=
-cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg=
-cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4=
-cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac=
-cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg=
-cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c=
-cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs=
-cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70=
-cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ=
-cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y=
-cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A=
-cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA=
-cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM=
-cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ=
-cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA=
-cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0=
-cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots=
-cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo=
-cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI=
-cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU=
-cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg=
-cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA=
-cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4=
-cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY=
-cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc=
-cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y=
-cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14=
-cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do=
-cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo=
-cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM=
-cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg=
-cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s=
-cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI=
-cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk=
-cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44=
-cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc=
-cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc=
-cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA=
-cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4=
-cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4=
-cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU=
-cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4=
-cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0=
-cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU=
-cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q=
-cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA=
-cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8=
-cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0=
-cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU=
-cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc=
-cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk=
-cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk=
-cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0=
-cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag=
-cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU=
-cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s=
-cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA=
-cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc=
-cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk=
-cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs=
-cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg=
-cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4=
-cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U=
-cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY=
-cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s=
-cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco=
-cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo=
-cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc=
-cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4=
-cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E=
-cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU=
-cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec=
-cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA=
-cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4=
-cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw=
-cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A=
-cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos=
-cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk=
-cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M=
-cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
-cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
-cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0=
-cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco=
-cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0=
-cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI=
-cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
-cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
-cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
-cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
-cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
-cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
-cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
-cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
-cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
-cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4=
-cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w=
-cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I=
-cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4=
-cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw=
-cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
-cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
-cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM=
-cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA=
-cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c=
-cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8=
-cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4=
-cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc=
-cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ=
-cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg=
-cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM=
-cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28=
-cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y=
-cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA=
-cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk=
-cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs=
-cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg=
-cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0=
-cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos=
-cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos=
-cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk=
-cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw=
-cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg=
-cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk=
-cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ=
-cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ=
-cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
-cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4=
-cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M=
-cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU=
-cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU=
-cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0=
-cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo=
-cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo=
-cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY=
-cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E=
-cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY=
-cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0=
-cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE=
-cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g=
-cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc=
-cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY=
-cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208=
-cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8=
-cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY=
-cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w=
-cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8=
-cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes=
-cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE=
-cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg=
-cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc=
-cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A=
-cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg=
-cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo=
-cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ=
-cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng=
-cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0=
-cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M=
-cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
-cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
-cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
-git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
+cloud.google.com/go/auth v0.3.0 h1:PRyzEpGfx/Z9e8+lHsbkoUVXD0gnu4MNmm7Gp8TQNIs=
+cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w=
+cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4=
+cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
+cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
+cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
+cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0=
+cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
-github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
-github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
-github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
-github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
-github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
-github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
-github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
-github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
-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.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
-github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
-github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
-github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
-github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34=
-github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
-github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
-github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
-github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
-github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
-github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
-github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
-github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
-github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
-github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
-github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
-github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
-github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
-github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
-github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
-github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
-github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
+github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
-github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
-github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
-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.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
-github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
-github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
-github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
-github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
-github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
-github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
-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/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
-github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
+github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
+github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
+github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA=
+github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
@@ -811,47 +88,16 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
-github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
-github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
-github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
-github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
-github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
-github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
-github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
-github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
-github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
-github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
+github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
+github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
-github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
-github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -859,687 +105,97 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
-github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
-github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
-github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
-github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
-github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
-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/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
-github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
-github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
-github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
-github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/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/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
-github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
-go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
+go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
+go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
+go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
+go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
+go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
+go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
-golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
-golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
-golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
-golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
-golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
-golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
-golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
-golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
-golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
-golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
-golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
-golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
-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.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
-golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
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-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
-golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
-golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
-golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
-golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
-golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
-golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
-golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
-golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
-golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
-golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
+golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
+golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
-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/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
-golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-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/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/time v0.0.0-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-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.1.0/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-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-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
-gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
-gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0=
-gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA=
-gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
-gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
-gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY=
-gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo=
-google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
-google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
-google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
-google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
-google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
-google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
-google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
-google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
-google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
-google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
-google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
-google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
-google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
-google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
-google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
-google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
-google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
-google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
-google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
-google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
-google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
-google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g=
-google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
-google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
-google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI=
-google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
-google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
-google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
-google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08=
-google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
-google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
-google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0=
-google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
-google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
-google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
-google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
-google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
-google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE=
-google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
+google.golang.org/api v0.177.0 h1:8a0p/BbPa65GlqGWtUKxot4p0TV8OGOfyTjtmkXNXmk=
+google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
-google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
-google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
-google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
-google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
-google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
-google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE=
-google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
-google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw=
-google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
-google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
-google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U=
-google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
-google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
-google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
-google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
-google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
-google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
-google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
-google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
-google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
-google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
-google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
-google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE=
-google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
-google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA=
-google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw=
-google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw=
-google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA=
-google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
-google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
-google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
-google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
-google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 h1:HCZ6DlkKtCDAtD8ForECsY3tKuaR+p4R3grlK80uCCc=
+google.golang.org/genproto v0.0.0-20240604185151-ef581f913117/go.mod h1:lesfX/+9iA+3OdqeCpoDddJaNxVB1AB6tD7EfqMmprc=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
-google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
-google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
-google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
-google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
-google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
-google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
-google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
-google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
-google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
-google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
-google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
+google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
+google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
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=
@@ -1548,68 +204,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
-lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
-lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
-modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
-modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
-modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
-modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
-modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
-modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
-modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
-modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws=
-modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo=
-modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
-modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
-modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
-modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
-modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
-modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
-modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
-modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0=
-modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s=
-modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
-modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
-modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
-modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
-modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
-modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
-modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
-modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
-modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4=
-modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
-modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
-modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw=
-modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
-modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
-rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
-rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/api/auth/kubernetes/go.mod b/api/auth/kubernetes/go.mod
index 62f1d36558..0b6d1ef446 100644
--- a/api/auth/kubernetes/go.mod
+++ b/api/auth/kubernetes/go.mod
@@ -1,5 +1,28 @@
module github.com/hashicorp/vault/api/auth/kubernetes
-go 1.16
+go 1.21
-require github.com/hashicorp/vault/api v1.12.0
+toolchain go1.22.2
+
+require github.com/hashicorp/vault/api v1.14.0
+
+require (
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // 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/hcl v1.0.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
+)
diff --git a/api/auth/kubernetes/go.sum b/api/auth/kubernetes/go.sum
index 8645312630..00d28f0404 100644
--- a/api/auth/kubernetes/go.sum
+++ b/api/auth/kubernetes/go.sum
@@ -5,29 +5,27 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
-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/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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
@@ -39,17 +37,14 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
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/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
-github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
+github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
+github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -64,73 +59,20 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/api/auth/ldap/go.mod b/api/auth/ldap/go.mod
index 72326b0d41..b97e5ad233 100644
--- a/api/auth/ldap/go.mod
+++ b/api/auth/ldap/go.mod
@@ -1,5 +1,28 @@
module github.com/hashicorp/vault/api/auth/ldap
-go 1.16
+go 1.21
-require github.com/hashicorp/vault/api v1.12.0
+toolchain go1.22.2
+
+require github.com/hashicorp/vault/api v1.14.0
+
+require (
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // 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/hcl v1.0.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
+)
diff --git a/api/auth/ldap/go.sum b/api/auth/ldap/go.sum
index 8645312630..00d28f0404 100644
--- a/api/auth/ldap/go.sum
+++ b/api/auth/ldap/go.sum
@@ -5,29 +5,27 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
-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/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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
@@ -39,17 +37,14 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
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/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
-github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
+github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
+github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -64,73 +59,20 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/api/auth/userpass/go.mod b/api/auth/userpass/go.mod
index e764c5e312..16cb26b3a6 100644
--- a/api/auth/userpass/go.mod
+++ b/api/auth/userpass/go.mod
@@ -1,5 +1,28 @@
module github.com/hashicorp/vault/api/auth/userpass
-go 1.16
+go 1.21
-require github.com/hashicorp/vault/api v1.12.0
+toolchain go1.22.2
+
+require github.com/hashicorp/vault/api v1.14.0
+
+require (
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // 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/hcl v1.0.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
+)
diff --git a/api/auth/userpass/go.sum b/api/auth/userpass/go.sum
index 8645312630..00d28f0404 100644
--- a/api/auth/userpass/go.sum
+++ b/api/auth/userpass/go.sum
@@ -5,29 +5,27 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
-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/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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
@@ -39,17 +37,14 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
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/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
-github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
+github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
+github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -64,73 +59,20 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/api/client.go b/api/client.go
index 52c991b1e2..0090321caa 100644
--- a/api/client.go
+++ b/api/client.go
@@ -10,6 +10,7 @@ import (
"crypto/tls"
"encoding/base64"
"encoding/hex"
+ "encoding/json"
"fmt"
"net"
"net/http"
@@ -41,6 +42,7 @@ const (
EnvVaultClientCert = "VAULT_CLIENT_CERT"
EnvVaultClientKey = "VAULT_CLIENT_KEY"
EnvVaultClientTimeout = "VAULT_CLIENT_TIMEOUT"
+ EnvVaultHeaders = "VAULT_HEADERS"
EnvVaultSRVLookup = "VAULT_SRV_LOOKUP"
EnvVaultSkipVerify = "VAULT_SKIP_VERIFY"
EnvVaultNamespace = "VAULT_NAMESPACE"
@@ -665,6 +667,30 @@ func NewClient(c *Config) (*Client, error) {
client.setNamespace(namespace)
}
+ if envHeaders := os.Getenv(EnvVaultHeaders); envHeaders != "" {
+ var result map[string]any
+ err := json.Unmarshal([]byte(envHeaders), &result)
+ if err != nil {
+ return nil, fmt.Errorf("could not unmarshal environment-supplied headers")
+ }
+ var forbiddenHeaders []string
+ for key, value := range result {
+ if strings.HasPrefix(key, "X-Vault-") {
+ forbiddenHeaders = append(forbiddenHeaders, key)
+ continue
+ }
+
+ value, ok := value.(string)
+ if !ok {
+ return nil, fmt.Errorf("environment-supplied headers include non-string values")
+ }
+ client.AddHeader(key, value)
+ }
+ if len(forbiddenHeaders) > 0 {
+ return nil, fmt.Errorf("failed to setup Headers[%s]: Header starting by 'X-Vault-' are for internal usage only", strings.Join(forbiddenHeaders, ", "))
+ }
+ }
+
return client, nil
}
@@ -705,7 +731,7 @@ func (c *Client) SetAddress(addr string) error {
parsedAddr, err := c.config.ParseAddress(addr)
if err != nil {
- return errwrap.Wrapf("failed to set address: {{err}}", err)
+ return fmt.Errorf("failed to set address: %w", err)
}
c.addr = parsedAddr
diff --git a/api/client_test.go b/api/client_test.go
index f89d531527..1ed4dfd3d3 100644
--- a/api/client_test.go
+++ b/api/client_test.go
@@ -7,7 +7,6 @@ import (
"bytes"
"context"
"crypto/tls"
- "crypto/x509"
"encoding/base64"
"fmt"
"io"
@@ -330,7 +329,7 @@ func TestDefaulRetryPolicy(t *testing.T) {
},
"don't retry connection failures": {
err: &url.Error{
- Err: x509.UnknownAuthorityError{},
+ Err: &tls.CertificateVerificationError{},
},
},
"don't retry on 200": {
@@ -375,6 +374,61 @@ func TestDefaulRetryPolicy(t *testing.T) {
}
}
+func TestClientEnvHeaders(t *testing.T) {
+ oldHeaders := os.Getenv(EnvVaultHeaders)
+
+ defer func() {
+ os.Setenv(EnvVaultHeaders, oldHeaders)
+ }()
+
+ cases := []struct {
+ Input string
+ Valid bool
+ }{
+ {
+ "{}",
+ true,
+ },
+ {
+ "{\"foo\": \"bar\"}",
+ true,
+ },
+ {
+ "{\"foo\": 1}", // Values must be strings
+ false,
+ },
+ {
+ "{\"X-Vault-Foo\": \"bar\"}", // X-Vault-* not allowed
+ false,
+ },
+ }
+
+ for _, tc := range cases {
+ os.Setenv(EnvVaultHeaders, tc.Input)
+ config := DefaultConfig()
+ config.ReadEnvironment()
+ _, err := NewClient(config)
+ if err != nil {
+ if tc.Valid {
+ t.Fatalf("unexpected error reading headers from environment: %v", err)
+ }
+ } else {
+ if !tc.Valid {
+ t.Fatal("no error reading headers from environment when error was expected")
+ }
+ }
+ }
+
+ os.Setenv(EnvVaultHeaders, "{\"foo\": \"bar\"}")
+ config := DefaultConfig()
+ config.ReadEnvironment()
+ cli, _ := NewClient(config)
+
+ if !reflect.DeepEqual(cli.Headers().Values("foo"), []string{"bar"}) {
+ t.Error("Environment-supplied headers not set in CLI client")
+ }
+}
+
func TestClientEnvSettings(t *testing.T) {
cwd, _ := os.Getwd()
diff --git a/api/go.mod b/api/go.mod
index e92d85a3ed..2b273d8a06 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -10,14 +10,14 @@ go 1.21
toolchain go1.21.8
require (
- github.com/cenkalti/backoff/v3 v3.0.0
+ github.com/cenkalti/backoff/v4 v4.3.0
github.com/go-jose/go-jose/v4 v4.0.1
github.com/go-test/deep v1.0.2
github.com/hashicorp/errwrap v1.1.0
github.com/hashicorp/go-cleanhttp v0.5.2
- github.com/hashicorp/go-hclog v0.16.2
+ github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-multierror v1.1.1
- github.com/hashicorp/go-retryablehttp v0.6.6
+ github.com/hashicorp/go-retryablehttp v0.7.7
github.com/hashicorp/go-rootcerts v1.0.2
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2
diff --git a/api/go.sum b/api/go.sum
index 4d0b5a4959..03a463b4b4 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -1,11 +1,12 @@
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
-github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
@@ -17,17 +18,15 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
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.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.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
@@ -40,12 +39,13 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG
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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
@@ -65,8 +65,8 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
@@ -74,8 +74,11 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
diff --git a/api/lifetime_watcher.go b/api/lifetime_watcher.go
index 4bc1390b93..bdb8fb64b3 100644
--- a/api/lifetime_watcher.go
+++ b/api/lifetime_watcher.go
@@ -10,7 +10,7 @@ import (
"sync"
"time"
- "github.com/cenkalti/backoff/v3"
+ "github.com/cenkalti/backoff/v4"
)
var (
diff --git a/api/request.go b/api/request.go
index a2d912c64d..c0c8dea734 100644
--- a/api/request.go
+++ b/api/request.go
@@ -7,7 +7,6 @@ import (
"bytes"
"encoding/json"
"io"
- "io/ioutil"
"net/http"
"net/url"
@@ -77,13 +76,13 @@ func (r *Request) ToHTTP() (*http.Request, error) {
// No body
case r.BodyBytes != nil:
- req.Request.Body = ioutil.NopCloser(bytes.NewReader(r.BodyBytes))
+ req.Request.Body = io.NopCloser(bytes.NewReader(r.BodyBytes))
default:
if c, ok := r.Body.(io.ReadCloser); ok {
req.Request.Body = c
} else {
- req.Request.Body = ioutil.NopCloser(r.Body)
+ req.Request.Body = io.NopCloser(r.Body)
}
}
diff --git a/api/response.go b/api/response.go
index 2842c12551..23246bf716 100644
--- a/api/response.go
+++ b/api/response.go
@@ -8,7 +8,6 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"net/http"
)
@@ -44,7 +43,7 @@ func (r *Response) Error() error {
}
r.Body.Close()
- r.Body = ioutil.NopCloser(bodyBuf)
+ r.Body = io.NopCloser(bodyBuf)
ns := r.Header.Get(NamespaceHeaderName)
// Build up the error object
diff --git a/api/secret.go b/api/secret.go
index d37bf3cf06..7df9f66a4d 100644
--- a/api/secret.go
+++ b/api/secret.go
@@ -159,6 +159,10 @@ TOKEN_DONE:
goto DONE
}
+ if s.Data["identity_policies"] == nil {
+ goto DONE
+ }
+
sList, ok := s.Data["identity_policies"].([]string)
if ok {
identityPolicies = sList
diff --git a/api/sudo_paths.go b/api/sudo_paths.go
index 24beb4bb1f..d458cbde0f 100644
--- a/api/sudo_paths.go
+++ b/api/sudo_paths.go
@@ -28,6 +28,7 @@ var sudoPaths = map[string]*regexp.Regexp{
"/sys/config/ui/headers": regexp.MustCompile(`^/sys/config/ui/headers/?$`),
"/sys/config/ui/headers/{header}": regexp.MustCompile(`^/sys/config/ui/headers/.+$`),
"/sys/internal/inspect/router/{tag}": regexp.MustCompile(`^/sys/internal/inspect/router/.+$`),
+ "/sys/internal/counters/activity/export": regexp.MustCompile(`^/sys/internal/counters/activity/export$`),
"/sys/leases": regexp.MustCompile(`^/sys/leases$`),
// This entry is a bit wrong... sys/leases/lookup does NOT require sudo. But sys/leases/lookup/ with a trailing
// slash DOES require sudo. But the part of the Vault CLI that uses this logic doesn't pass operation-appropriate
diff --git a/api/sys_raft.go b/api/sys_raft.go
index 699f6e9fd0..f0e896271b 100644
--- a/api/sys_raft.go
+++ b/api/sys_raft.go
@@ -264,7 +264,7 @@ func (c *Sys) RaftSnapshotWithContext(ctx context.Context, snapWriter io.Writer)
continue
}
var b []byte
- b, err = ioutil.ReadAll(t)
+ b, err = io.ReadAll(t)
if err != nil || len(b) == 0 {
return
}
diff --git a/audit/backend.go b/audit/backend.go
index 49d46c8f00..4bce4b6edb 100644
--- a/audit/backend.go
+++ b/audit/backend.go
@@ -19,6 +19,7 @@ import (
const (
optionElideListResponses = "elide_list_responses"
+ optionExclude = "exclude"
optionFallback = "fallback"
optionFilter = "filter"
optionFormat = "format"
@@ -253,6 +254,7 @@ func HasInvalidOptions(options map[string]string) bool {
// are only for use in the Enterprise version of Vault.
func hasEnterpriseAuditOptions(options map[string]string) bool {
enterpriseAuditOptions := []string{
+ optionExclude,
optionFallback,
optionFilter,
}
diff --git a/audit/backend_file.go b/audit/backend_file.go
index a1e07ef0dd..b321c66176 100644
--- a/audit/backend_file.go
+++ b/audit/backend_file.go
@@ -20,9 +20,9 @@ const (
optionMode = "mode"
)
-var _ Backend = (*FileBackend)(nil)
+var _ Backend = (*fileBackend)(nil)
-type FileBackend struct {
+type fileBackend struct {
*backend
}
@@ -34,7 +34,7 @@ func NewFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Back
}
// newFileBackend creates a backend and configures all nodes including a file sink.
-func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBackend, error) {
+func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*fileBackend, error) {
if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
}
@@ -60,7 +60,7 @@ func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBa
if err != nil {
return nil, err
}
- b := &FileBackend{backend: bec}
+ b := &fileBackend{backend: bec}
// normalize file path if configured for stdout
if strings.EqualFold(filePath, stdout) {
@@ -76,12 +76,12 @@ func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBa
return nil, err
}
- var opt []event.Option
+ sinkOpts := []event.Option{event.WithLogger(conf.Logger)}
if mode, ok := conf.Config[optionMode]; ok {
- opt = append(opt, event.WithFileMode(mode))
+ sinkOpts = append(sinkOpts, event.WithFileMode(mode))
}
- err = b.configureSinkNode(conf.MountPath, filePath, cfg.requiredFormat, opt...)
+ err = b.configureSinkNode(conf.MountPath, filePath, cfg.requiredFormat, sinkOpts...)
if err != nil {
return nil, err
}
@@ -89,9 +89,9 @@ func newFileBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*FileBa
return b, nil
}
-// configureSinkNode is used internally by FileBackend to create and configure the
+// configureSinkNode is used internally by fileBackend to create and configure the
// sink node on the backend.
-func (b *FileBackend) configureSinkNode(name string, filePath string, format format, opt ...event.Option) error {
+func (b *fileBackend) configureSinkNode(name string, filePath string, format format, opt ...event.Option) error {
name = strings.TrimSpace(name)
if name == "" {
return fmt.Errorf("name is required: %w", ErrExternalOptions)
@@ -143,7 +143,7 @@ func (b *FileBackend) configureSinkNode(name string, filePath string, format for
}
// Reload will trigger the reload action on the sink node for this backend.
-func (b *FileBackend) Reload() error {
+func (b *fileBackend) Reload() error {
for _, n := range b.nodeMap {
if n.Type() == eventlogger.NodeTypeSink {
return n.Reopen()
diff --git a/audit/backend_file_ce_test.go b/audit/backend_file_ce_test.go
index 34c8e7b5ec..732fbc7eb4 100644
--- a/audit/backend_file_ce_test.go
+++ b/audit/backend_file_ce_test.go
@@ -16,7 +16,7 @@ import (
)
// TestFileBackend_newFileBackend_fallback ensures that we get the correct errors
-// in CE when we try to enable a FileBackend with enterprise options like fallback
+// in CE when we try to enable a fileBackend with enterprise options like fallback
// and filter.
func TestFileBackend_newFileBackend_fallback(t *testing.T) {
t.Parallel()
@@ -62,7 +62,7 @@ func TestFileBackend_newFileBackend_fallback(t *testing.T) {
name := name
tc := tc
t.Run(name, func(t *testing.T) {
- be, err := newFileBackend(tc.backendConfig, &NoopHeaderFormatter{})
+ be, err := newFileBackend(tc.backendConfig, &noopHeaderFormatter{})
if tc.isErrorExpected {
require.Error(t, err)
@@ -97,13 +97,13 @@ func TestFileBackend_newFileBackend_FilterFormatterSink(t *testing.T) {
Logger: hclog.NewNullLogger(),
}
- b, err := newFileBackend(backendConfig, &NoopHeaderFormatter{})
+ b, err := newFileBackend(backendConfig, &noopHeaderFormatter{})
require.Error(t, err)
require.EqualError(t, err, "enterprise-only options supplied: invalid configuration")
// Try without filter option
delete(cfg, "filter")
- b, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
+ b, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err)
require.Len(t, b.nodeIDList, 2)
@@ -133,14 +133,14 @@ func TestBackend_IsFallback(t *testing.T) {
},
}
- be, err := newFileBackend(cfg, &NoopHeaderFormatter{})
+ be, err := newFileBackend(cfg, &noopHeaderFormatter{})
require.Error(t, err)
require.EqualError(t, err, "enterprise-only options supplied: invalid configuration")
// Remove the option and try again
delete(cfg.Config, "fallback")
- be, err = newFileBackend(cfg, &NoopHeaderFormatter{})
+ be, err = newFileBackend(cfg, &noopHeaderFormatter{})
require.NoError(t, err)
require.NotNil(t, be)
require.Equal(t, false, be.IsFallback())
diff --git a/audit/backend_file_test.go b/audit/backend_file_test.go
index 0a6fbf2e90..a69edc469d 100644
--- a/audit/backend_file_test.go
+++ b/audit/backend_file_test.go
@@ -38,7 +38,7 @@ func TestAuditFile_fileModeNew(t *testing.T) {
SaltView: &logical.InmemStorage{},
Logger: hclog.NewNullLogger(),
}
- _, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
+ _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err)
info, err := os.Stat(file)
@@ -71,7 +71,7 @@ func TestAuditFile_fileModeExisting(t *testing.T) {
Logger: hclog.NewNullLogger(),
}
- _, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
+ _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err)
info, err := os.Stat(f.Name())
@@ -105,7 +105,7 @@ func TestAuditFile_fileMode0000(t *testing.T) {
Logger: hclog.NewNullLogger(),
}
- _, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
+ _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err)
info, err := os.Stat(f.Name())
@@ -134,7 +134,7 @@ func TestAuditFile_EventLogger_fileModeNew(t *testing.T) {
Logger: hclog.NewNullLogger(),
}
- _, err = newFileBackend(backendConfig, &NoopHeaderFormatter{})
+ _, err = newFileBackend(backendConfig, &noopHeaderFormatter{})
require.NoError(t, err)
info, err := os.Stat(file)
@@ -267,7 +267,7 @@ func TestFileBackend_newFileBackend(t *testing.T) {
},
MountPath: tc.mountPath,
}
- b, err := newFileBackend(cfg, &NoopHeaderFormatter{})
+ b, err := newFileBackend(cfg, &noopHeaderFormatter{})
if tc.wantErr {
require.Error(t, err)
diff --git a/audit/backend_noop.go b/audit/backend_noop.go
index 3d8862c891..b6d9e195b1 100644
--- a/audit/backend_noop.go
+++ b/audit/backend_noop.go
@@ -35,14 +35,17 @@ type noopWrapper struct {
backend *NoopAudit
}
-// NoopAuditEventListener is a callback used by noopWrapper.Process() to notify
-// of each received audit event.
-type NoopAuditEventListener func(*AuditEvent)
-
-func (n *NoopAudit) SetListener(listener NoopAuditEventListener) {
+// SetListener provides a callback func to the NoopAudit which can be invoked
+// during processing of the Event.
+//
+// Deprecated: SetListener should not be used in new tests.
+func (n *NoopAudit) SetListener(listener func(event *Event)) {
n.listener = listener
}
+// NoopAudit only exists to allow legacy tests to continue working.
+//
+// Deprecated: NoopAudit should not be used in new tests.
type NoopAudit struct {
Config *BackendConfig
@@ -68,16 +71,16 @@ type NoopAudit struct {
nodeIDList []eventlogger.NodeID
nodeMap map[eventlogger.NodeID]eventlogger.Node
- listener NoopAuditEventListener
+ listener func(event *Event)
}
-// NoopHeaderFormatter can be used within no-op audit devices to do nothing when
+// noopHeaderFormatter can be used within no-op audit devices to do nothing when
// it comes to only allow configured headers to appear in the result.
// Whatever is passed in will be returned (nil becomes an empty map) in lowercase.
-type NoopHeaderFormatter struct{}
+type noopHeaderFormatter struct{}
-// ApplyConfig implements the relevant interface to make NoopHeaderFormatter an HeaderFormatter.
-func (f *NoopHeaderFormatter) ApplyConfig(_ context.Context, headers map[string][]string, _ Salter) (result map[string][]string, retErr error) {
+// ApplyConfig implements the relevant interface to make noopHeaderFormatter an HeaderFormatter.
+func (f *noopHeaderFormatter) ApplyConfig(_ context.Context, headers map[string][]string, _ Salter) (result map[string][]string, retErr error) {
if len(headers) < 1 {
return map[string][]string{}, nil
}
@@ -95,6 +98,8 @@ func (f *NoopHeaderFormatter) ApplyConfig(_ context.Context, headers map[string]
// NewNoopAudit should be used to create a NoopAudit as it handles creation of a
// predictable salt and wraps eventlogger nodes so information can be retrieved on
// what they've seen or formatted.
+//
+// Deprecated: NewNoopAudit only exists to allow legacy tests to continue working.
func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
view := &logical.InmemStorage{}
@@ -122,7 +127,7 @@ func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
nodeMap: make(map[eventlogger.NodeID]eventlogger.Node, 2),
}
- cfg, err := newFormatterConfig(&NoopHeaderFormatter{}, nil)
+ cfg, err := newFormatterConfig(&noopHeaderFormatter{}, nil)
if err != nil {
return nil, err
}
@@ -158,6 +163,8 @@ func NewNoopAudit(config *BackendConfig) (*NoopAudit, error) {
// NoopAuditFactory should be used when the test needs a way to access bytes that
// have been formatted by the pipeline during audit requests.
// The records parameter will be repointed to the one used within the pipeline.
+//
+// Deprecated: NoopAuditFactory only exists to allow legacy tests to continue working.
func NoopAuditFactory(records **[][]byte) Factory {
return func(config *BackendConfig, _ HeaderFormatter) (Backend, error) {
n, err := NewNoopAudit(config)
@@ -184,7 +191,7 @@ func (n *noopWrapper) Process(ctx context.Context, e *eventlogger.Event) (*event
var err error
// We're expecting audit events since this is an audit device.
- a, ok := e.Payload.(*AuditEvent)
+ a, ok := e.Payload.(*Event)
if !ok {
return nil, errors.New("cannot parse payload as an audit event")
}
@@ -244,7 +251,7 @@ func (n *noopWrapper) Process(ctx context.Context, e *eventlogger.Event) (*event
// formatted headers that would have made it to the logs via the sink node.
// They only appear in requests.
if a.Subtype == RequestType {
- reqEntry := &RequestEntry{}
+ reqEntry := &entry{}
err = json.Unmarshal(b, &reqEntry)
if err != nil {
return nil, fmt.Errorf("unable to parse formatted audit entry data: %w", err)
@@ -336,6 +343,7 @@ func (n *NoopAudit) IsFallback() bool {
return false
}
+// Deprecated: TestNoopAudit only exists to allow legacy tests to continue working.
func TestNoopAudit(t *testing.T, path string, config map[string]string) *NoopAudit {
cfg := &BackendConfig{
Config: config,
diff --git a/audit/backend_socket.go b/audit/backend_socket.go
index 5e98b64f54..7f5d396a92 100644
--- a/audit/backend_socket.go
+++ b/audit/backend_socket.go
@@ -18,9 +18,9 @@ const (
optionWriteTimeout = "write_timeout"
)
-var _ Backend = (*SocketBackend)(nil)
+var _ Backend = (*socketBackend)(nil)
-type SocketBackend struct {
+type socketBackend struct {
*backend
}
@@ -32,7 +32,7 @@ func NewSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Ba
}
// newSocketBackend creates a backend and configures all nodes including a socket sink.
-func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*SocketBackend, error) {
+func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*socketBackend, error) {
if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
}
@@ -70,6 +70,7 @@ func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sock
sinkOpts := []event.Option{
event.WithSocketType(socketType),
event.WithMaxDuration(writeDeadline),
+ event.WithLogger(conf.Logger),
}
err = event.ValidateOptions(sinkOpts...)
@@ -77,7 +78,7 @@ func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sock
return nil, err
}
- b := &SocketBackend{backend: bec}
+ b := &socketBackend{backend: bec}
// Configure the sink.
cfg, err := newFormatterConfig(headersConfig, conf.Config)
@@ -93,7 +94,7 @@ func newSocketBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sock
return b, nil
}
-func (b *SocketBackend) configureSinkNode(name string, address string, format format, opts ...event.Option) error {
+func (b *socketBackend) configureSinkNode(name string, address string, format format, opts ...event.Option) error {
sinkNodeID, err := event.GenerateNodeID()
if err != nil {
return fmt.Errorf("error generating random NodeID for sink node: %w", err)
@@ -114,7 +115,7 @@ func (b *SocketBackend) configureSinkNode(name string, address string, format fo
}
// Reload will trigger the reload action on the sink node for this backend.
-func (b *SocketBackend) Reload() error {
+func (b *socketBackend) Reload() error {
for _, n := range b.nodeMap {
if n.Type() == eventlogger.NodeTypeSink {
return n.Reopen()
diff --git a/audit/backend_socket_test.go b/audit/backend_socket_test.go
index 49cc408c68..f8386cc507 100644
--- a/audit/backend_socket_test.go
+++ b/audit/backend_socket_test.go
@@ -114,7 +114,7 @@ func TestSocketBackend_newSocketBackend(t *testing.T) {
},
MountPath: tc.mountPath,
}
- b, err := newSocketBackend(cfg, &NoopHeaderFormatter{})
+ b, err := newSocketBackend(cfg, &noopHeaderFormatter{})
if tc.wantErr {
require.Error(t, err)
diff --git a/audit/backend_syslog.go b/audit/backend_syslog.go
index a554372607..b0fd90efa9 100644
--- a/audit/backend_syslog.go
+++ b/audit/backend_syslog.go
@@ -15,9 +15,9 @@ const (
optionTag = "tag"
)
-var _ Backend = (*SyslogBackend)(nil)
+var _ Backend = (*syslogBackend)(nil)
-type SyslogBackend struct {
+type syslogBackend struct {
*backend
}
@@ -29,7 +29,7 @@ func NewSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (be Ba
}
// newSyslogBackend creates a backend and configures all nodes including a socket sink.
-func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*SyslogBackend, error) {
+func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*syslogBackend, error) {
if headersConfig == nil || reflect.ValueOf(headersConfig).IsNil() {
return nil, fmt.Errorf("nil header formatter: %w", ErrInvalidParameter)
}
@@ -60,6 +60,7 @@ func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sysl
sinkOpts := []event.Option{
event.WithFacility(facility),
event.WithTag(tag),
+ event.WithLogger(conf.Logger),
}
err = event.ValidateOptions(sinkOpts...)
@@ -67,7 +68,7 @@ func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sysl
return nil, err
}
- b := &SyslogBackend{backend: bec}
+ b := &syslogBackend{backend: bec}
// Configure the sink.
cfg, err := newFormatterConfig(headersConfig, conf.Config)
@@ -83,7 +84,7 @@ func newSyslogBackend(conf *BackendConfig, headersConfig HeaderFormatter) (*Sysl
return b, nil
}
-func (b *SyslogBackend) configureSinkNode(name string, format format, opts ...event.Option) error {
+func (b *syslogBackend) configureSinkNode(name string, format format, opts ...event.Option) error {
sinkNodeID, err := event.GenerateNodeID()
if err != nil {
return fmt.Errorf("error generating random NodeID for sink node: %w: %w", ErrInternal, err)
@@ -103,6 +104,6 @@ func (b *SyslogBackend) configureSinkNode(name string, format format, opts ...ev
}
// Reload will trigger the reload action on the sink node for this backend.
-func (b *SyslogBackend) Reload() error {
+func (b *syslogBackend) Reload() error {
return nil
}
diff --git a/audit/backend_syslog_test.go b/audit/backend_syslog_test.go
index ac5a6d3d26..f81c281049 100644
--- a/audit/backend_syslog_test.go
+++ b/audit/backend_syslog_test.go
@@ -97,7 +97,7 @@ func TestSyslogBackend_newSyslogBackend(t *testing.T) {
},
MountPath: tc.mountPath,
}
- b, err := newSyslogBackend(cfg, &NoopHeaderFormatter{})
+ b, err := newSyslogBackend(cfg, &noopHeaderFormatter{})
if tc.wantErr {
require.Error(t, err)
diff --git a/audit/backend_test.go b/audit/backend_test.go
index f2a2da3630..000b827f6c 100644
--- a/audit/backend_test.go
+++ b/audit/backend_test.go
@@ -25,7 +25,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
}{
"happy-path-json": {
config: map[string]string{
- "format": JSONFormat.String(),
+ "format": jsonFormat.String(),
"hmac_accessor": "true",
"log_raw": "true",
"elide_list_responses": "true",
@@ -39,7 +39,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
},
"happy-path-jsonx": {
config: map[string]string{
- "format": JSONxFormat.String(),
+ "format": jsonxFormat.String(),
"hmac_accessor": "true",
"log_raw": "true",
"elide_list_responses": "true",
@@ -65,7 +65,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
},
"invalid-hmac-accessor": {
config: map[string]string{
- "format": JSONFormat.String(),
+ "format": jsonFormat.String(),
"hmac_accessor": "maybe",
},
want: formatterConfig{},
@@ -74,7 +74,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
},
"invalid-log-raw": {
config: map[string]string{
- "format": JSONFormat.String(),
+ "format": jsonFormat.String(),
"hmac_accessor": "true",
"log_raw": "maybe",
},
@@ -84,7 +84,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
},
"invalid-elide-bool": {
config: map[string]string{
- "format": JSONFormat.String(),
+ "format": jsonFormat.String(),
"hmac_accessor": "true",
"log_raw": "true",
"elide_list_responses": "maybe",
@@ -95,11 +95,11 @@ func TestBackend_newFormatterConfig(t *testing.T) {
},
"prefix": {
config: map[string]string{
- "format": JSONFormat.String(),
+ "format": jsonFormat.String(),
"prefix": "foo",
},
want: formatterConfig{
- requiredFormat: JSONFormat,
+ requiredFormat: jsonFormat,
prefix: "foo",
hmacAccessor: true,
},
@@ -111,7 +111,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
- got, err := newFormatterConfig(&NoopHeaderFormatter{}, tc.config)
+ got, err := newFormatterConfig(&noopHeaderFormatter{}, tc.config)
if tc.wantErr {
require.Error(t, err)
require.EqualError(t, err, tc.expectedMessage)
@@ -133,7 +133,7 @@ func TestBackend_newFormatterConfig(t *testing.T) {
func TestBackend_configureFormatterNode(t *testing.T) {
t.Parallel()
- b, err := newBackend(&NoopHeaderFormatter{}, &BackendConfig{
+ b, err := newBackend(&noopHeaderFormatter{}, &BackendConfig{
MountPath: "foo",
Logger: hclog.NewNullLogger(),
})
@@ -188,6 +188,15 @@ func TestBackend_hasEnterpriseAuditOptions(t *testing.T) {
},
expected: true,
},
+ "ent-opt-exclude": {
+ input: map[string]string{
+ "exclude": `{
+ "condition": "\"/request/mount_type\" == transit",
+ "fields": [ "/request/data", "/response/data" ]
+ }`,
+ },
+ expected: true,
+ },
}
for name, tc := range tests {
@@ -241,6 +250,15 @@ func TestBackend_hasInvalidAuditOptions(t *testing.T) {
},
expected: !constants.IsEnterprise,
},
+ "ent-opt-exclude": {
+ input: map[string]string{
+ "exclude": `{
+ "condition": "\"/request/mount_type\" == transit",
+ "fields": [ "/request/data", "/response/data" ]
+ }`,
+ },
+ expected: !constants.IsEnterprise,
+ },
}
for name, tc := range tests {
diff --git a/audit/broker.go b/audit/broker.go
index 2681ca0ede..601831eab0 100644
--- a/audit/broker.go
+++ b/audit/broker.go
@@ -15,8 +15,7 @@ import (
"github.com/armon/go-metrics"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog"
- "github.com/hashicorp/go-multierror"
- "github.com/hashicorp/vault/helper/namespace"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/internal/observability/event"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -253,7 +252,7 @@ func (b *Broker) Deregister(ctx context.Context, name string) error {
// LogRequest is used to ensure all the audit backends have an opportunity to
// log the given request and that *at least one* succeeds.
-func (b *Broker) LogRequest(ctx context.Context, in *logical.LogInput) (ret error) {
+func (b *Broker) LogRequest(ctx context.Context, in *logical.LogInput) (retErr error) {
b.RLock()
defer b.RUnlock()
@@ -265,18 +264,15 @@ func (b *Broker) LogRequest(ctx context.Context, in *logical.LogInput) (ret erro
defer metrics.MeasureSince([]string{"audit", "log_request"}, time.Now())
defer func() {
metricVal := float32(0.0)
- if ret != nil {
+ if retErr != nil {
metricVal = 1.0
}
metrics.IncrCounter([]string{"audit", "log_request_failure"}, metricVal)
}()
- var retErr *multierror.Error
-
- e, err := NewEvent(RequestType)
+ e, err := newEvent(RequestType)
if err != nil {
- retErr = multierror.Append(retErr, err)
- return retErr.ErrorOrNil()
+ return err
}
e.Data = in
@@ -293,49 +289,54 @@ func (b *Broker) LogRequest(ctx context.Context, in *logical.LogInput) (ret erro
// has taken up a lot of time handling the request before audit (request)
// is triggered. Pipeline nodes and the eventlogger.Broker may check for a
// cancelled context and refuse to process the nodes further.
- ns, err := namespace.FromContext(ctx)
+ ns, err := nshelper.FromContext(ctx)
if err != nil {
- retErr = multierror.Append(retErr, fmt.Errorf("namespace missing from context: %w", err))
- return retErr.ErrorOrNil()
+ return fmt.Errorf("namespace missing from context: %w", err)
}
tempContext, auditCancel := context.WithTimeout(context.Background(), timeout)
defer auditCancel()
- auditContext = namespace.ContextWithNamespace(tempContext, ns)
+ auditContext = nshelper.ContextWithNamespace(tempContext, ns)
+
+ b.logger.Trace("log request requires a derived context (original context was not viable)", "namespace ID", ns.ID, "namespace path", ns.Path, "timeout", timeout)
}
var status eventlogger.Status
if hasAuditPipelines(b.broker) {
status, err = b.broker.Send(auditContext, event.AuditType.AsEventType(), e)
if err != nil {
- retErr = multierror.Append(retErr, multierror.Append(err, status.Warnings...))
- return retErr.ErrorOrNil()
+ return errors.Join(append([]error{err}, status.Warnings...)...)
}
}
// Audit event ended up in at least 1 sink.
if len(status.CompleteSinks()) > 0 {
- return retErr.ErrorOrNil()
+ // We should log warnings to the operational logs regardless of whether
+ // we consider the overall auditing attempt to be successful.
+ if len(status.Warnings) > 0 {
+ b.logger.Error("log request underlying pipeline error(s)", "error", errors.Join(status.Warnings...))
+ }
+
+ return nil
}
// There were errors from inside the pipeline and we didn't write to a sink.
if len(status.Warnings) > 0 {
- retErr = multierror.Append(retErr, multierror.Append(errors.New("error during audit pipeline processing"), status.Warnings...))
- return retErr.ErrorOrNil()
+ return fmt.Errorf("error during audit pipeline processing: %w", errors.Join(status.Warnings...))
}
// Handle any additional audit that is required (Enterprise/CE dependant).
err = b.handleAdditionalAudit(auditContext, e)
if err != nil {
- retErr = multierror.Append(retErr, err)
+ return err
}
- return retErr.ErrorOrNil()
+ return nil
}
// LogResponse is used to ensure all the audit backends have an opportunity to
// log the given response and that *at least one* succeeds.
-func (b *Broker) LogResponse(ctx context.Context, in *logical.LogInput) (ret error) {
+func (b *Broker) LogResponse(ctx context.Context, in *logical.LogInput) (retErr error) {
b.RLock()
defer b.RUnlock()
@@ -347,18 +348,15 @@ func (b *Broker) LogResponse(ctx context.Context, in *logical.LogInput) (ret err
defer metrics.MeasureSince([]string{"audit", "log_response"}, time.Now())
defer func() {
metricVal := float32(0.0)
- if ret != nil {
+ if retErr != nil {
metricVal = 1.0
}
metrics.IncrCounter([]string{"audit", "log_response_failure"}, metricVal)
}()
- var retErr *multierror.Error
-
- e, err := NewEvent(ResponseType)
+ e, err := newEvent(ResponseType)
if err != nil {
- retErr = multierror.Append(retErr, err)
- return retErr.ErrorOrNil()
+ return err
}
e.Data = in
@@ -375,44 +373,49 @@ func (b *Broker) LogResponse(ctx context.Context, in *logical.LogInput) (ret err
// has taken up a lot of time handling the request before audit (response)
// is triggered. Pipeline nodes and the eventlogger.Broker may check for a
// cancelled context and refuse to process the nodes further.
- ns, err := namespace.FromContext(ctx)
+ ns, err := nshelper.FromContext(ctx)
if err != nil {
- retErr = multierror.Append(retErr, fmt.Errorf("namespace missing from context: %w", err))
- return retErr.ErrorOrNil()
+ return fmt.Errorf("namespace missing from context: %w", err)
}
tempContext, auditCancel := context.WithTimeout(context.Background(), timeout)
defer auditCancel()
- auditContext = namespace.ContextWithNamespace(tempContext, ns)
+ auditContext = nshelper.ContextWithNamespace(tempContext, ns)
+
+ b.logger.Trace("log response requires a derived context (original context was not viable)", "namespace ID", ns.ID, "namespace path", ns.Path, "timeout", timeout)
}
var status eventlogger.Status
if hasAuditPipelines(b.broker) {
status, err = b.broker.Send(auditContext, event.AuditType.AsEventType(), e)
if err != nil {
- retErr = multierror.Append(retErr, multierror.Append(err, status.Warnings...))
- return retErr.ErrorOrNil()
+ return errors.Join(append([]error{err}, status.Warnings...)...)
}
}
// Audit event ended up in at least 1 sink.
if len(status.CompleteSinks()) > 0 {
- return retErr.ErrorOrNil()
+ // We should log warnings to the operational logs regardless of whether
+ // we consider the overall auditing attempt to be successful.
+ if len(status.Warnings) > 0 {
+ b.logger.Error("log response underlying pipeline error(s)", "error", errors.Join(status.Warnings...))
+ }
+
+ return nil
}
// There were errors from inside the pipeline and we didn't write to a sink.
if len(status.Warnings) > 0 {
- retErr = multierror.Append(retErr, multierror.Append(errors.New("error during audit pipeline processing"), status.Warnings...))
- return retErr.ErrorOrNil()
+ return fmt.Errorf("error during audit pipeline processing: %w", errors.Join(status.Warnings...))
}
// Handle any additional audit that is required (Enterprise/CE dependant).
err = b.handleAdditionalAudit(auditContext, e)
if err != nil {
- retErr = multierror.Append(retErr, err)
+ return err
}
- return retErr.ErrorOrNil()
+ return nil
}
func (b *Broker) Invalidate(ctx context.Context, _ string) {
@@ -449,7 +452,7 @@ func (b *Broker) GetHash(ctx context.Context, name string, input string) (string
return "", fmt.Errorf("unknown audit backend %q", name)
}
- return HashString(ctx, be.backend, input)
+ return hashString(ctx, be.backend, input)
}
// IsRegistered is used to check if a given audit backend is registered.
@@ -462,6 +465,8 @@ func (b *Broker) IsRegistered(name string) bool {
// isContextViable examines the supplied context to see if its own deadline would
// occur later than a newly created context with a specific timeout.
+// Additionally, whether the supplied context is already cancelled, thus making it
+// unviable.
// If the existing context is viable it can be used 'as-is', if not, the caller
// should consider creating a new context with the relevant deadline and associated
// context values (e.g. namespace) in order to reduce the likelihood that the
@@ -472,6 +477,12 @@ func isContextViable(ctx context.Context) bool {
return false
}
+ select {
+ case <-ctx.Done():
+ return false
+ default:
+ }
+
deadline, hasDeadline := ctx.Deadline()
// If there's no deadline on the context then we don't need to worry about
diff --git a/audit/broker_ce.go b/audit/broker_ce.go
index 1ec3bff7d0..7a2d56e992 100644
--- a/audit/broker_ce.go
+++ b/audit/broker_ce.go
@@ -44,6 +44,6 @@ func (b *Broker) requiredSuccessThresholdSinks() int {
return 0
}
-func (b *brokerEnt) handleAdditionalAudit(_ context.Context, _ *AuditEvent) error {
+func (b *brokerEnt) handleAdditionalAudit(_ context.Context, _ *Event) error {
return nil
}
diff --git a/audit/broker_test.go b/audit/broker_test.go
index 074cb203f0..1fd6d54577 100644
--- a/audit/broker_test.go
+++ b/audit/broker_test.go
@@ -10,7 +10,7 @@ import (
"time"
"github.com/hashicorp/go-hclog"
- "github.com/hashicorp/vault/helper/namespace"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/logical"
@@ -23,7 +23,7 @@ func testAuditBackend(t *testing.T, path string, config map[string]string) Backe
t.Helper()
headersCfg := &HeadersConfig{
- headerSettings: make(map[string]*HeaderSettings),
+ headerSettings: make(map[string]*headerSettings),
view: nil,
}
@@ -148,7 +148,7 @@ func BenchmarkAuditBroker_File_Request_DevNull(b *testing.B) {
},
}
- ctx := namespace.RootContext(context.Background())
+ ctx := nshelper.RootContext(context.Background())
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
@@ -160,11 +160,14 @@ func BenchmarkAuditBroker_File_Request_DevNull(b *testing.B) {
}
// TestBroker_isContextViable_basics checks the expected result of isContextViable
-// for basic inputs such as nil and a never-ending context.
+// for basic inputs such as nil, cancelled context and a never-ending context.
func TestBroker_isContextViable_basics(t *testing.T) {
t.Parallel()
require.False(t, isContextViable(nil))
+ ctx, cancel := context.WithCancel(context.Background())
+ cancel()
+ require.False(t, isContextViable(ctx))
require.True(t, isContextViable(context.Background()))
}
diff --git a/audit/entry_filter.go b/audit/entry_filter.go
index 5ddf6b2c27..fbe0c1a1e7 100644
--- a/audit/entry_filter.go
+++ b/audit/entry_filter.go
@@ -10,7 +10,7 @@ import (
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-bexpr"
- "github.com/hashicorp/vault/helper/namespace"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -71,7 +71,7 @@ func (f *entryFilter) Process(ctx context.Context, e *eventlogger.Event) (*event
return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
}
- a, ok := e.Payload.(*AuditEvent)
+ a, ok := e.Payload.(*Event)
if !ok {
return nil, fmt.Errorf("cannot parse event payload: %w", ErrInvalidParameter)
}
@@ -81,7 +81,7 @@ func (f *entryFilter) Process(ctx context.Context, e *eventlogger.Event) (*event
return nil, nil
}
- ns, err := namespace.FromContext(ctx)
+ ns, err := nshelper.FromContext(ctx)
if err != nil {
return nil, fmt.Errorf("cannot obtain namespace: %w", err)
}
diff --git a/audit/entry_filter_test.go b/audit/entry_filter_test.go
index 43ec7db818..847f4ab799 100644
--- a/audit/entry_filter_test.go
+++ b/audit/entry_filter_test.go
@@ -9,7 +9,7 @@ import (
"time"
"github.com/hashicorp/eventlogger"
- "github.com/hashicorp/vault/helper/namespace"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/internal/observability/event"
"github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require"
@@ -117,7 +117,7 @@ func TestEntryFilter_Process_ContextDone(t *testing.T) {
require.NoError(t, err)
// Fake audit event
- a, err := NewEvent(RequestType)
+ a, err := newEvent(RequestType)
require.NoError(t, err)
// Fake event logger event
@@ -184,7 +184,7 @@ func TestEntryFilter_Process_NoAuditDataInPayload(t *testing.T) {
l, err := newEntryFilter("operation == foo")
require.NoError(t, err)
- a, err := NewEvent(RequestType)
+ a, err := newEvent(RequestType)
require.NoError(t, err)
// Ensure audit data is nil
@@ -212,7 +212,7 @@ func TestEntryFilter_Process_FilterSuccess(t *testing.T) {
l, err := newEntryFilter("mount_type == juan")
require.NoError(t, err)
- a, err := NewEvent(RequestType)
+ a, err := newEvent(RequestType)
require.NoError(t, err)
a.Data = &logical.LogInput{
@@ -229,7 +229,7 @@ func TestEntryFilter_Process_FilterSuccess(t *testing.T) {
Payload: a,
}
- ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)
+ ctx := nshelper.ContextWithNamespace(context.Background(), nshelper.RootNamespace)
e2, err := l.Process(ctx, e)
@@ -245,7 +245,7 @@ func TestEntryFilter_Process_FilterFail(t *testing.T) {
l, err := newEntryFilter("mount_type == john and operation == create and namespace == root")
require.NoError(t, err)
- a, err := NewEvent(RequestType)
+ a, err := newEvent(RequestType)
require.NoError(t, err)
a.Data = &logical.LogInput{
@@ -262,7 +262,7 @@ func TestEntryFilter_Process_FilterFail(t *testing.T) {
Payload: a,
}
- ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)
+ ctx := nshelper.ContextWithNamespace(context.Background(), nshelper.RootNamespace)
e2, err := l.Process(ctx, e)
diff --git a/audit/entry_formatter.go b/audit/entry_formatter.go
index 74c0c4035e..accd8bbf64 100644
--- a/audit/entry_formatter.go
+++ b/audit/entry_formatter.go
@@ -5,8 +5,6 @@ package audit
import (
"context"
- "crypto/tls"
- "errors"
"fmt"
"reflect"
"runtime/debug"
@@ -17,11 +15,12 @@ import (
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror"
- "github.com/hashicorp/vault/helper/namespace"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/logical"
"github.com/jefferai/jsonx"
+ "github.com/mitchellh/copystructure"
)
var _ eventlogger.Node = (*entryFormatter)(nil)
@@ -78,7 +77,7 @@ func (*entryFormatter) Type() eventlogger.NodeType {
}
// Process will attempt to parse the incoming event data into a corresponding
-// audit Request/Response which is serialized to JSON/JSONx and stored within the event.
+// audit request/response which is serialized to JSON/JSONx and stored within the event.
func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *eventlogger.Event, retErr error) {
// Return early if the context was cancelled, eventlogger will not carry on
// asking nodes to process, so any sink node in the pipeline won't be called.
@@ -94,13 +93,13 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
}
- a, ok := e.Payload.(*AuditEvent)
+ a, ok := e.Payload.(*Event)
if !ok {
return nil, fmt.Errorf("cannot parse event payload: %w", ErrInvalidParameter)
}
if a.Data == nil {
- return nil, fmt.Errorf("cannot audit event (%s) with no data: %w", a.Subtype, ErrInvalidParameter)
+ return nil, fmt.Errorf("cannot audit a '%s' event with no data: %w", a.Subtype, ErrInvalidParameter)
}
// Handle panics
@@ -110,8 +109,13 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
return
}
+ path := "unknown"
+ if a.Data.Request != nil {
+ path = a.Data.Request.Path
+ }
+
f.logger.Error("panic during logging",
- "request_path", a.Data.Request.Path,
+ "request_path", path,
"audit_device_path", f.name,
"error", r,
"stacktrace", string(debug.Stack()))
@@ -120,46 +124,23 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
retErr = multierror.Append(retErr, fmt.Errorf("panic generating audit log: %q", f.name)).ErrorOrNil()
}()
- // Take a copy of the event data before we modify anything.
- data, err := a.Data.Clone()
- if err != nil {
- return nil, fmt.Errorf("unable to clone audit event data: %w", err)
- }
-
- // If the request is present in the input data, apply header configuration
- // regardless. We shouldn't be in a situation where the header formatter isn't
- // present as it's required.
- if data.Request != nil {
- // Ensure that any headers in the request, are formatted as required, and are
- // only present if they have been configured to appear in the audit log.
- // e.g. via: /sys/config/auditing/request-headers/:name
- data.Request.Headers, err = f.config.headerFormatter.ApplyConfig(ctx, data.Request.Headers, f.salter)
- if err != nil {
- return nil, fmt.Errorf("unable to transform headers for auditing: %w", err)
- }
- }
-
- // If the request contains a Server-Side Consistency Token (SSCT), and we
- // have an auth response, overwrite the existing client token with the SSCT,
- // so that the SSCT appears in the audit log for this entry.
- if data.Request != nil && data.Request.InboundSSCToken != "" && data.Auth != nil {
- data.Auth.ClientToken = data.Request.InboundSSCToken
- }
-
- // Using 'any' as we have two different types that we can get back from either
- // formatRequest or formatResponse, but the JSON encoder doesn't care about types.
+ // Using 'any' to make exclusion easier, the JSON encoder doesn't care about types.
var entry any
-
- switch a.Subtype {
- case RequestType:
- entry, err = f.formatRequest(ctx, data, a)
- case ResponseType:
- entry, err = f.formatResponse(ctx, data, a)
- default:
- return nil, fmt.Errorf("unknown audit event subtype: %q", a.Subtype)
- }
+ var err error
+ entry, err = f.createEntry(ctx, a)
if err != nil {
- return nil, fmt.Errorf("unable to parse %s from audit event: %w", a.Subtype, err)
+ return nil, err
+ }
+
+ // If this pipeline has been configured with (Enterprise-only) exclusions then
+ // attempt to exclude the fields from the audit entry.
+ if f.shouldExclude() {
+ m, err := f.excludeFields(entry)
+ if err != nil {
+ return nil, fmt.Errorf("unable to exclude %s audit data from %q: %w", a.Subtype, f.name, err)
+ }
+
+ entry = m
}
result, err := jsonutil.EncodeJSON(entry)
@@ -167,7 +148,7 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
return nil, fmt.Errorf("unable to format %s: %w", a.Subtype, err)
}
- if f.config.requiredFormat == JSONxFormat {
+ if f.config.requiredFormat == jsonxFormat {
var err error
result, err = jsonx.EncodeJSONBytes(result)
if err != nil {
@@ -186,21 +167,12 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
result = append([]byte(f.config.prefix), result...)
}
- // Copy some properties from the event (and audit event) and store the
- // format for the next (sink) node to Process.
- a2 := &AuditEvent{
- ID: a.ID,
- Version: a.Version,
- Subtype: a.Subtype,
- Timestamp: a.Timestamp,
- Data: data, // Use the cloned data here rather than a pointer to the original.
- }
-
+ // Create a new event, so we can store our formatted data without conflict.
e2 := &eventlogger.Event{
Type: e.Type,
CreatedAt: e.CreatedAt,
Formatted: make(map[string][]byte), // we are about to set this ourselves.
- Payload: a2,
+ Payload: a,
}
e2.FormattedAs(f.config.requiredFormat.String(), result)
@@ -208,377 +180,31 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ *
return e2, nil
}
-// formatRequest attempts to format the specified logical.LogInput into a RequestEntry.
-func (f *entryFormatter) formatRequest(ctx context.Context, in *logical.LogInput, provider timeProvider) (*RequestEntry, error) {
- switch {
- case in == nil || in.Request == nil:
- return nil, errors.New("request to request-audit a nil request")
- case f.salter == nil:
- return nil, errors.New("salt func not configured")
- }
-
- // Set these to the input values at first
- auth := in.Auth
- req := in.Request
- var connState *tls.ConnectionState
- if auth == nil {
- auth = new(logical.Auth)
- }
-
- if in.Request.Connection != nil && in.Request.Connection.ConnState != nil {
- connState = in.Request.Connection.ConnState
- }
-
- if !f.config.raw {
- var err error
- auth, err = HashAuth(ctx, f.salter, auth, f.config.hmacAccessor)
- if err != nil {
- return nil, err
- }
-
- req, err = HashRequest(ctx, f.salter, req, f.config.hmacAccessor, in.NonHMACReqDataKeys)
- if err != nil {
- return nil, err
- }
- }
-
- var errString string
- if in.OuterErr != nil {
- errString = in.OuterErr.Error()
- }
-
- ns, err := namespace.FromContext(ctx)
- if err != nil {
- return nil, err
- }
-
- reqType := in.Type
- if reqType == "" {
- reqType = "request"
- }
- reqEntry := &RequestEntry{
- Type: reqType,
- Error: errString,
- ForwardedFrom: req.ForwardedFrom,
- Auth: &Auth{
- ClientToken: auth.ClientToken,
- Accessor: auth.Accessor,
- DisplayName: auth.DisplayName,
- Policies: auth.Policies,
- TokenPolicies: auth.TokenPolicies,
- IdentityPolicies: auth.IdentityPolicies,
- ExternalNamespacePolicies: auth.ExternalNamespacePolicies,
- NoDefaultPolicy: auth.NoDefaultPolicy,
- Metadata: auth.Metadata,
- EntityID: auth.EntityID,
- RemainingUses: req.ClientTokenRemainingUses,
- TokenType: auth.TokenType.String(),
- TokenTTL: int64(auth.TTL.Seconds()),
- },
-
- Request: &Request{
- ID: req.ID,
- ClientID: req.ClientID,
- ClientToken: req.ClientToken,
- ClientTokenAccessor: req.ClientTokenAccessor,
- Operation: req.Operation,
- MountPoint: req.MountPoint,
- MountType: req.MountType,
- MountAccessor: req.MountAccessor,
- MountRunningVersion: req.MountRunningVersion(),
- MountRunningSha256: req.MountRunningSha256(),
- MountIsExternalPlugin: req.MountIsExternalPlugin(),
- MountClass: req.MountClass(),
- Namespace: &Namespace{
- ID: ns.ID,
- Path: ns.Path,
- },
- Path: req.Path,
- Data: req.Data,
- PolicyOverride: req.PolicyOverride,
- RemoteAddr: getRemoteAddr(req),
- RemotePort: getRemotePort(req),
- ReplicationCluster: req.ReplicationCluster,
- Headers: req.Headers,
- ClientCertificateSerialNumber: getClientCertificateSerialNumber(connState),
- },
- }
-
- if req.HTTPRequest != nil && req.HTTPRequest.RequestURI != req.Path {
- reqEntry.Request.RequestURI = req.HTTPRequest.RequestURI
- }
-
- if !auth.IssueTime.IsZero() {
- reqEntry.Auth.TokenIssueTime = auth.IssueTime.Format(time.RFC3339)
- }
-
- if auth.PolicyResults != nil {
- reqEntry.Auth.PolicyResults = &PolicyResults{
- Allowed: auth.PolicyResults.Allowed,
- }
-
- for _, p := range auth.PolicyResults.GrantingPolicies {
- reqEntry.Auth.PolicyResults.GrantingPolicies = append(reqEntry.Auth.PolicyResults.GrantingPolicies, PolicyInfo{
- Name: p.Name,
- NamespaceId: p.NamespaceId,
- NamespacePath: p.NamespacePath,
- Type: p.Type,
- })
- }
- }
-
- if req.WrapInfo != nil {
- reqEntry.Request.WrapTTL = int(req.WrapInfo.TTL / time.Second)
- }
-
- if !f.config.omitTime {
- // Use the time provider to supply the time for this entry.
- reqEntry.Time = provider.formattedTime()
- }
-
- return reqEntry, nil
-}
-
-// formatResponse attempts to format the specified logical.LogInput into a ResponseEntry.
-func (f *entryFormatter) formatResponse(ctx context.Context, in *logical.LogInput, provider timeProvider) (*ResponseEntry, error) {
- switch {
- case f == nil:
- return nil, errors.New("formatter is nil")
- case in == nil || in.Request == nil:
- return nil, errors.New("request to response-audit a nil request")
- case f.salter == nil:
- return nil, errors.New("salt func not configured")
- }
-
- // Set these to the input values at first
- auth, req, resp := in.Auth, in.Request, in.Response
- if auth == nil {
- auth = new(logical.Auth)
- }
- if resp == nil {
- resp = new(logical.Response)
- }
- var connState *tls.ConnectionState
-
- if in.Request.Connection != nil && in.Request.Connection.ConnState != nil {
- connState = in.Request.Connection.ConnState
- }
-
- elideListResponseData := f.config.elideListResponses && req.Operation == logical.ListOperation
-
- var respData map[string]interface{}
- if f.config.raw {
- // In the non-raw case, elision of list response data occurs inside HashResponse, to avoid redundant deep
- // copies and hashing of data only to elide it later. In the raw case, we need to do it here.
- if elideListResponseData && resp.Data != nil {
- // Copy the data map before making changes, but we only need to go one level deep in this case
- respData = make(map[string]interface{}, len(resp.Data))
- for k, v := range resp.Data {
- respData[k] = v
- }
-
- doElideListResponseData(respData)
- } else {
- respData = resp.Data
- }
- } else {
- var err error
- auth, err = HashAuth(ctx, f.salter, auth, f.config.hmacAccessor)
- if err != nil {
- return nil, err
- }
-
- req, err = HashRequest(ctx, f.salter, req, f.config.hmacAccessor, in.NonHMACReqDataKeys)
- if err != nil {
- return nil, err
- }
-
- resp, err = HashResponse(ctx, f.salter, resp, f.config.hmacAccessor, in.NonHMACRespDataKeys, elideListResponseData)
- if err != nil {
- return nil, err
- }
-
- respData = resp.Data
- }
-
- var errString string
- if in.OuterErr != nil {
- errString = in.OuterErr.Error()
- }
-
- ns, err := namespace.FromContext(ctx)
- if err != nil {
- return nil, err
- }
-
- var respAuth *Auth
- if resp.Auth != nil {
- respAuth = &Auth{
- ClientToken: resp.Auth.ClientToken,
- Accessor: resp.Auth.Accessor,
- DisplayName: resp.Auth.DisplayName,
- Policies: resp.Auth.Policies,
- TokenPolicies: resp.Auth.TokenPolicies,
- IdentityPolicies: resp.Auth.IdentityPolicies,
- ExternalNamespacePolicies: resp.Auth.ExternalNamespacePolicies,
- NoDefaultPolicy: resp.Auth.NoDefaultPolicy,
- Metadata: resp.Auth.Metadata,
- NumUses: resp.Auth.NumUses,
- EntityID: resp.Auth.EntityID,
- TokenType: resp.Auth.TokenType.String(),
- TokenTTL: int64(resp.Auth.TTL.Seconds()),
- }
- if !resp.Auth.IssueTime.IsZero() {
- respAuth.TokenIssueTime = resp.Auth.IssueTime.Format(time.RFC3339)
- }
- }
-
- var respSecret *Secret
- if resp.Secret != nil {
- respSecret = &Secret{
- LeaseID: resp.Secret.LeaseID,
- }
- }
-
- var respWrapInfo *ResponseWrapInfo
- if resp.WrapInfo != nil {
- token := resp.WrapInfo.Token
- if jwtToken := parseVaultTokenFromJWT(token); jwtToken != nil {
- token = *jwtToken
- }
- respWrapInfo = &ResponseWrapInfo{
- TTL: int(resp.WrapInfo.TTL / time.Second),
- Token: token,
- Accessor: resp.WrapInfo.Accessor,
- CreationTime: resp.WrapInfo.CreationTime.UTC().Format(time.RFC3339Nano),
- CreationPath: resp.WrapInfo.CreationPath,
- WrappedAccessor: resp.WrapInfo.WrappedAccessor,
- }
- }
-
- respType := in.Type
- if respType == "" {
- respType = "response"
- }
- respEntry := &ResponseEntry{
- Type: respType,
- Error: errString,
- Forwarded: req.ForwardedFrom != "",
- Auth: &Auth{
- ClientToken: auth.ClientToken,
- Accessor: auth.Accessor,
- DisplayName: auth.DisplayName,
- Policies: auth.Policies,
- TokenPolicies: auth.TokenPolicies,
- IdentityPolicies: auth.IdentityPolicies,
- ExternalNamespacePolicies: auth.ExternalNamespacePolicies,
- NoDefaultPolicy: auth.NoDefaultPolicy,
- Metadata: auth.Metadata,
- RemainingUses: req.ClientTokenRemainingUses,
- EntityID: auth.EntityID,
- EntityCreated: auth.EntityCreated,
- TokenType: auth.TokenType.String(),
- TokenTTL: int64(auth.TTL.Seconds()),
- },
-
- Request: &Request{
- ID: req.ID,
- ClientToken: req.ClientToken,
- ClientTokenAccessor: req.ClientTokenAccessor,
- ClientID: req.ClientID,
- Operation: req.Operation,
- MountPoint: req.MountPoint,
- MountType: req.MountType,
- MountAccessor: req.MountAccessor,
- MountRunningVersion: req.MountRunningVersion(),
- MountRunningSha256: req.MountRunningSha256(),
- MountIsExternalPlugin: req.MountIsExternalPlugin(),
- MountClass: req.MountClass(),
- Namespace: &Namespace{
- ID: ns.ID,
- Path: ns.Path,
- },
- Path: req.Path,
- Data: req.Data,
- PolicyOverride: req.PolicyOverride,
- RemoteAddr: getRemoteAddr(req),
- RemotePort: getRemotePort(req),
- ClientCertificateSerialNumber: getClientCertificateSerialNumber(connState),
- ReplicationCluster: req.ReplicationCluster,
- Headers: req.Headers,
- },
-
- Response: &Response{
- MountPoint: req.MountPoint,
- MountType: req.MountType,
- MountAccessor: req.MountAccessor,
- MountRunningVersion: req.MountRunningVersion(),
- MountRunningSha256: req.MountRunningSha256(),
- MountIsExternalPlugin: req.MountIsExternalPlugin(),
- MountClass: req.MountClass(),
- Auth: respAuth,
- Secret: respSecret,
- Data: respData,
- Warnings: resp.Warnings,
- Redirect: resp.Redirect,
- WrapInfo: respWrapInfo,
- Headers: resp.Headers,
- },
- }
-
- if req.HTTPRequest != nil && req.HTTPRequest.RequestURI != req.Path {
- respEntry.Request.RequestURI = req.HTTPRequest.RequestURI
- }
-
- if auth.PolicyResults != nil {
- respEntry.Auth.PolicyResults = &PolicyResults{
- Allowed: auth.PolicyResults.Allowed,
- }
-
- for _, p := range auth.PolicyResults.GrantingPolicies {
- respEntry.Auth.PolicyResults.GrantingPolicies = append(respEntry.Auth.PolicyResults.GrantingPolicies, PolicyInfo{
- Name: p.Name,
- NamespaceId: p.NamespaceId,
- NamespacePath: p.NamespacePath,
- Type: p.Type,
- })
- }
- }
-
- if !auth.IssueTime.IsZero() {
- respEntry.Auth.TokenIssueTime = auth.IssueTime.Format(time.RFC3339)
- }
- if req.WrapInfo != nil {
- respEntry.Request.WrapTTL = int(req.WrapInfo.TTL / time.Second)
- }
-
- if !f.config.omitTime {
- // Use the time provider to supply the time for this entry.
- respEntry.Time = provider.formattedTime()
- }
-
- return respEntry, nil
-}
-
-// getRemoteAddr safely gets the remote address avoiding a nil pointer
-func getRemoteAddr(req *logical.Request) string {
+// remoteAddr safely gets the remote address avoiding a nil pointer.
+func remoteAddr(req *logical.Request) string {
if req != nil && req.Connection != nil {
return req.Connection.RemoteAddr
}
return ""
}
-// getRemotePort safely gets the remote port avoiding a nil pointer
-func getRemotePort(req *logical.Request) int {
+// remotePort safely gets the remote port avoiding a nil pointer.
+func remotePort(req *logical.Request) int {
if req != nil && req.Connection != nil {
return req.Connection.RemotePort
}
return 0
}
-// getClientCertificateSerialNumber attempts the retrieve the serial number of
-// the peer certificate from the specified tls.ConnectionState.
-func getClientCertificateSerialNumber(connState *tls.ConnectionState) string {
+// clientCertSerialNumber attempts the retrieve the serial number of the peer
+// certificate from the specified tls.ConnectionState.
+func clientCertSerialNumber(req *logical.Request) string {
+ if req == nil || req.Connection == nil {
+ return ""
+ }
+
+ connState := req.Connection.ConnState
+
if connState == nil || len(connState.VerifiedChains) == 0 || len(connState.VerifiedChains[0]) == 0 {
return ""
}
@@ -606,25 +232,6 @@ func parseVaultTokenFromJWT(token string) *string {
return &claims.ID
}
-// doElideListResponseData performs the actual elision of list operation response data, once surrounding code has
-// determined it should apply to a particular request. The data map that is passed in must be a copy that is safe to
-// modify in place, but need not be a full recursive deep copy, as only top-level keys are changed.
-//
-// See the documentation of the controlling option in formatterConfig for more information on the purpose.
-func doElideListResponseData(data map[string]interface{}) {
- for k, v := range data {
- if k == "keys" {
- if vSlice, ok := v.([]string); ok {
- data[k] = len(vSlice)
- }
- } else if k == "key_info" {
- if vMap, ok := v.(map[string]interface{}); ok {
- data[k] = len(vMap)
- }
- }
- }
-}
-
// newTemporaryEntryFormatter creates a cloned entryFormatter instance with a non-persistent Salter.
func newTemporaryEntryFormatter(n *entryFormatter) *entryFormatter {
return &entryFormatter{
@@ -637,3 +244,373 @@ func newTemporaryEntryFormatter(n *entryFormatter) *entryFormatter {
func (s *nonPersistentSalt) Salt(_ context.Context) (*salt.Salt, error) {
return salt.NewNonpersistentSalt(), nil
}
+
+// clone can be used to deep clone the specified type.
+func clone[V any](s V) (V, error) {
+ s2, err := copystructure.Copy(s)
+
+ return s2.(V), err
+}
+
+// newAuth takes a logical.Auth and the number of remaining client token uses
+// (which should be supplied from the logical.Request's client token), and creates
+// an audit auth.
+// tokenRemainingUses should be the client token remaining uses to include in auth.
+// This usually can be found in logical.Request.ClientTokenRemainingUses.
+// NOTE: supplying a nil value for auth will result in a nil return value and
+// (nil) error. The caller should check the return value before attempting to use it.
+// ignore-nil-nil-function-check.
+func newAuth(input *logical.Auth, tokenRemainingUses int) (*auth, error) {
+ if input == nil {
+ return nil, nil
+ }
+
+ extNSPolicies, err := clone(input.ExternalNamespacePolicies)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical auth: external namespace policies: %w", err)
+ }
+
+ identityPolicies, err := clone(input.IdentityPolicies)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical auth: identity policies: %w", err)
+ }
+
+ metadata, err := clone(input.Metadata)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical auth: metadata: %w", err)
+ }
+
+ policies, err := clone(input.Policies)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical auth: policies: %w", err)
+ }
+
+ var polRes *policyResults
+ if input.PolicyResults != nil {
+ polRes = &policyResults{
+ Allowed: input.PolicyResults.Allowed,
+ GrantingPolicies: make([]policyInfo, len(input.PolicyResults.GrantingPolicies)),
+ }
+
+ for _, p := range input.PolicyResults.GrantingPolicies {
+ polRes.GrantingPolicies = append(polRes.GrantingPolicies, policyInfo{
+ Name: p.Name,
+ NamespaceId: p.NamespaceId,
+ NamespacePath: p.NamespacePath,
+ Type: p.Type,
+ })
+ }
+ }
+
+ tokenPolicies, err := clone(input.TokenPolicies)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical auth: token policies: %w", err)
+ }
+
+ var tokenIssueTime string
+ if !input.IssueTime.IsZero() {
+ tokenIssueTime = input.IssueTime.Format(time.RFC3339)
+ }
+
+ return &auth{
+ Accessor: input.Accessor,
+ ClientToken: input.ClientToken,
+ DisplayName: input.DisplayName,
+ EntityCreated: input.EntityCreated,
+ EntityID: input.EntityID,
+ ExternalNamespacePolicies: extNSPolicies,
+ IdentityPolicies: identityPolicies,
+ Metadata: metadata,
+ NoDefaultPolicy: input.NoDefaultPolicy,
+ NumUses: input.NumUses,
+ Policies: policies,
+ PolicyResults: polRes,
+ RemainingUses: tokenRemainingUses,
+ TokenPolicies: tokenPolicies,
+ TokenIssueTime: tokenIssueTime,
+ TokenTTL: int64(input.TTL.Seconds()),
+ TokenType: input.TokenType.String(),
+ }, nil
+}
+
+// newRequest takes a logical.Request and namespace.Namespace, transforms and
+// aggregates them into an audit request.
+func newRequest(req *logical.Request, ns *nshelper.Namespace) (*request, error) {
+ if req == nil {
+ return nil, fmt.Errorf("request cannot be nil")
+ }
+
+ remoteAddr := remoteAddr(req)
+ remotePort := remotePort(req)
+ clientCertSerial := clientCertSerialNumber(req)
+
+ data, err := clone(req.Data)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical request: data: %w", err)
+ }
+
+ headers, err := clone(req.Headers)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical request: headers: %w", err)
+ }
+
+ var reqURI string
+ if req.HTTPRequest != nil && req.HTTPRequest.RequestURI != req.Path {
+ reqURI = req.HTTPRequest.RequestURI
+ }
+ var wrapTTL int
+ if req.WrapInfo != nil {
+ wrapTTL = int(req.WrapInfo.TTL / time.Second)
+ }
+
+ return &request{
+ ClientCertificateSerialNumber: clientCertSerial,
+ ClientID: req.ClientID,
+ ClientToken: req.ClientToken,
+ ClientTokenAccessor: req.ClientTokenAccessor,
+ Data: data,
+ Headers: headers,
+ ID: req.ID,
+ MountAccessor: req.MountAccessor,
+ MountClass: req.MountClass(),
+ MountIsExternalPlugin: req.MountIsExternalPlugin(),
+ MountPoint: req.MountPoint,
+ MountRunningSha256: req.MountRunningSha256(),
+ MountRunningVersion: req.MountRunningVersion(),
+ MountType: req.MountType,
+ Namespace: &namespace{
+ ID: ns.ID,
+ Path: ns.Path,
+ },
+ Operation: req.Operation,
+ Path: req.Path,
+ PolicyOverride: req.PolicyOverride,
+ RemoteAddr: remoteAddr,
+ RemotePort: remotePort,
+ ReplicationCluster: req.ReplicationCluster,
+ RequestURI: reqURI,
+ WrapTTL: wrapTTL,
+ }, nil
+}
+
+// newResponse takes a logical.Response and logical.Request, transforms and
+// aggregates them into an audit response.
+// isElisionRequired is used to indicate that response 'Data' should be elided.
+// NOTE: supplying a nil value for response will result in a nil return value and
+// (nil) error. The caller should check the return value before attempting to use it.
+// ignore-nil-nil-function-check.
+func newResponse(resp *logical.Response, req *logical.Request, isElisionRequired bool) (*response, error) {
+ if resp == nil {
+ return nil, nil
+ }
+
+ if req == nil {
+ // Request should never be nil, even for a response.
+ return nil, fmt.Errorf("request cannot be nil")
+ }
+
+ auth, err := newAuth(resp.Auth, req.ClientTokenRemainingUses)
+ if err != nil {
+ return nil, fmt.Errorf("unable to convert logical auth response: %w", err)
+ }
+
+ var data map[string]any
+ if resp.Data != nil {
+ data = make(map[string]any, len(resp.Data))
+
+ if isElisionRequired {
+ // Performs the actual elision (ideally for list operations) of response data,
+ // once surrounding code has determined it should apply to a particular request.
+ // If the value for a key should not be elided, then it will be cloned.
+ for k, v := range resp.Data {
+ isCloneRequired := true
+ switch k {
+ case "keys":
+ if vSlice, ok := v.([]string); ok {
+ data[k] = len(vSlice)
+ isCloneRequired = false
+ }
+ case "key_info":
+ if vMap, ok := v.(map[string]any); ok {
+ data[k] = len(vMap)
+ isCloneRequired = false
+ }
+ }
+
+ // Clone values if they weren't legitimate keys or key_info.
+ if isCloneRequired {
+ v2, err := clone(v)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone response data while eliding: %w", err)
+ }
+ data[k] = v2
+ }
+ }
+ } else {
+ // Deep clone all values, no shortcuts here.
+ data, err = clone(resp.Data)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone response data: %w", err)
+ }
+ }
+ }
+
+ headers, err := clone(resp.Headers)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical response: headers: %w", err)
+ }
+
+ var s *secret
+ if resp.Secret != nil {
+ s = &secret{LeaseID: resp.Secret.LeaseID}
+ }
+
+ var wrapInfo *responseWrapInfo
+ if resp.WrapInfo != nil {
+ token := resp.WrapInfo.Token
+ if jwtToken := parseVaultTokenFromJWT(token); jwtToken != nil {
+ token = *jwtToken
+ }
+
+ ttl := int(resp.WrapInfo.TTL / time.Second)
+ wrapInfo = &responseWrapInfo{
+ TTL: ttl,
+ Token: token,
+ Accessor: resp.WrapInfo.Accessor,
+ CreationTime: resp.WrapInfo.CreationTime.UTC().Format(time.RFC3339Nano),
+ CreationPath: resp.WrapInfo.CreationPath,
+ WrappedAccessor: resp.WrapInfo.WrappedAccessor,
+ }
+ }
+
+ warnings, err := clone(resp.Warnings)
+ if err != nil {
+ return nil, fmt.Errorf("unable to clone logical response: warnings: %w", err)
+ }
+
+ return &response{
+ Auth: auth,
+ Data: data,
+ Headers: headers,
+ MountAccessor: req.MountAccessor,
+ MountClass: req.MountClass(),
+ MountIsExternalPlugin: req.MountIsExternalPlugin(),
+ MountPoint: req.MountPoint,
+ MountRunningSha256: req.MountRunningSha256(),
+ MountRunningVersion: req.MountRunningVersion(),
+ MountType: req.MountType,
+ Redirect: resp.Redirect,
+ Secret: s,
+ WrapInfo: wrapInfo,
+ Warnings: warnings,
+ }, nil
+}
+
+// createEntry takes the AuditEvent and builds an audit entry.
+// The entry will be HMAC'd and elided where required.
+func (f *entryFormatter) createEntry(ctx context.Context, a *Event) (*entry, error) {
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+
+ }
+
+ data := a.Data
+
+ if data.Request == nil {
+ // Request should never be nil, even for a response.
+ return nil, fmt.Errorf("unable to parse request from '%s' audit event: request cannot be nil", a.Subtype)
+ }
+
+ ns, err := nshelper.FromContext(ctx)
+ if err != nil {
+ return nil, fmt.Errorf("unable to retrieve namespace from context: %w", err)
+ }
+
+ auth, err := newAuth(data.Auth, data.Request.ClientTokenRemainingUses)
+ if err != nil {
+ return nil, fmt.Errorf("cannot convert auth: %w", err)
+ }
+
+ req, err := newRequest(data.Request, ns)
+ if err != nil {
+ return nil, fmt.Errorf("cannot convert request: %w", err)
+ }
+
+ var resp *response
+ if a.Subtype == ResponseType {
+ shouldElide := f.config.elideListResponses && req.Operation == logical.ListOperation
+ resp, err = newResponse(data.Response, data.Request, shouldElide)
+ if err != nil {
+ return nil, fmt.Errorf("cannot convert response: %w", err)
+ }
+ }
+
+ var outerErr string
+ if data.OuterErr != nil {
+ outerErr = data.OuterErr.Error()
+ }
+
+ entryType := data.Type
+ if entryType == "" {
+ entryType = a.Subtype.String()
+ }
+
+ entry := &entry{
+ Auth: auth,
+ Error: outerErr,
+ Forwarded: false,
+ ForwardedFrom: data.Request.ForwardedFrom,
+ Request: req,
+ Response: resp,
+ Type: entryType,
+ }
+
+ if !f.config.omitTime {
+ // Use the time provider to supply the time for this entry.
+ entry.Time = a.timeProvider().formattedTime()
+ }
+
+ // If the request is present in the input data, apply header configuration
+ // regardless. We shouldn't be in a situation where the header formatter isn't
+ // present as it's required.
+ if entry.Request != nil {
+ // Ensure that any headers in the request, are formatted as required, and are
+ // only present if they have been configured to appear in the audit log.
+ // e.g. via: /sys/config/auditing/request-headers/:name
+ entry.Request.Headers, err = f.config.headerFormatter.ApplyConfig(ctx, entry.Request.Headers, f.salter)
+ if err != nil {
+ return nil, fmt.Errorf("unable to transform headers for auditing: %w", err)
+ }
+ }
+
+ // If the request contains a Server-Side Consistency Token (SSCT), and we
+ // have an auth response, overwrite the existing client token with the SSCT,
+ // so that the SSCT appears in the audit log for this entry.
+ if data.Request != nil && data.Request.InboundSSCToken != "" && entry.Auth != nil {
+ entry.Auth.ClientToken = data.Request.InboundSSCToken
+ }
+
+ // Hash the entry if we aren't expecting raw output.
+ if !f.config.raw {
+ // Requests and responses have auth and request.
+ err = hashAuth(ctx, f.salter, entry.Auth, f.config.hmacAccessor)
+ if err != nil {
+ return nil, err
+ }
+
+ err = hashRequest(ctx, f.salter, entry.Request, f.config.hmacAccessor, data.NonHMACReqDataKeys)
+ if err != nil {
+ return nil, err
+ }
+
+ if a.Subtype == ResponseType {
+ if err = hashResponse(ctx, f.salter, entry.Response, f.config.hmacAccessor, data.NonHMACRespDataKeys); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ return entry, nil
+}
diff --git a/audit/entry_formatter_ce.go b/audit/entry_formatter_ce.go
new file mode 100644
index 0000000000..7c3f33212e
--- /dev/null
+++ b/audit/entry_formatter_ce.go
@@ -0,0 +1,18 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build !enterprise
+
+package audit
+
+import (
+ "errors"
+)
+
+func (f *entryFormatter) shouldExclude() bool {
+ return false
+}
+
+func (f *entryFormatter) excludeFields(entry any) (map[string]any, error) {
+ return nil, errors.New("enterprise-only feature: audit exclusion")
+}
diff --git a/audit/entry_formatter_ce_test.go b/audit/entry_formatter_ce_test.go
new file mode 100644
index 0000000000..ffe181f4b8
--- /dev/null
+++ b/audit/entry_formatter_ce_test.go
@@ -0,0 +1,37 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build !enterprise
+
+package audit
+
+import (
+ "testing"
+
+ "github.com/hashicorp/go-hclog"
+ "github.com/stretchr/testify/require"
+)
+
+// TestEntryFormatter_excludeFields tests that we can exclude data based on the
+// pre-configured conditions/fields of the EntryFormatter. It covers some scenarios
+// where we expect errors due to invalid input, which is unlikely to happen in reality.
+func TestEntryFormatter_excludeFields(t *testing.T) {
+ // Create the formatter node.
+ cfg, err := newFormatterConfig(&testHeaderFormatter{}, nil)
+ require.NoError(t, err)
+ ss := newStaticSalt(t)
+
+ // We intentionally create the EntryFormatter manually, as we wouldn't be
+ // able to set exclusions via NewEntryFormatter WithExclusions option.
+ formatter := &entryFormatter{
+ config: cfg,
+ salter: ss,
+ logger: hclog.NewNullLogger(),
+ name: "juan",
+ }
+
+ res, err := formatter.excludeFields(nil)
+ require.Error(t, err)
+ require.EqualError(t, err, "enterprise-only feature: audit exclusion")
+ require.Nil(t, res)
+}
diff --git a/audit/entry_formatter_config.go b/audit/entry_formatter_config.go
index 2caefb02e3..aa55a2ea2d 100644
--- a/audit/entry_formatter_config.go
+++ b/audit/entry_formatter_config.go
@@ -12,6 +12,8 @@ import (
// formatterConfig is used to provide basic configuration to a formatter.
// Use newFormatterConfig to initialize the formatterConfig struct.
type formatterConfig struct {
+ formatterConfigEnt
+
raw bool
hmacAccessor bool
@@ -40,7 +42,7 @@ type formatterConfig struct {
// This should only ever be used in a testing context
omitTime bool
- // The required/target format for the event (supported: JSONFormat and JSONxFormat).
+ // The required/target format for the event (supported: jsonFormat and jsonxFormat).
requiredFormat format
// headerFormatter specifies the formatter used for headers that existing in any incoming audit request.
@@ -56,14 +58,14 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
return formatterConfig{}, fmt.Errorf("header formatter is required: %w", ErrInvalidParameter)
}
- var opt []Option
+ var opt []option
if format, ok := config[optionFormat]; ok {
- if !IsValidFormat(format) {
+ if !isValidFormat(format) {
return formatterConfig{}, fmt.Errorf("unsupported %q: %w", optionFormat, ErrExternalOptions)
}
- opt = append(opt, WithFormat(format))
+ opt = append(opt, withFormat(format))
}
// Check if hashing of accessor is disabled
@@ -72,7 +74,7 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
if err != nil {
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionHMACAccessor, ErrExternalOptions)
}
- opt = append(opt, WithHMACAccessor(v))
+ opt = append(opt, withHMACAccessor(v))
}
// Check if raw logging is enabled
@@ -81,7 +83,7 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
if err != nil {
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionLogRaw, ErrExternalOptions)
}
- opt = append(opt, WithRaw(v))
+ opt = append(opt, withRaw(v))
}
if elideListResponsesRaw, ok := config[optionElideListResponses]; ok {
@@ -89,11 +91,11 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
if err != nil {
return formatterConfig{}, fmt.Errorf("unable to parse %q: %w", optionElideListResponses, ErrExternalOptions)
}
- opt = append(opt, WithElision(v))
+ opt = append(opt, withElision(v))
}
if prefix, ok := config[optionPrefix]; ok {
- opt = append(opt, WithPrefix(prefix))
+ opt = append(opt, withPrefix(prefix))
}
opts, err := getOpts(opt...)
@@ -101,7 +103,13 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin
return formatterConfig{}, err
}
+ fmtCfgEnt, err := newFormatterConfigEnt(config)
+ if err != nil {
+ return formatterConfig{}, err
+ }
+
return formatterConfig{
+ formatterConfigEnt: fmtCfgEnt,
headerFormatter: headerFormatter,
elideListResponses: opts.withElision,
hmacAccessor: opts.withHMACAccessor,
diff --git a/audit/entry_formatter_config_ce.go b/audit/entry_formatter_config_ce.go
new file mode 100644
index 0000000000..43b7307f4d
--- /dev/null
+++ b/audit/entry_formatter_config_ce.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build !enterprise
+
+package audit
+
+// formatterConfigEnt provides extensions to a formatterConfig which behave differently
+// for Enterprise and community edition.
+// NOTE: Use newFormatterConfigEnt to initialize the formatterConfigEnt struct.
+type formatterConfigEnt struct{}
+
+// newFormatterConfigEnt should be used to create formatterConfigEnt.
+func newFormatterConfigEnt(config map[string]string) (formatterConfigEnt, error) {
+ return formatterConfigEnt{}, nil
+}
diff --git a/audit/entry_formatter_test.go b/audit/entry_formatter_test.go
index 3fc0882552..35bf5cb058 100644
--- a/audit/entry_formatter_test.go
+++ b/audit/entry_formatter_test.go
@@ -15,7 +15,8 @@ import (
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-sockaddr"
- "github.com/hashicorp/vault/helper/namespace"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
+ "github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/internal/observability/event"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/helper/salt"
@@ -131,14 +132,14 @@ func TestNewEntryFormatter(t *testing.T) {
Options: map[string]string{
"format": "json",
},
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"default": {
Name: "juan",
UseStaticSalt: true,
Logger: hclog.NewNullLogger(),
IsErrorExpected: false,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"config-json": {
Name: "juan",
@@ -148,7 +149,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "json",
},
IsErrorExpected: false,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"config-jsonx": {
Name: "juan",
@@ -158,7 +159,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "jsonx",
},
IsErrorExpected: false,
- ExpectedFormat: JSONxFormat,
+ ExpectedFormat: jsonxFormat,
},
"config-json-prefix": {
Name: "juan",
@@ -169,7 +170,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "json",
},
IsErrorExpected: false,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
ExpectedPrefix: "foo",
},
"config-jsonx-prefix": {
@@ -181,7 +182,7 @@ func TestNewEntryFormatter(t *testing.T) {
"format": "jsonx",
},
IsErrorExpected: false,
- ExpectedFormat: JSONxFormat,
+ ExpectedFormat: jsonxFormat,
ExpectedPrefix: "foo",
},
}
@@ -244,7 +245,7 @@ func TestEntryFormatter_Type(t *testing.T) {
}
// TestEntryFormatter_Process attempts to run the Process method to convert the
-// logical.LogInput within an audit event to JSON and JSONx (RequestEntry or ResponseEntry).
+// logical.LogInput within an audit event to JSON and JSONx (entry),
func TestEntryFormatter_Process(t *testing.T) {
t.Parallel()
@@ -258,115 +259,134 @@ func TestEntryFormatter_Process(t *testing.T) {
}{
"json-request-no-data": {
IsErrorExpected: true,
- ExpectedErrorMessage: "cannot audit event (request) with no data: invalid internal parameter",
+ ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter",
Subtype: RequestType,
- RequiredFormat: JSONFormat,
+ RequiredFormat: jsonFormat,
Data: nil,
},
"json-response-no-data": {
IsErrorExpected: true,
- ExpectedErrorMessage: "cannot audit event (response) with no data: invalid internal parameter",
+ ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter",
Subtype: ResponseType,
- RequiredFormat: JSONFormat,
+ RequiredFormat: jsonFormat,
Data: nil,
},
"json-request-basic-input": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse request from audit event: request to request-audit a nil request",
+ ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil",
Subtype: RequestType,
- RequiredFormat: JSONFormat,
+ RequiredFormat: jsonFormat,
Data: &logical.LogInput{Type: "magic"},
+ RootNamespace: true,
},
"json-response-basic-input": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse response from audit event: request to response-audit a nil request",
+ ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
Subtype: ResponseType,
- RequiredFormat: JSONFormat,
+ RequiredFormat: jsonFormat,
Data: &logical.LogInput{Type: "magic"},
},
"json-request-basic-input-and-request-no-ns": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse request from audit event: no namespace",
+ ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: RequestType,
- RequiredFormat: JSONFormat,
+ RequiredFormat: jsonFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
},
"json-response-basic-input-and-request-no-ns": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse response from audit event: no namespace",
+ ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: ResponseType,
- RequiredFormat: JSONFormat,
+ RequiredFormat: jsonFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
},
"json-request-basic-input-and-request-with-ns": {
IsErrorExpected: false,
Subtype: RequestType,
- RequiredFormat: JSONFormat,
+ RequiredFormat: jsonFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
RootNamespace: true,
},
"json-response-basic-input-and-request-with-ns": {
IsErrorExpected: false,
Subtype: ResponseType,
- RequiredFormat: JSONFormat,
- Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
- RootNamespace: true,
+ RequiredFormat: jsonFormat,
+ Data: &logical.LogInput{
+ Request: &logical.Request{ID: "123"},
+ Response: &logical.Response{},
+ },
+ RootNamespace: true,
},
"jsonx-request-no-data": {
IsErrorExpected: true,
- ExpectedErrorMessage: "cannot audit event (request) with no data: invalid internal parameter",
+ ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter",
Subtype: RequestType,
- RequiredFormat: JSONxFormat,
+ RequiredFormat: jsonxFormat,
Data: nil,
},
"jsonx-response-no-data": {
IsErrorExpected: true,
- ExpectedErrorMessage: "cannot audit event (response) with no data: invalid internal parameter",
+ ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter",
Subtype: ResponseType,
- RequiredFormat: JSONxFormat,
+ RequiredFormat: jsonxFormat,
Data: nil,
},
"jsonx-request-basic-input": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse request from audit event: request to request-audit a nil request",
+ ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil",
Subtype: RequestType,
- RequiredFormat: JSONxFormat,
+ RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Type: "magic"},
+ RootNamespace: true,
},
"jsonx-response-basic-input": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse response from audit event: request to response-audit a nil request",
+ ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
Subtype: ResponseType,
- RequiredFormat: JSONxFormat,
+ RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Type: "magic"},
+ RootNamespace: true,
},
"jsonx-request-basic-input-and-request-no-ns": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse request from audit event: no namespace",
+ ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: RequestType,
- RequiredFormat: JSONxFormat,
+ RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
},
"jsonx-response-basic-input-and-request-no-ns": {
IsErrorExpected: true,
- ExpectedErrorMessage: "unable to parse response from audit event: no namespace",
+ ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
Subtype: ResponseType,
- RequiredFormat: JSONxFormat,
+ RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
},
"jsonx-request-basic-input-and-request-with-ns": {
IsErrorExpected: false,
Subtype: RequestType,
- RequiredFormat: JSONxFormat,
+ RequiredFormat: jsonxFormat,
Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
RootNamespace: true,
},
"jsonx-response-basic-input-and-request-with-ns": {
IsErrorExpected: false,
Subtype: ResponseType,
- RequiredFormat: JSONxFormat,
- Data: &logical.LogInput{Request: &logical.Request{ID: "123"}},
- RootNamespace: true,
+ RequiredFormat: jsonxFormat,
+ Data: &logical.LogInput{
+ Request: &logical.Request{ID: "123"},
+ Response: &logical.Response{},
+ },
+ RootNamespace: true,
+ },
+ "no-request": {
+ IsErrorExpected: true,
+ ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
+ Subtype: ResponseType,
+ RequiredFormat: jsonxFormat,
+ Data: &logical.LogInput{
+ Auth: &logical.Auth{},
+ },
+ RootNamespace: true,
},
}
@@ -382,14 +402,14 @@ func TestEntryFormatter_Process(t *testing.T) {
cfg, err := newFormatterConfig(&testHeaderFormatter{}, map[string]string{"format": tc.RequiredFormat.String()})
require.NoError(t, err)
- f, err := newEntryFormatter("juan", cfg, ss, hclog.NewNullLogger())
+ f, err := newEntryFormatter("juan", cfg, ss, corehelpers.NewTestLogger(t))
require.NoError(t, err)
require.NotNil(t, f)
var ctx context.Context
switch {
case tc.RootNamespace:
- ctx = namespace.RootContext(context.Background())
+ ctx = nshelper.RootContext(context.Background())
default:
ctx = context.Background()
}
@@ -441,7 +461,7 @@ func BenchmarkAuditFileSink_Process(b *testing.B) {
},
}
- ctx := namespace.RootContext(context.Background())
+ ctx := nshelper.RootContext(context.Background())
// Create the formatter node.
cfg, err := newFormatterConfig(&testHeaderFormatter{}, nil)
@@ -452,7 +472,7 @@ func BenchmarkAuditFileSink_Process(b *testing.B) {
require.NotNil(b, formatter)
// Create the sink node.
- sink, err := event.NewFileSink("/dev/null", JSONFormat.String())
+ sink, err := event.NewFileSink("/dev/null", jsonFormat.String())
require.NoError(b, err)
require.NotNil(b, sink)
@@ -475,9 +495,9 @@ func BenchmarkAuditFileSink_Process(b *testing.B) {
})
}
-// TestEntryFormatter_FormatRequest exercises entryFormatter.formatRequest with
-// varying inputs.
-func TestEntryFormatter_FormatRequest(t *testing.T) {
+// TestEntryFormatter_Process_Request exercises entryFormatter process an event
+// with varying inputs.
+func TestEntryFormatter_Process_Request(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -490,17 +510,17 @@ func TestEntryFormatter_FormatRequest(t *testing.T) {
"nil": {
Input: nil,
IsErrorExpected: true,
- ExpectedErrorMessage: "request to request-audit a nil request",
+ ExpectedErrorMessage: "cannot audit a 'request' event with no data: invalid internal parameter",
},
"basic-input": {
Input: &logical.LogInput{},
IsErrorExpected: true,
- ExpectedErrorMessage: "request to request-audit a nil request",
+ ExpectedErrorMessage: "unable to parse request from 'request' audit event: request cannot be nil",
},
"input-and-request-no-ns": {
Input: &logical.LogInput{Request: &logical.Request{ID: "123"}},
IsErrorExpected: true,
- ExpectedErrorMessage: "no namespace",
+ ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
RootNamespace: false,
},
"input-and-request-with-ns": {
@@ -531,25 +551,46 @@ func TestEntryFormatter_FormatRequest(t *testing.T) {
var ctx context.Context
switch {
case tc.RootNamespace:
- ctx = namespace.RootContext(context.Background())
+ ctx = nshelper.RootContext(context.Background())
default:
ctx = context.Background()
}
- entry, err := f.formatRequest(ctx, tc.Input, &testTimeProvider{})
+ auditEvent, err := newEvent(RequestType)
+ auditEvent.setTimeProvider(&testTimeProvider{})
+ require.NoError(t, err)
+ auditEvent.Data = tc.Input
+ e := &eventlogger.Event{
+ Type: event.AuditType.AsEventType(),
+ CreatedAt: time.Now(),
+ Formatted: make(map[string][]byte),
+ Payload: auditEvent,
+ }
+
+ e2, err := f.Process(ctx, e)
switch {
case tc.IsErrorExpected:
require.Error(t, err)
require.EqualError(t, err, tc.ExpectedErrorMessage)
- require.Nil(t, entry)
+ require.Nil(t, e2)
case tc.ShouldOmitTime:
require.NoError(t, err)
- require.NotNil(t, entry)
+ require.NotNil(t, e2)
+ b, ok := e2.Format(jsonFormat.String())
+ require.True(t, ok)
+ var entry *entry
+ err = json.Unmarshal(b, &entry)
+ require.NoError(t, err)
require.Zero(t, entry.Time)
default:
require.NoError(t, err)
- require.NotNil(t, entry)
+ require.NotNil(t, e2)
+ b, ok := e2.Format(jsonFormat.String())
+ require.True(t, ok)
+ var entry *entry
+ err = json.Unmarshal(b, &entry)
+ require.NoError(t, err)
require.NotZero(t, entry.Time)
require.Equal(t, "2024-03-22T10:00:05.00000001Z", entry.Time)
}
@@ -557,9 +598,9 @@ func TestEntryFormatter_FormatRequest(t *testing.T) {
}
}
-// TestEntryFormatter_FormatResponse exercises entryFormatter.formatResponse with
-// varying inputs.
-func TestEntryFormatter_FormatResponse(t *testing.T) {
+// TestEntryFormatter_Process_ResponseType exercises entryFormatter
+// with varying inputs also checking if the time can be omitted.
+func TestEntryFormatter_Process_ResponseType(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -572,26 +613,32 @@ func TestEntryFormatter_FormatResponse(t *testing.T) {
"nil": {
Input: nil,
IsErrorExpected: true,
- ExpectedErrorMessage: "request to response-audit a nil request",
+ ExpectedErrorMessage: "cannot audit a 'response' event with no data: invalid internal parameter",
},
"basic-input": {
Input: &logical.LogInput{},
IsErrorExpected: true,
- ExpectedErrorMessage: "request to response-audit a nil request",
+ ExpectedErrorMessage: "unable to parse request from 'response' audit event: request cannot be nil",
},
"input-and-request-no-ns": {
Input: &logical.LogInput{Request: &logical.Request{ID: "123"}},
IsErrorExpected: true,
- ExpectedErrorMessage: "no namespace",
+ ExpectedErrorMessage: "unable to retrieve namespace from context: no namespace",
RootNamespace: false,
},
"input-and-request-with-ns": {
- Input: &logical.LogInput{Request: &logical.Request{ID: "123"}},
+ Input: &logical.LogInput{
+ Request: &logical.Request{ID: "123"},
+ Response: &logical.Response{},
+ },
IsErrorExpected: false,
RootNamespace: true,
},
"omit-time": {
- Input: &logical.LogInput{Request: &logical.Request{ID: "123"}},
+ Input: &logical.LogInput{
+ Request: &logical.Request{ID: "123"},
+ Response: &logical.Response{},
+ },
ShouldOmitTime: true,
IsErrorExpected: false,
RootNamespace: true,
@@ -614,25 +661,47 @@ func TestEntryFormatter_FormatResponse(t *testing.T) {
var ctx context.Context
switch {
case tc.RootNamespace:
- ctx = namespace.RootContext(context.Background())
+ ctx = nshelper.RootContext(context.Background())
default:
ctx = context.Background()
}
- entry, err := f.formatResponse(ctx, tc.Input, &testTimeProvider{})
+ auditEvent, err := newEvent(ResponseType)
+ auditEvent.setTimeProvider(&testTimeProvider{})
+ require.NoError(t, err)
+ auditEvent.Data = tc.Input
+
+ e := &eventlogger.Event{
+ Type: event.AuditType.AsEventType(),
+ CreatedAt: time.Now(),
+ Formatted: make(map[string][]byte),
+ Payload: auditEvent,
+ }
+
+ e2, err := f.Process(ctx, e)
switch {
case tc.IsErrorExpected:
require.Error(t, err)
require.EqualError(t, err, tc.ExpectedErrorMessage)
- require.Nil(t, entry)
+ require.Nil(t, e2)
case tc.ShouldOmitTime:
require.NoError(t, err)
- require.NotNil(t, entry)
+ require.NotNil(t, e2)
+ b, ok := e2.Format(jsonFormat.String())
+ require.True(t, ok)
+ var entry *entry
+ err = json.Unmarshal(b, &entry)
+ require.NoError(t, err)
require.Zero(t, entry.Time)
default:
require.NoError(t, err)
- require.NotNil(t, entry)
+ require.NotNil(t, e2)
+ b, ok := e2.Format(jsonFormat.String())
+ require.True(t, ok)
+ var entry *entry
+ err = json.Unmarshal(b, &entry)
+ require.NoError(t, err)
require.NotZero(t, entry.Time)
require.Equal(t, "2024-03-22T10:00:05.00000001Z", entry.Time)
}
@@ -738,7 +807,7 @@ func TestEntryFormatter_Process_JSON(t *testing.T) {
// Create an audit event and more generic eventlogger.event to allow us
// to process (format).
- auditEvent, err := NewEvent(RequestType)
+ auditEvent, err := newEvent(RequestType)
require.NoError(t, err)
auditEvent.Data = in
@@ -749,10 +818,10 @@ func TestEntryFormatter_Process_JSON(t *testing.T) {
Payload: auditEvent,
}
- e2, err := formatter.Process(namespace.RootContext(nil), e)
+ e2, err := formatter.Process(nshelper.RootContext(nil), e)
require.NoErrorf(t, err, "bad: %s\nerr: %s", name, err)
- jsonBytes, ok := e2.Format(JSONFormat.String())
+ jsonBytes, ok := e2.Format(jsonFormat.String())
require.True(t, ok)
require.Positive(t, len(jsonBytes))
@@ -760,14 +829,14 @@ func TestEntryFormatter_Process_JSON(t *testing.T) {
t.Fatalf("no prefix: %s \n log: %s\nprefix: %s", name, expectedResultStr, tc.Prefix)
}
- expectedJSON := new(RequestEntry)
+ expectedJSON := new(entry)
if err := jsonutil.DecodeJSON([]byte(expectedResultStr), &expectedJSON); err != nil {
t.Fatalf("bad json: %s", err)
}
- expectedJSON.Request.Namespace = &Namespace{ID: "root"}
+ expectedJSON.Request.Namespace = &namespace{ID: "root"}
- actualJSON := new(RequestEntry)
+ actualJSON := new(entry)
if err := jsonutil.DecodeJSON(jsonBytes[len(tc.Prefix):], &actualJSON); err != nil {
t.Fatalf("bad json: %s", err)
}
@@ -903,7 +972,7 @@ func TestEntryFormatter_Process_JSONx(t *testing.T) {
// Create an audit event and more generic eventlogger.event to allow us
// to process (format).
- auditEvent, err := NewEvent(RequestType)
+ auditEvent, err := newEvent(RequestType)
require.NoError(t, err)
auditEvent.Data = in
@@ -914,10 +983,10 @@ func TestEntryFormatter_Process_JSONx(t *testing.T) {
Payload: auditEvent,
}
- e2, err := formatter.Process(namespace.RootContext(nil), e)
+ e2, err := formatter.Process(nshelper.RootContext(nil), e)
require.NoErrorf(t, err, "bad: %s\nerr: %s", name, err)
- jsonxBytes, ok := e2.Format(JSONxFormat.String())
+ jsonxBytes, ok := e2.Format(jsonxFormat.String())
require.True(t, ok)
require.Positive(t, len(jsonxBytes))
@@ -933,9 +1002,9 @@ func TestEntryFormatter_Process_JSONx(t *testing.T) {
}
}
-// TestEntryFormatter_FormatResponse_ElideListResponses ensures that we correctly
-// elide data in responses to LIST operations.
-func TestEntryFormatter_FormatResponse_ElideListResponses(t *testing.T) {
+// TestEntryFormatter_ElideListResponses ensures that we correctly elide data in
+// responses to LIST operations.
+func TestEntryFormatter_ElideListResponses(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -1002,11 +1071,11 @@ func TestEntryFormatter_FormatResponse_ElideListResponses(t *testing.T) {
oneInterestingTestCase := tests["Enhanced list (has key_info)"]
ss := newStaticSalt(t)
- ctx := namespace.RootContext(context.Background())
+ ctx := nshelper.RootContext(context.Background())
var formatter *entryFormatter
var err error
- format := func(t *testing.T, config formatterConfig, operation logical.Operation, inputData map[string]any) *ResponseEntry {
+ format := func(t *testing.T, config formatterConfig, operation logical.Operation, inputData map[string]any) *entry {
formatter, err = newEntryFormatter("juan", config, ss, hclog.NewNullLogger())
require.NoError(t, err)
require.NotNil(t, formatter)
@@ -1016,10 +1085,15 @@ func TestEntryFormatter_FormatResponse_ElideListResponses(t *testing.T) {
Response: &logical.Response{Data: inputData},
}
- resp, err := formatter.formatResponse(ctx, in, &testTimeProvider{})
+ auditEvent, err := newEvent(ResponseType)
require.NoError(t, err)
+ auditEvent.Data = in
- return resp
+ entry, err := formatter.createEntry(ctx, auditEvent)
+ require.NoError(t, err)
+ require.NotNil(t, entry)
+
+ return entry
}
t.Run("Default case", func(t *testing.T) {
@@ -1040,7 +1114,8 @@ func TestEntryFormatter_FormatResponse_ElideListResponses(t *testing.T) {
require.NoError(t, err)
tc := oneInterestingTestCase
entry := format(t, config, logical.ReadOperation, tc.inputData)
- assert.Equal(t, formatter.hashExpectedValueForComparison(tc.inputData), entry.Response.Data)
+ hashedExpected := formatter.hashExpectedValueForComparison(tc.inputData)
+ assert.Equal(t, hashedExpected, entry.Response.Data)
})
t.Run("When elideListResponses is false, eliding does not happen", func(t *testing.T) {
@@ -1107,23 +1182,12 @@ func TestEntryFormatter_Process_NoMutation(t *testing.T) {
e := fakeEvent(t, RequestType, in)
- e2, err := formatter.Process(namespace.RootContext(nil), e)
+ e2, err := formatter.Process(nshelper.RootContext(nil), e)
require.NoError(t, err)
require.NotNil(t, e2)
// Ensure the pointers are different.
require.NotEqual(t, e2, e)
-
- // Do the same for the audit event in the payload.
- a, ok := e.Payload.(*AuditEvent)
- require.True(t, ok)
- require.NotNil(t, a)
-
- a2, ok := e2.Payload.(*AuditEvent)
- require.True(t, ok)
- require.NotNil(t, a2)
-
- require.NotEqual(t, a2, a)
}
// TestEntryFormatter_Process_Panic tries to send data into the entryFormatter
@@ -1170,6 +1234,7 @@ func TestEntryFormatter_Process_Panic(t *testing.T) {
Data: map[string]interface{}{},
},
Response: &logical.Response{
+ Auth: &logical.Auth{},
Data: map[string]any{
"token_bound_cidrs": []*sockaddr.SockAddrMarshaler{
{SockAddr: badAddr},
@@ -1180,7 +1245,7 @@ func TestEntryFormatter_Process_Panic(t *testing.T) {
e := fakeEvent(t, ResponseType, in)
- e2, err := formatter.Process(namespace.RootContext(nil), e)
+ e2, err := formatter.Process(nshelper.RootContext(nil), e)
require.Error(t, err)
require.Contains(t, err.Error(), "panic generating audit log: \"juan\"")
require.Nil(t, e2)
@@ -1217,13 +1282,13 @@ func TestEntryFormatter_Process_NeverLeaksHeaders(t *testing.T) {
e := fakeEvent(t, RequestType, input)
// Process the node.
- ctx := namespace.RootContext(context.Background())
+ ctx := nshelper.RootContext(context.Background())
e2, err := formatter.Process(ctx, e)
require.NoError(t, err)
require.NotNil(t, e2)
// Now check we can retrieve the formatted JSON.
- jsonFormatted, b2 := e2.Format(JSONFormat.String())
+ jsonFormatted, b2 := e2.Format(jsonFormat.String())
require.True(t, b2)
require.NotNil(t, jsonFormatted)
var input2 *logical.LogInput
@@ -1263,9 +1328,9 @@ func fakeEvent(tb testing.TB, subtype subtype, input *logical.LogInput) *eventlo
date := time.Date(2023, time.July, 11, 15, 49, 10, 0o0, time.Local)
- auditEvent, err := NewEvent(subtype,
- WithID("123"),
- WithNow(date),
+ auditEvent, err := newEvent(subtype,
+ withID("123"),
+ withNow(date),
)
require.NoError(tb, err)
require.NotNil(tb, auditEvent)
@@ -1275,6 +1340,7 @@ func fakeEvent(tb testing.TB, subtype subtype, input *logical.LogInput) *eventlo
require.Equal(tb, date, auditEvent.Timestamp)
auditEvent.Data = input
+ auditEvent.setTimeProvider(&testTimeProvider{})
e := &eventlogger.Event{
Type: eventlogger.EventType(event.AuditType),
diff --git a/audit/errors.go b/audit/errors.go
index be4e879fd2..31ac9fb4fb 100644
--- a/audit/errors.go
+++ b/audit/errors.go
@@ -20,9 +20,9 @@ var (
ErrExternalOptions = errors.New("invalid configuration")
)
-// ConvertToExternalError handles converting an error that was generated in Vault
-// and should appear as-is in the server logs, to an error that can be returned to
-// calling clients (via the API/CLI).
+// ConvertToExternalError handles converting an audit related error that was generated
+// in Vault and should appear as-is in the server logs, to an error that can be
+// returned to calling clients (via the API/CLI).
func ConvertToExternalError(err error) error {
// If the error is an internal error, the contents will have been logged, and
// we should probably shield the caller from the details.
diff --git a/audit/event.go b/audit/event.go
index f3d0d3cbcd..11f02e6b9e 100644
--- a/audit/event.go
+++ b/audit/event.go
@@ -23,20 +23,37 @@ const (
// Audit formats.
const (
- JSONFormat format = "json"
- JSONxFormat format = "jsonx"
+ jsonFormat format = "json"
+ jsonxFormat format = "jsonx"
)
// Check AuditEvent implements the timeProvider at compile time.
-var _ timeProvider = (*AuditEvent)(nil)
+var _ timeProvider = (*Event)(nil)
-// AuditEvent is the audit event.
-type AuditEvent struct {
+// Event is the audit event.
+type Event struct {
ID string `json:"id"`
Version string `json:"version"`
Subtype subtype `json:"subtype"` // the subtype of the audit event.
Timestamp time.Time `json:"timestamp"`
Data *logical.LogInput `json:"data"`
+ prov timeProvider
+}
+
+// setTimeProvider can be used to set a specific time provider which is used when
+// creating an entry.
+// NOTE: This is primarily used for testing to supply a known time value.
+func (a *Event) setTimeProvider(t timeProvider) {
+ a.prov = t
+}
+
+// timeProvider returns a configured time provider, or the default if not set.
+func (a *Event) timeProvider() timeProvider {
+ if a.prov == nil {
+ return a
+ }
+
+ return a.prov
}
// format defines types of format audit events support.
@@ -45,10 +62,10 @@ type format string
// subtype defines the type of audit event.
type subtype string
-// NewEvent should be used to create an audit event. The subtype field is needed
+// newEvent should be used to create an audit event. The subtype field is needed
// for audit events. It will generate an ID if no ID is supplied. Supported
-// options: WithID, WithNow.
-func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) {
+// options: withID, withNow.
+func newEvent(s subtype, opt ...option) (*Event, error) {
// Get the default options
opts, err := getOpts(opt...)
if err != nil {
@@ -64,7 +81,7 @@ func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) {
}
}
- audit := &AuditEvent{
+ audit := &Event{
ID: opts.withID,
Timestamp: opts.withNow,
Version: version,
@@ -78,7 +95,7 @@ func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) {
}
// validate attempts to ensure the audit event in its present state is valid.
-func (a *AuditEvent) validate() error {
+func (a *Event) validate() error {
if a == nil {
return fmt.Errorf("event is nil: %w", ErrInvalidParameter)
}
@@ -116,7 +133,7 @@ func (t subtype) validate() error {
// validate ensures that format is one of the set of allowed event formats.
func (f format) validate() error {
switch f {
- case JSONFormat, JSONxFormat:
+ case jsonFormat, jsonxFormat:
return nil
default:
return fmt.Errorf("invalid format %q: %w", f, ErrInvalidParameter)
@@ -155,13 +172,13 @@ func (t subtype) String() string {
// formattedTime returns the UTC time the AuditEvent was created in the RFC3339Nano
// format (which removes trailing zeros from the seconds field).
-func (a *AuditEvent) formattedTime() string {
+func (a *Event) formattedTime() string {
return a.Timestamp.UTC().Format(time.RFC3339Nano)
}
-// IsValidFormat provides a means to validate whether the supplied format is valid.
+// isValidFormat provides a means to validate whether the supplied format is valid.
// Examples of valid formats are JSON and JSONx.
-func IsValidFormat(v string) bool {
+func isValidFormat(v string) bool {
err := format(strings.TrimSpace(strings.ToLower(v))).validate()
return err == nil
}
diff --git a/audit/event_test.go b/audit/event_test.go
index 9dc8d6b6a7..a9f17677fd 100644
--- a/audit/event_test.go
+++ b/audit/event_test.go
@@ -15,7 +15,7 @@ func TestAuditEvent_new(t *testing.T) {
t.Parallel()
tests := map[string]struct {
- Options []Option
+ Options []option
Subtype subtype
Format format
IsErrorExpected bool
@@ -33,47 +33,47 @@ func TestAuditEvent_new(t *testing.T) {
IsErrorExpected: true,
ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter",
},
- "empty-Option": {
- Options: []Option{},
+ "empty-option": {
+ Options: []option{},
Subtype: subtype(""),
Format: format(""),
IsErrorExpected: true,
ExpectedErrorMessage: "invalid event subtype \"\": invalid internal parameter",
},
"bad-id": {
- Options: []Option{WithID("")},
+ Options: []option{withID("")},
Subtype: ResponseType,
- Format: JSONFormat,
+ Format: jsonFormat,
IsErrorExpected: true,
ExpectedErrorMessage: "id cannot be empty",
},
"good": {
- Options: []Option{
- WithID("audit_123"),
- WithFormat(string(JSONFormat)),
- WithSubtype(string(ResponseType)),
- WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
+ Options: []option{
+ withID("audit_123"),
+ withFormat(string(jsonFormat)),
+ withSubtype(string(ResponseType)),
+ withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
},
Subtype: RequestType,
- Format: JSONxFormat,
+ Format: jsonxFormat,
IsErrorExpected: false,
ExpectedID: "audit_123",
ExpectedTimestamp: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
ExpectedSubtype: RequestType,
- ExpectedFormat: JSONxFormat,
+ ExpectedFormat: jsonxFormat,
},
"good-no-time": {
- Options: []Option{
- WithID("audit_123"),
- WithFormat(string(JSONFormat)),
- WithSubtype(string(ResponseType)),
+ Options: []option{
+ withID("audit_123"),
+ withFormat(string(jsonFormat)),
+ withSubtype(string(ResponseType)),
},
Subtype: RequestType,
- Format: JSONxFormat,
+ Format: jsonxFormat,
IsErrorExpected: false,
ExpectedID: "audit_123",
ExpectedSubtype: RequestType,
- ExpectedFormat: JSONxFormat,
+ ExpectedFormat: jsonxFormat,
IsNowExpected: true,
},
}
@@ -84,7 +84,7 @@ func TestAuditEvent_new(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
- audit, err := NewEvent(tc.Subtype, tc.Options...)
+ audit, err := newEvent(tc.Subtype, tc.Options...)
switch {
case tc.IsErrorExpected:
require.Error(t, err)
@@ -112,7 +112,7 @@ func TestAuditEvent_Validate(t *testing.T) {
t.Parallel()
tests := map[string]struct {
- Value *AuditEvent
+ Value *Event
IsErrorExpected bool
ExpectedErrorMessage string
}{
@@ -122,12 +122,12 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "event is nil: invalid internal parameter",
},
"default": {
- Value: &AuditEvent{},
+ Value: &Event{},
IsErrorExpected: true,
ExpectedErrorMessage: "missing ID: invalid internal parameter",
},
"id-empty": {
- Value: &AuditEvent{
+ Value: &Event{
ID: "",
Version: version,
Subtype: RequestType,
@@ -138,7 +138,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "missing ID: invalid internal parameter",
},
"version-fiddled": {
- Value: &AuditEvent{
+ Value: &Event{
ID: "audit_123",
Version: "magic-v2",
Subtype: RequestType,
@@ -149,7 +149,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "event version unsupported: invalid internal parameter",
},
"subtype-fiddled": {
- Value: &AuditEvent{
+ Value: &Event{
ID: "audit_123",
Version: version,
Subtype: subtype("moon"),
@@ -160,7 +160,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "invalid event subtype \"moon\": invalid internal parameter",
},
"default-time": {
- Value: &AuditEvent{
+ Value: &Event{
ID: "audit_123",
Version: version,
Subtype: ResponseType,
@@ -171,7 +171,7 @@ func TestAuditEvent_Validate(t *testing.T) {
ExpectedErrorMessage: "event timestamp cannot be the zero time instant: invalid internal parameter",
},
"valid": {
- Value: &AuditEvent{
+ Value: &Event{
ID: "audit_123",
Version: version,
Subtype: ResponseType,
@@ -373,7 +373,7 @@ func TestAuditEvent_Subtype_String(t *testing.T) {
// method returns the correct format.
func TestAuditEvent_formattedTime(t *testing.T) {
theTime := time.Date(2024, time.March, 22, 10, 0o0, 5, 10, time.UTC)
- a, err := NewEvent(ResponseType, WithNow(theTime))
+ a, err := newEvent(ResponseType, withNow(theTime))
require.NoError(t, err)
require.NotNil(t, a)
require.Equal(t, "2024-03-22T10:00:05.00000001Z", a.formattedTime())
@@ -439,7 +439,7 @@ func TestEvent_IsValidFormat(t *testing.T) {
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
- res := IsValidFormat(tc.input)
+ res := isValidFormat(tc.input)
require.Equal(t, tc.expected, res)
})
}
diff --git a/audit/hashstructure.go b/audit/hashstructure.go
index d49c02865c..ab4988ceec 100644
--- a/audit/hashstructure.go
+++ b/audit/hashstructure.go
@@ -11,14 +11,12 @@ import (
"time"
"github.com/hashicorp/go-secure-stdlib/strutil"
- "github.com/hashicorp/vault/sdk/helper/wrapping"
"github.com/hashicorp/vault/sdk/logical"
- "github.com/mitchellh/copystructure"
"github.com/mitchellh/reflectwalk"
)
-// HashString hashes the given opaque string and returns it
-func HashString(ctx context.Context, salter Salter, data string) (string, error) {
+// hashString uses the Salter to hash the supplied opaque string and returns it.
+func hashString(ctx context.Context, salter Salter, data string) (string, error) {
salt, err := salter.Salt(ctx)
if err != nil {
return "", err
@@ -27,79 +25,68 @@ func HashString(ctx context.Context, salter Salter, data string) (string, error)
return salt.GetIdentifiedHMAC(data), nil
}
-// HashAuth returns a hashed copy of the logical.Auth input.
-func HashAuth(ctx context.Context, salter Salter, in *logical.Auth, HMACAccessor bool) (*logical.Auth, error) {
- if in == nil {
- return nil, nil
+// hashAuth uses the Salter to hash the supplied auth (modifying it).
+// hmacAccessor is used to indicate whether the accessor should also be HMAC'd
+// when present.
+func hashAuth(ctx context.Context, salter Salter, auth *auth, hmacAccessor bool) error {
+ if auth == nil {
+ return nil
}
salt, err := salter.Salt(ctx)
if err != nil {
- return nil, err
+ return err
}
fn := salt.GetIdentifiedHMAC
- auth := *in
if auth.ClientToken != "" {
auth.ClientToken = fn(auth.ClientToken)
}
- if HMACAccessor && auth.Accessor != "" {
+ if hmacAccessor && auth.Accessor != "" {
auth.Accessor = fn(auth.Accessor)
}
- return &auth, nil
+
+ return nil
}
-// HashRequest returns a hashed copy of the logical.Request input.
-func HashRequest(ctx context.Context, salter Salter, in *logical.Request, HMACAccessor bool, nonHMACDataKeys []string) (*logical.Request, error) {
- if in == nil {
- return nil, nil
+// hashRequest uses the Salter to hash the supplied request (modifying it).
+// nonHMACDataKeys is used when hashing any 'Data' field within the request which
+// prevents those specific keys from HMAC'd.
+// hmacAccessor is used to indicate whether some accessors should also be HMAC'd
+// when present.
+// nonHMACDataKeys is used when hashing any 'Data' field within the request which
+// prevents those specific keys from HMAC'd.
+func hashRequest(ctx context.Context, salter Salter, req *request, hmacAccessor bool, nonHMACDataKeys []string) error {
+ if req == nil {
+ return nil
}
salt, err := salter.Salt(ctx)
if err != nil {
- return nil, err
+ return err
}
fn := salt.GetIdentifiedHMAC
- req := *in
-
- if req.Auth != nil {
- cp, err := copystructure.Copy(req.Auth)
- if err != nil {
- return nil, err
- }
-
- req.Auth, err = HashAuth(ctx, salter, cp.(*logical.Auth), HMACAccessor)
- if err != nil {
- return nil, err
- }
- }
if req.ClientToken != "" {
req.ClientToken = fn(req.ClientToken)
}
- if HMACAccessor && req.ClientTokenAccessor != "" {
+ if hmacAccessor && req.ClientTokenAccessor != "" {
req.ClientTokenAccessor = fn(req.ClientTokenAccessor)
}
if req.Data != nil {
- copy, err := copystructure.Copy(req.Data)
+ err = hashMap(fn, req.Data, nonHMACDataKeys)
if err != nil {
- return nil, err
+ return err
}
-
- err = hashMap(fn, copy.(map[string]interface{}), nonHMACDataKeys)
- if err != nil {
- return nil, err
- }
- req.Data = copy.(map[string]interface{})
}
- return &req, nil
+ return nil
}
-func hashMap(hashFunc HashCallback, data map[string]interface{}, nonHMACDataKeys []string) error {
+func hashMap(hashFunc hashCallback, data map[string]interface{}, nonHMACDataKeys []string) error {
for k, v := range data {
if o, ok := v.(logical.OptMarshaler); ok {
marshaled, err := o.MarshalJSONWithOptions(&logical.MarshalOptions{
@@ -112,104 +99,82 @@ func hashMap(hashFunc HashCallback, data map[string]interface{}, nonHMACDataKeys
}
}
- return HashStructure(data, hashFunc, nonHMACDataKeys)
+ return hashStructure(data, hashFunc, nonHMACDataKeys)
}
-// HashResponse returns a hashed copy of the logical.Request input.
-func HashResponse(ctx context.Context, salter Salter, in *logical.Response, HMACAccessor bool, nonHMACDataKeys []string, elideListResponseData bool) (*logical.Response, error) {
- if in == nil {
- return nil, nil
+// hashResponse uses the Salter to hash the supplied response (modifying it).
+// hmacAccessor is used to indicate whether some accessors should also be HMAC'd
+// when present.
+// nonHMACDataKeys is used when hashing any 'Data' field within the response which
+// prevents those specific keys from HMAC'd.
+// See: /vault/docs/audit#eliding-list-response-bodies
+func hashResponse(ctx context.Context, salter Salter, resp *response, hmacAccessor bool, nonHMACDataKeys []string) error {
+ if resp == nil {
+ return nil
}
salt, err := salter.Salt(ctx)
if err != nil {
- return nil, err
+ return err
}
fn := salt.GetIdentifiedHMAC
- resp := *in
-
- if resp.Auth != nil {
- cp, err := copystructure.Copy(resp.Auth)
- if err != nil {
- return nil, err
- }
-
- resp.Auth, err = HashAuth(ctx, salter, cp.(*logical.Auth), HMACAccessor)
- if err != nil {
- return nil, err
- }
- }
if resp.Data != nil {
- copy, err := copystructure.Copy(resp.Data)
+ if b, ok := resp.Data[logical.HTTPRawBody].([]byte); ok {
+ resp.Data[logical.HTTPRawBody] = string(b)
+ }
+
+ err = hashMap(fn, resp.Data, nonHMACDataKeys)
if err != nil {
- return nil, err
+ return err
}
-
- mapCopy := copy.(map[string]interface{})
- if b, ok := mapCopy[logical.HTTPRawBody].([]byte); ok {
- mapCopy[logical.HTTPRawBody] = string(b)
- }
-
- // Processing list response data elision takes place at this point in the code for performance reasons:
- // - take advantage of the deep copy of resp.Data that was going to be done anyway for hashing
- // - but elide data before potentially spending time hashing it
- if elideListResponseData {
- doElideListResponseData(mapCopy)
- }
-
- err = hashMap(fn, mapCopy, nonHMACDataKeys)
- if err != nil {
- return nil, err
- }
- resp.Data = mapCopy
}
if resp.WrapInfo != nil {
var err error
- resp.WrapInfo, err = hashWrapInfo(fn, resp.WrapInfo, HMACAccessor)
+ err = hashWrapInfo(fn, resp.WrapInfo, hmacAccessor)
if err != nil {
- return nil, err
+ return err
}
}
- return &resp, nil
+ return nil
}
-// hashWrapInfo returns a hashed copy of the wrapping.ResponseWrapInfo input.
-func hashWrapInfo(hashFunc HashCallback, in *wrapping.ResponseWrapInfo, HMACAccessor bool) (*wrapping.ResponseWrapInfo, error) {
- if in == nil {
- return nil, nil
+// hashWrapInfo uses the supplied hashing function to hash responseWrapInfo (modifying it).
+// hmacAccessor is used to indicate whether some accessors should also be HMAC'd
+// when present.
+func hashWrapInfo(hashFunc hashCallback, wrapInfo *responseWrapInfo, hmacAccessor bool) error {
+ if wrapInfo == nil {
+ return nil
}
- wrapinfo := *in
+ wrapInfo.Token = hashFunc(wrapInfo.Token)
- wrapinfo.Token = hashFunc(wrapinfo.Token)
+ if hmacAccessor {
+ wrapInfo.Accessor = hashFunc(wrapInfo.Accessor)
- if HMACAccessor {
- wrapinfo.Accessor = hashFunc(wrapinfo.Accessor)
-
- if wrapinfo.WrappedAccessor != "" {
- wrapinfo.WrappedAccessor = hashFunc(wrapinfo.WrappedAccessor)
+ if wrapInfo.WrappedAccessor != "" {
+ wrapInfo.WrappedAccessor = hashFunc(wrapInfo.WrappedAccessor)
}
}
- return &wrapinfo, nil
+ return nil
}
-// HashStructure takes an interface and hashes all the values within
+// hashStructure takes an interface and hashes all the values within
// the structure. Only _values_ are hashed: keys of objects are not.
//
-// For the HashCallback, see the built-in HashCallbacks below.
-func HashStructure(s interface{}, cb HashCallback, ignoredKeys []string) error {
+// For the hashCallback, see the built-in HashCallbacks below.
+func hashStructure(s interface{}, cb hashCallback, ignoredKeys []string) error {
walker := &hashWalker{Callback: cb, IgnoredKeys: ignoredKeys}
return reflectwalk.Walk(s, walker)
}
-// HashCallback is the callback called for HashStructure to hash
+// hashCallback is the callback called for hashStructure to hash
// a value.
-type HashCallback func(string) string
+type hashCallback func(string) string
// hashWalker implements interfaces for the reflectwalk package
// (github.com/mitchellh/reflectwalk) that can be used to automatically
@@ -218,21 +183,27 @@ type hashWalker struct {
// Callback is the function to call with the primitive that is
// to be hashed. If there is an error, walking will be halted
// immediately and the error returned.
- Callback HashCallback
- // IgnoreKeys are the keys that wont have the HashCallback applied
+ Callback hashCallback
+
+ // IgnoreKeys are the keys that won't have the hashCallback applied
IgnoredKeys []string
+
// MapElem appends the key itself (not the reflect.Value) to key.
// The last element in key is the most recently entered map key.
// Since Exit pops the last element of key, only nesting to another
// structure increases the size of this slice.
- key []string
+ key []string
+
lastValue reflect.Value
+
// Enter appends to loc and exit pops loc. The last element of loc is thus
// the current location.
loc []reflectwalk.Location
+
// Map and Slice append to cs, Exit pops the last element off cs.
// The last element in cs is the most recently entered map or slice.
cs []reflect.Value
+
// MapElem and SliceElem append to csKey. The last element in csKey is the
// most recently entered map key or slice index. Since Exit pops the last
// element of csKey, only nesting to another structure increases the size of
diff --git a/audit/hashstructure_test.go b/audit/hashstructure_test.go
index f437b3e14c..f4eccaa8e5 100644
--- a/audit/hashstructure_test.go
+++ b/audit/hashstructure_test.go
@@ -7,17 +7,17 @@ import (
"context"
"crypto/sha256"
"encoding/json"
- "fmt"
"reflect"
"testing"
"time"
- "github.com/go-test/deep"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/helper/wrapping"
"github.com/hashicorp/vault/sdk/logical"
"github.com/mitchellh/copystructure"
+ "github.com/stretchr/testify/require"
)
func TestCopy_auth(t *testing.T) {
@@ -97,18 +97,21 @@ func TestCopy_response(t *testing.T) {
}
}
-// TestSalter is a structure that implements the Salter interface in a trivial
+// testSalter is a structure that implements the Salter interface in a trivial
// manner.
-type TestSalter struct{}
+type testSalter struct{}
// Salt returns a salt.Salt pointer based on dummy data stored in an in-memory
// storage instance.
-func (*TestSalter) Salt(ctx context.Context) (*salt.Salt, error) {
+func (*testSalter) Salt(ctx context.Context) (*salt.Salt, error) {
inmemStorage := &logical.InmemStorage{}
- inmemStorage.Put(context.Background(), &logical.StorageEntry{
+ err := inmemStorage.Put(context.Background(), &logical.StorageEntry{
Key: "salt",
Value: []byte("foo"),
})
+ if err != nil {
+ return nil, err
+ }
return salt.NewSalt(context.Background(), inmemStorage, &salt.Config{
HMAC: sha256.New,
@@ -117,62 +120,74 @@ func (*TestSalter) Salt(ctx context.Context) (*salt.Salt, error) {
}
func TestHashString(t *testing.T) {
- salter := &TestSalter{}
+ salter := &testSalter{}
- out, err := HashString(context.Background(), salter, "foo")
+ out, err := hashString(context.Background(), salter, "foo")
if err != nil {
t.Fatalf("Error instantiating salt: %s", err)
}
if out != "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a" {
- t.Fatalf("err: HashString output did not match expected")
+ t.Fatalf("err: hashString output did not match expected")
}
}
func TestHashAuth(t *testing.T) {
- cases := []struct {
+ cases := map[string]struct {
Input *logical.Auth
- Output *logical.Auth
+ Output *auth
HMACAccessor bool
}{
- {
- &logical.Auth{ClientToken: "foo"},
- &logical.Auth{ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a"},
+ "no-accessor-hmac": {
+ &logical.Auth{
+ ClientToken: "foo",
+ Accessor: "very-accessible",
+ LeaseOptions: logical.LeaseOptions{
+ TTL: 1 * time.Hour,
+ },
+ TokenType: logical.TokenTypeService,
+ },
+ &auth{
+ ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
+ Accessor: "very-accessible",
+ TokenTTL: 3600,
+ TokenType: "service",
+ RemainingUses: 5,
+ },
false,
},
- {
+ "accessor-hmac": {
&logical.Auth{
- LeaseOptions: logical.LeaseOptions{
- TTL: 1 * time.Hour,
- },
-
+ Accessor: "very-accessible",
ClientToken: "foo",
- },
- &logical.Auth{
LeaseOptions: logical.LeaseOptions{
TTL: 1 * time.Hour,
},
-
- ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
+ TokenType: logical.TokenTypeBatch,
},
- false,
+ &auth{
+ ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
+ Accessor: "hmac-sha256:5d6d7c8da5b699ace193ea453bbf77082a8aaca42a474436509487d646a7c0af",
+ TokenTTL: 3600,
+ TokenType: "batch",
+ RemainingUses: 5,
+ },
+ true,
},
}
inmemStorage := &logical.InmemStorage{}
- inmemStorage.Put(context.Background(), &logical.StorageEntry{
+ err := inmemStorage.Put(context.Background(), &logical.StorageEntry{
Key: "salt",
Value: []byte("foo"),
})
- salter := &TestSalter{}
+ require.NoError(t, err)
+ salter := &testSalter{}
for _, tc := range cases {
- input := fmt.Sprintf("%#v", tc.Input)
- out, err := HashAuth(context.Background(), salter, tc.Input, tc.HMACAccessor)
- if err != nil {
- t.Fatalf("err: %s\n\n%s", err, input)
- }
- if !reflect.DeepEqual(out, tc.Output) {
- t.Fatalf("bad:\nInput:\n%s\nOutput:\n%#v\nExpected output:\n%#v", input, out, tc.Output)
- }
+ auditAuth, err := newAuth(tc.Input, 5)
+ require.NoError(t, err)
+ err = hashAuth(context.Background(), salter, auditAuth, tc.HMACAccessor)
+ require.NoError(t, err)
+ require.Equal(t, tc.Output, auditAuth)
}
}
@@ -190,7 +205,7 @@ var _ logical.OptMarshaler = &testOptMarshaler{}
func TestHashRequest(t *testing.T) {
cases := []struct {
Input *logical.Request
- Output *logical.Request
+ Output *request
NonHMACDataKeys []string
HMACAccessor bool
}{
@@ -203,13 +218,17 @@ func TestHashRequest(t *testing.T) {
"om": &testOptMarshaler{S: "bar", I: 1},
},
},
- &logical.Request{
+ &request{
Data: map[string]interface{}{
"foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
"baz": "foobar",
"private_key_type": "hmac-sha256:995230dca56fffd310ff591aa404aab52b2abb41703c787cfa829eceb4595bf1",
"om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`),
},
+ Namespace: &namespace{
+ ID: nshelper.RootNamespace.ID,
+ Path: nshelper.RootNamespace.Path,
+ },
},
[]string{"baz"},
false,
@@ -217,86 +236,82 @@ func TestHashRequest(t *testing.T) {
}
inmemStorage := &logical.InmemStorage{}
- inmemStorage.Put(context.Background(), &logical.StorageEntry{
+ err := inmemStorage.Put(context.Background(), &logical.StorageEntry{
Key: "salt",
Value: []byte("foo"),
})
- salter := &TestSalter{}
+ require.NoError(t, err)
+ salter := &testSalter{}
for _, tc := range cases {
- input := fmt.Sprintf("%#v", tc.Input)
- out, err := HashRequest(context.Background(), salter, tc.Input, tc.HMACAccessor, tc.NonHMACDataKeys)
- if err != nil {
- t.Fatalf("err: %s\n\n%s", err, input)
- }
- if diff := deep.Equal(out, tc.Output); len(diff) > 0 {
- t.Fatalf("bad:\nInput:\n%s\nDiff:\n%#v", input, diff)
- }
+ auditReq, err := newRequest(tc.Input, nshelper.RootNamespace)
+ require.NoError(t, err)
+ err = hashRequest(context.Background(), salter, auditReq, tc.HMACAccessor, tc.NonHMACDataKeys)
+ require.NoError(t, err)
+ require.Equal(t, tc.Output, auditReq)
}
}
func TestHashResponse(t *testing.T) {
now := time.Now()
- cases := []struct {
- Input *logical.Response
- Output *logical.Response
- NonHMACDataKeys []string
- HMACAccessor bool
- }{
- {
- &logical.Response{
- Data: map[string]interface{}{
- "foo": "bar",
- "baz": "foobar",
- // Responses can contain time values, so test that with
- // a known fixed value.
- "bar": now,
- "om": &testOptMarshaler{S: "bar", I: 1},
- },
- WrapInfo: &wrapping.ResponseWrapInfo{
- TTL: 60,
- Token: "bar",
- Accessor: "flimflam",
- CreationTime: now,
- WrappedAccessor: "bar",
- },
- },
- &logical.Response{
- Data: map[string]interface{}{
- "foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
- "baz": "foobar",
- "bar": now.Format(time.RFC3339Nano),
- "om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`),
- },
- WrapInfo: &wrapping.ResponseWrapInfo{
- TTL: 60,
- Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
- Accessor: "hmac-sha256:7c9c6fe666d0af73b3ebcfbfabe6885015558213208e6635ba104047b22f6390",
- CreationTime: now,
- WrappedAccessor: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
- },
- },
- []string{"baz"},
- true,
+ resp := &logical.Response{
+ Data: map[string]interface{}{
+ "foo": "bar",
+ "baz": "foobar",
+ // Responses can contain time values, so test that with a known fixed value.
+ "bar": now,
+ "om": &testOptMarshaler{S: "bar", I: 1},
+ },
+ WrapInfo: &wrapping.ResponseWrapInfo{
+ TTL: 1 * time.Minute,
+ Token: "bar",
+ Accessor: "flimflam",
+ CreationTime: now,
+ WrappedAccessor: "bar",
},
}
+ req := &logical.Request{MountPoint: "/foo/bar"}
+ req.SetMountClass("kv")
+ req.SetMountIsExternalPlugin(true)
+ req.SetMountRunningVersion("123")
+ req.SetMountRunningSha256("256-256!")
+
+ nonHMACDataKeys := []string{"baz"}
+
+ expected := &response{
+ Data: map[string]interface{}{
+ "foo": "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
+ "baz": "foobar",
+ "bar": now.Format(time.RFC3339Nano),
+ "om": json.RawMessage(`{"S":"hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317","I":1}`),
+ },
+ WrapInfo: &responseWrapInfo{
+ TTL: 60,
+ Token: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
+ Accessor: "hmac-sha256:7c9c6fe666d0af73b3ebcfbfabe6885015558213208e6635ba104047b22f6390",
+ CreationTime: now.UTC().Format(time.RFC3339Nano),
+ WrappedAccessor: "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317",
+ },
+ MountClass: "kv",
+ MountIsExternalPlugin: true,
+ MountPoint: "/foo/bar",
+ MountRunningVersion: "123",
+ MountRunningSha256: "256-256!",
+ }
+
inmemStorage := &logical.InmemStorage{}
- inmemStorage.Put(context.Background(), &logical.StorageEntry{
+ err := inmemStorage.Put(context.Background(), &logical.StorageEntry{
Key: "salt",
Value: []byte("foo"),
})
- salter := &TestSalter{}
- for _, tc := range cases {
- input := fmt.Sprintf("%#v", tc.Input)
- out, err := HashResponse(context.Background(), salter, tc.Input, tc.HMACAccessor, tc.NonHMACDataKeys, false)
- if err != nil {
- t.Fatalf("err: %s\n\n%s", err, input)
- }
- if diff := deep.Equal(out, tc.Output); len(diff) > 0 {
- t.Fatalf("bad:\nInput:\n%s\nDiff:\n%#v", input, diff)
- }
- }
+ require.NoError(t, err)
+ salter := &testSalter{}
+ auditResp, err := newResponse(resp, req, false)
+ require.NoError(t, err)
+ err = hashResponse(context.Background(), salter, auditResp, true, nonHMACDataKeys)
+ require.NoError(t, err)
+ require.Equal(t, expected, auditResp)
}
func TestHashWalker(t *testing.T) {
@@ -326,7 +341,7 @@ func TestHashWalker(t *testing.T) {
}
for _, tc := range cases {
- err := HashStructure(tc.Input, func(string) string {
+ err := hashStructure(tc.Input, func(string) string {
return replaceText
}, nil)
if err != nil {
@@ -380,7 +395,7 @@ func TestHashWalker_TimeStructs(t *testing.T) {
}
for _, tc := range cases {
- err := HashStructure(tc.Input, func(s string) string {
+ err := hashStructure(tc.Input, func(s string) string {
return s + replaceText
}, nil)
if err != nil {
diff --git a/audit/headers.go b/audit/headers.go
index 535a61244e..a6ba6b00cd 100644
--- a/audit/headers.go
+++ b/audit/headers.go
@@ -42,7 +42,7 @@ func AuditedHeadersKey() string {
return AuditedHeadersSubPath + auditedHeadersEntry
}
-type HeaderSettings struct {
+type headerSettings struct {
// HMAC is used to indicate whether the value of the header should be HMAC'd.
HMAC bool `json:"hmac"`
}
@@ -51,7 +51,7 @@ type HeaderSettings struct {
// headers to the audit logs. It uses a BarrierView to persist the settings.
type HeadersConfig struct {
// headerSettings stores the current headers that should be audited, and their settings.
- headerSettings map[string]*HeaderSettings
+ headerSettings map[string]*headerSettings
// view is the barrier view which should be used to access underlying audit header config data.
view durableStorer
@@ -69,18 +69,18 @@ func NewHeadersConfig(view durableStorer) (*HeadersConfig, error) {
// Store the view so that we can reload headers when we 'Invalidate'.
return &HeadersConfig{
view: view,
- headerSettings: make(map[string]*HeaderSettings),
+ headerSettings: make(map[string]*headerSettings),
}, nil
}
// Header attempts to retrieve a copy of the settings associated with the specified header.
// The second boolean return parameter indicates whether the header existed in configuration,
// it should be checked as when 'false' the returned settings will have the default values.
-func (a *HeadersConfig) Header(name string) (HeaderSettings, bool) {
+func (a *HeadersConfig) Header(name string) (headerSettings, bool) {
a.RLock()
defer a.RUnlock()
- var s HeaderSettings
+ var s headerSettings
v, ok := a.headerSettings[strings.ToLower(name)]
if ok {
@@ -91,16 +91,16 @@ func (a *HeadersConfig) Header(name string) (HeaderSettings, bool) {
}
// Headers returns all existing headers along with a copy of their current settings.
-func (a *HeadersConfig) Headers() map[string]HeaderSettings {
+func (a *HeadersConfig) Headers() map[string]headerSettings {
a.RLock()
defer a.RUnlock()
// We know how many entries the map should have.
- headers := make(map[string]HeaderSettings, len(a.headerSettings))
+ headers := make(map[string]headerSettings, len(a.headerSettings))
// Clone the headers
for name, setting := range a.headerSettings {
- headers[name] = HeaderSettings{HMAC: setting.HMAC}
+ headers[name] = headerSettings{HMAC: setting.HMAC}
}
return headers
@@ -118,10 +118,10 @@ func (a *HeadersConfig) Add(ctx context.Context, header string, hmac bool) error
defer a.Unlock()
if a.headerSettings == nil {
- a.headerSettings = make(map[string]*HeaderSettings, 1)
+ a.headerSettings = make(map[string]*headerSettings, 1)
}
- a.headerSettings[strings.ToLower(header)] = &HeaderSettings{hmac}
+ a.headerSettings[strings.ToLower(header)] = &headerSettings{hmac}
entry, err := logical.StorageEntryJSON(auditedHeadersEntry, a.headerSettings)
if err != nil {
return fmt.Errorf("failed to persist audited headers config: %w", err)
@@ -167,12 +167,12 @@ func (a *HeadersConfig) Remove(ctx context.Context, header string) error {
// added to HeadersConfig in order to allow them to appear in audit logs in a raw
// format. If the Vault Operator adds their own setting for any of the defaults,
// their setting will be honored.
-func (a *HeadersConfig) DefaultHeaders() map[string]*HeaderSettings {
+func (a *HeadersConfig) DefaultHeaders() map[string]*headerSettings {
// Support deprecated 'x-' prefix (https://datatracker.ietf.org/doc/html/rfc6648)
const correlationID = "correlation-id"
xCorrelationID := fmt.Sprintf("x-%s", correlationID)
- return map[string]*HeaderSettings{
+ return map[string]*headerSettings{
correlationID: {},
xCorrelationID: {},
}
@@ -192,7 +192,7 @@ func (a *HeadersConfig) Invalidate(ctx context.Context) error {
// If we cannot update the stored 'new' headers, we will clear the existing
// ones as part of invalidation.
- headers := make(map[string]*HeaderSettings)
+ headers := make(map[string]*headerSettings)
if out != nil {
err = out.DecodeJSON(&headers)
if err != nil {
@@ -202,7 +202,7 @@ func (a *HeadersConfig) Invalidate(ctx context.Context) error {
// Ensure that we are able to case-sensitively access the headers;
// necessary for the upgrade case
- lowerHeaders := make(map[string]*HeaderSettings, len(headers))
+ lowerHeaders := make(map[string]*headerSettings, len(headers))
for k, v := range headers {
lowerHeaders[strings.ToLower(k)] = v
}
@@ -248,7 +248,7 @@ func (a *HeadersConfig) ApplyConfig(ctx context.Context, headers map[string][]st
// Optionally hmac the values
if settings.HMAC {
for i, el := range hVals {
- hVal, err := HashString(ctx, salter, el)
+ hVal, err := hashString(ctx, salter, el)
if err != nil {
return nil, err
}
diff --git a/audit/headers_test.go b/audit/headers_test.go
index e4ff34047f..025f4a422f 100644
--- a/audit/headers_test.go
+++ b/audit/headers_test.go
@@ -71,7 +71,7 @@ func newMockStorage(t *testing.T) *mockStorage {
func mockAuditedHeadersConfig(t *testing.T) *HeadersConfig {
return &HeadersConfig{
- headerSettings: make(map[string]*HeaderSettings),
+ headerSettings: make(map[string]*headerSettings),
view: newMockStorage(t),
}
}
@@ -110,13 +110,13 @@ func testAddHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value")
}
- headers := make(map[string]*HeaderSettings)
+ headers := make(map[string]*headerSettings)
err = out.DecodeJSON(&headers)
if err != nil {
t.Fatalf("Error decoding header view: %s", err)
}
- expected := map[string]*HeaderSettings{
+ expected := map[string]*headerSettings{
"x-test-header": {
HMAC: false,
},
@@ -148,13 +148,13 @@ func testAddHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value")
}
- headers = make(map[string]*HeaderSettings)
+ headers = make(map[string]*headerSettings)
err = out.DecodeJSON(&headers)
if err != nil {
t.Fatalf("Error decoding header view: %s", err)
}
- expected["x-vault-header"] = &HeaderSettings{
+ expected["x-vault-header"] = &headerSettings{
HMAC: true,
}
@@ -184,13 +184,13 @@ func testRemoveHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value")
}
- headers := make(map[string]*HeaderSettings)
+ headers := make(map[string]*headerSettings)
err = out.DecodeJSON(&headers)
if err != nil {
t.Fatalf("Error decoding header view: %s", err)
}
- expected := map[string]*HeaderSettings{
+ expected := map[string]*headerSettings{
"x-vault-header": {
HMAC: true,
},
@@ -218,13 +218,13 @@ func testRemoveHeaders(t *testing.T, conf *HeadersConfig) {
t.Fatal("nil value")
}
- headers = make(map[string]*HeaderSettings)
+ headers = make(map[string]*headerSettings)
err = out.DecodeJSON(&headers)
if err != nil {
t.Fatalf("Error decoding header view: %s", err)
}
- expected = make(map[string]*HeaderSettings)
+ expected = make(map[string]*headerSettings)
if !reflect.DeepEqual(headers, expected) {
t.Fatalf("Expected config didn't match actual. Expected: %#v, Got: %#v", expected, headers)
@@ -247,7 +247,7 @@ func TestAuditedHeadersConfig_ApplyConfig(t *testing.T) {
"Content-Type": {"json"},
}
- salter := &TestSalter{}
+ salter := &testSalter{}
result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter)
if err != nil {
@@ -307,7 +307,7 @@ func TestAuditedHeadersConfig_ApplyConfig_NoRequestHeaders(t *testing.T) {
err = conf.Add(context.Background(), "X-Vault-HeAdEr", true)
require.NoError(t, err)
- salter := &TestSalter{}
+ salter := &testSalter{}
// Test sending in nil headers first.
result, err := conf.ApplyConfig(context.Background(), nil, salter)
@@ -331,7 +331,7 @@ func TestAuditedHeadersConfig_ApplyConfig_NoConfiguredHeaders(t *testing.T) {
"Content-Type": {"json"},
}
- salter := &TestSalter{}
+ salter := &testSalter{}
result, err := conf.ApplyConfig(context.Background(), reqHeaders, salter)
if err != nil {
@@ -364,7 +364,7 @@ func (s *FailingSalter) Salt(context.Context) (*salt.Salt, error) {
}
// TestAuditedHeadersConfig_ApplyConfig_HashStringError tests the case where
-// an error is returned from HashString instead of a map of headers.
+// an error is returned from hashString instead of a map of headers.
func TestAuditedHeadersConfig_ApplyConfig_HashStringError(t *testing.T) {
t.Parallel()
@@ -391,11 +391,11 @@ func TestAuditedHeadersConfig_ApplyConfig_HashStringError(t *testing.T) {
func BenchmarkAuditedHeaderConfig_ApplyConfig(b *testing.B) {
conf := &HeadersConfig{
- headerSettings: make(map[string]*HeaderSettings),
+ headerSettings: make(map[string]*headerSettings),
view: nil,
}
- conf.headerSettings = map[string]*HeaderSettings{
+ conf.headerSettings = map[string]*headerSettings{
"X-Test-Header": {false},
"X-Vault-Header": {true},
}
@@ -406,7 +406,7 @@ func BenchmarkAuditedHeaderConfig_ApplyConfig(b *testing.B) {
"Content-Type": {"json"},
}
- salter := &TestSalter{}
+ salter := &testSalter{}
// Reset the timer since we did a lot above
b.ResetTimer()
@@ -449,7 +449,7 @@ func TestAuditedHeaders_invalidate(t *testing.T) {
require.Len(t, ahc.headerSettings, 0)
// Store some data using the view.
- fakeHeaders1 := map[string]*HeaderSettings{"x-magic-header": {}}
+ fakeHeaders1 := map[string]*headerSettings{"x-magic-header": {}}
fakeBytes1, err := json.Marshal(fakeHeaders1)
require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
@@ -463,7 +463,7 @@ func TestAuditedHeaders_invalidate(t *testing.T) {
require.True(t, ok)
// Do it again with more headers and random casing.
- fakeHeaders2 := map[string]*HeaderSettings{
+ fakeHeaders2 := map[string]*headerSettings{
"x-magic-header": {},
"x-even-MORE-magic-header": {},
}
@@ -493,7 +493,7 @@ func TestAuditedHeaders_invalidate_nil_view(t *testing.T) {
require.Len(t, ahc.headerSettings, 0)
// Store some data using the view.
- fakeHeaders1 := map[string]*HeaderSettings{"x-magic-header": {}}
+ fakeHeaders1 := map[string]*headerSettings{"x-magic-header": {}}
fakeBytes1, err := json.Marshal(fakeHeaders1)
require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
@@ -597,7 +597,7 @@ func TestAuditedHeaders_invalidate_defaults(t *testing.T) {
require.Len(t, ahc.headerSettings, 0)
// Store some data using the view.
- fakeHeaders1 := map[string]*HeaderSettings{"x-magic-header": {}}
+ fakeHeaders1 := map[string]*headerSettings{"x-magic-header": {}}
fakeBytes1, err := json.Marshal(fakeHeaders1)
require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
@@ -614,7 +614,7 @@ func TestAuditedHeaders_invalidate_defaults(t *testing.T) {
require.False(t, s.HMAC)
// Add correlation ID specifically with HMAC and make sure it doesn't get blasted away.
- fakeHeaders1 = map[string]*HeaderSettings{"x-magic-header": {}, "X-Correlation-ID": {HMAC: true}}
+ fakeHeaders1 = map[string]*headerSettings{"x-magic-header": {}, "X-Correlation-ID": {HMAC: true}}
fakeBytes1, err = json.Marshal(fakeHeaders1)
require.NoError(t, err)
err = view.Put(context.Background(), &logical.StorageEntry{Key: auditedHeadersEntry, Value: fakeBytes1})
diff --git a/audit/nodes.go b/audit/nodes.go
index 3a038c35f2..bea1a2049e 100644
--- a/audit/nodes.go
+++ b/audit/nodes.go
@@ -34,7 +34,7 @@ func processManual(ctx context.Context, data *logical.LogInput, ids []eventlogge
}
// Create an audit event.
- a, err := NewEvent(RequestType)
+ a, err := newEvent(RequestType)
if err != nil {
return err
}
diff --git a/audit/nodes_test.go b/audit/nodes_test.go
index a33f66bb2b..43f7eae354 100644
--- a/audit/nodes_test.go
+++ b/audit/nodes_test.go
@@ -9,7 +9,7 @@ import (
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-uuid"
- "github.com/hashicorp/vault/helper/namespace"
+ nshelper "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/internal/observability/event"
"github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require"
@@ -32,7 +32,7 @@ func TestProcessManual_NilData(t *testing.T) {
ids = append(ids, sinkId)
nodes[sinkId] = sinkNode
- err := processManual(namespace.RootContext(context.Background()), nil, ids, nodes)
+ err := processManual(nshelper.RootContext(context.Background()), nil, ids, nodes)
require.Error(t, err)
require.EqualError(t, err, "data cannot be nil")
}
@@ -76,7 +76,7 @@ func TestProcessManual_BadIDs(t *testing.T) {
require.NoError(t, err)
data := newData(requestId)
- err = processManual(namespace.RootContext(context.Background()), data, tc.IDs, nodes)
+ err = processManual(nshelper.RootContext(context.Background()), data, tc.IDs, nodes)
require.Error(t, err)
require.EqualError(t, err, tc.ExpectedErrorMessage)
})
@@ -103,7 +103,7 @@ func TestProcessManual_NoNodes(t *testing.T) {
require.NoError(t, err)
data := newData(requestId)
- err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
+ err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
require.Error(t, err)
require.EqualError(t, err, "nodes are required")
}
@@ -130,7 +130,7 @@ func TestProcessManual_IdNodeMismatch(t *testing.T) {
require.NoError(t, err)
data := newData(requestId)
- err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
+ err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
require.Error(t, err)
require.ErrorContains(t, err, "node not found: ")
}
@@ -153,7 +153,7 @@ func TestProcessManual_NotEnoughNodes(t *testing.T) {
require.NoError(t, err)
data := newData(requestId)
- err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
+ err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
require.Error(t, err)
require.EqualError(t, err, "minimum of 2 ids are required")
}
@@ -181,7 +181,7 @@ func TestProcessManual_LastNodeNotSink(t *testing.T) {
require.NoError(t, err)
data := newData(requestId)
- err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
+ err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
require.Error(t, err)
require.EqualError(t, err, "last node must be a filter or sink")
}
@@ -210,7 +210,7 @@ func TestProcessManualEndWithSink(t *testing.T) {
require.NoError(t, err)
data := newData(requestId)
- err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
+ err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
require.NoError(t, err)
}
@@ -243,7 +243,7 @@ func TestProcessManual_EndWithFilter(t *testing.T) {
require.NoError(t, err)
data := newData(requestId)
- err = processManual(namespace.RootContext(context.Background()), data, ids, nodes)
+ err = processManual(nshelper.RootContext(context.Background()), data, ids, nodes)
require.NoError(t, err)
}
diff --git a/audit/options.go b/audit/options.go
index a48d76cd02..73c46afb7d 100644
--- a/audit/options.go
+++ b/audit/options.go
@@ -9,8 +9,8 @@ import (
"time"
)
-// Option is how options are passed as arguments.
-type Option func(*options) error
+// option is how options are passed as arguments.
+type option func(*options) error
// options are used to represent configuration for a audit related nodes.
type options struct {
@@ -29,15 +29,15 @@ type options struct {
func getDefaultOptions() options {
return options{
withNow: time.Now(),
- withFormat: JSONFormat,
+ withFormat: jsonFormat,
withHMACAccessor: true,
}
}
-// getOpts applies each supplied Option and returns the fully configured options.
-// Each Option is applied in the order it appears in the argument list, so it is
-// possible to supply the same Option numerous times and the 'last write wins'.
-func getOpts(opt ...Option) (options, error) {
+// getOpts applies each supplied option and returns the fully configured options.
+// Each option is applied in the order it appears in the argument list, so it is
+// possible to supply the same option numerous times and the 'last write wins'.
+func getOpts(opt ...option) (options, error) {
opts := getDefaultOptions()
for _, o := range opt {
if o == nil {
@@ -50,8 +50,8 @@ func getOpts(opt ...Option) (options, error) {
return opts, nil
}
-// WithID provides an optional ID.
-func WithID(id string) Option {
+// withID provides an optional ID.
+func withID(id string) option {
return func(o *options) error {
var err error
@@ -67,8 +67,8 @@ func WithID(id string) Option {
}
}
-// WithNow provides an Option to represent 'now'.
-func WithNow(now time.Time) Option {
+// withNow provides an option to represent 'now'.
+func withNow(now time.Time) option {
return func(o *options) error {
var err error
@@ -83,8 +83,8 @@ func WithNow(now time.Time) Option {
}
}
-// WithSubtype provides an Option to represent the event subtype.
-func WithSubtype(s string) Option {
+// withSubtype provides an option to represent the event subtype.
+func withSubtype(s string) option {
return func(o *options) error {
s := strings.TrimSpace(s)
if s == "" {
@@ -101,8 +101,8 @@ func WithSubtype(s string) Option {
}
}
-// WithFormat provides an Option to represent event format.
-func WithFormat(f string) Option {
+// withFormat provides an option to represent event format.
+func withFormat(f string) option {
return func(o *options) error {
f := strings.TrimSpace(strings.ToLower(f))
if f == "" {
@@ -121,8 +121,8 @@ func WithFormat(f string) Option {
}
}
-// WithPrefix provides an Option to represent a prefix for a file sink.
-func WithPrefix(prefix string) Option {
+// withPrefix provides an option to represent a prefix for a file sink.
+func withPrefix(prefix string) option {
return func(o *options) error {
o.withPrefix = prefix
@@ -130,32 +130,32 @@ func WithPrefix(prefix string) Option {
}
}
-// WithRaw provides an Option to represent whether 'raw' is required.
-func WithRaw(r bool) Option {
+// withRaw provides an option to represent whether 'raw' is required.
+func withRaw(r bool) option {
return func(o *options) error {
o.withRaw = r
return nil
}
}
-// WithElision provides an Option to represent whether elision (...) is required.
-func WithElision(e bool) Option {
+// withElision provides an option to represent whether elision (...) is required.
+func withElision(e bool) option {
return func(o *options) error {
o.withElision = e
return nil
}
}
-// WithOmitTime provides an Option to represent whether to omit time.
-func WithOmitTime(t bool) Option {
+// withOmitTime provides an option to represent whether to omit time.
+func withOmitTime(t bool) option {
return func(o *options) error {
o.withOmitTime = t
return nil
}
}
-// WithHMACAccessor provides an Option to represent whether an HMAC accessor is applicable.
-func WithHMACAccessor(h bool) Option {
+// withHMACAccessor provides an option to represent whether an HMAC accessor is applicable.
+func withHMACAccessor(h bool) option {
return func(o *options) error {
o.withHMACAccessor = h
return nil
diff --git a/audit/options_test.go b/audit/options_test.go
index 33de069fae..b4a668c3a8 100644
--- a/audit/options_test.go
+++ b/audit/options_test.go
@@ -10,8 +10,8 @@ import (
"github.com/stretchr/testify/require"
)
-// TestOptions_WithFormat exercises WithFormat Option to ensure it performs as expected.
-func TestOptions_WithFormat(t *testing.T) {
+// TestOptions_withFormat exercises withFormat option to ensure it performs as expected.
+func TestOptions_withFormat(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -38,12 +38,12 @@ func TestOptions_WithFormat(t *testing.T) {
"valid-json": {
Value: "json",
IsErrorExpected: false,
- ExpectedValue: JSONFormat,
+ ExpectedValue: jsonFormat,
},
"valid-jsonx": {
Value: "jsonx",
IsErrorExpected: false,
- ExpectedValue: JSONxFormat,
+ ExpectedValue: jsonxFormat,
},
}
@@ -53,7 +53,7 @@ func TestOptions_WithFormat(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithFormat(tc.Value)
+ applyOption := withFormat(tc.Value)
err := applyOption(opts)
switch {
case tc.IsErrorExpected:
@@ -67,8 +67,8 @@ func TestOptions_WithFormat(t *testing.T) {
}
}
-// TestOptions_WithSubtype exercises WithSubtype Option to ensure it performs as expected.
-func TestOptions_WithSubtype(t *testing.T) {
+// TestOptions_withSubtype exercises withSubtype option to ensure it performs as expected.
+func TestOptions_withSubtype(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -100,7 +100,7 @@ func TestOptions_WithSubtype(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithSubtype(tc.Value)
+ applyOption := withSubtype(tc.Value)
err := applyOption(opts)
switch {
case tc.IsErrorExpected:
@@ -114,8 +114,8 @@ func TestOptions_WithSubtype(t *testing.T) {
}
}
-// TestOptions_WithNow exercises WithNow Option to ensure it performs as expected.
-func TestOptions_WithNow(t *testing.T) {
+// TestOptions_withNow exercises withNow option to ensure it performs as expected.
+func TestOptions_withNow(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -143,7 +143,7 @@ func TestOptions_WithNow(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithNow(tc.Value)
+ applyOption := withNow(tc.Value)
err := applyOption(opts)
switch {
case tc.IsErrorExpected:
@@ -157,8 +157,8 @@ func TestOptions_WithNow(t *testing.T) {
}
}
-// TestOptions_WithID exercises WithID Option to ensure it performs as expected.
-func TestOptions_WithID(t *testing.T) {
+// TestOptions_withID exercises withID option to ensure it performs as expected.
+func TestOptions_withID(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -190,7 +190,7 @@ func TestOptions_WithID(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithID(tc.Value)
+ applyOption := withID(tc.Value)
err := applyOption(opts)
switch {
case tc.IsErrorExpected:
@@ -204,8 +204,8 @@ func TestOptions_WithID(t *testing.T) {
}
}
-// TestOptions_WithPrefix exercises WithPrefix Option to ensure it performs as expected.
-func TestOptions_WithPrefix(t *testing.T) {
+// TestOptions_withPrefix exercises withPrefix option to ensure it performs as expected.
+func TestOptions_withPrefix(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -237,7 +237,7 @@ func TestOptions_WithPrefix(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithPrefix(tc.Value)
+ applyOption := withPrefix(tc.Value)
err := applyOption(opts)
switch {
case tc.IsErrorExpected:
@@ -251,8 +251,8 @@ func TestOptions_WithPrefix(t *testing.T) {
}
}
-// TestOptions_WithRaw exercises WithRaw Option to ensure it performs as expected.
-func TestOptions_WithRaw(t *testing.T) {
+// TestOptions_withRaw exercises withRaw option to ensure it performs as expected.
+func TestOptions_withRaw(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -275,7 +275,7 @@ func TestOptions_WithRaw(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithRaw(tc.Value)
+ applyOption := withRaw(tc.Value)
err := applyOption(opts)
require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withRaw)
@@ -283,8 +283,8 @@ func TestOptions_WithRaw(t *testing.T) {
}
}
-// TestOptions_WithElision exercises WithElision Option to ensure it performs as expected.
-func TestOptions_WithElision(t *testing.T) {
+// TestOptions_withElision exercises withElision option to ensure it performs as expected.
+func TestOptions_withElision(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -307,7 +307,7 @@ func TestOptions_WithElision(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithElision(tc.Value)
+ applyOption := withElision(tc.Value)
err := applyOption(opts)
require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withElision)
@@ -315,8 +315,8 @@ func TestOptions_WithElision(t *testing.T) {
}
}
-// TestOptions_WithHMACAccessor exercises WithHMACAccessor Option to ensure it performs as expected.
-func TestOptions_WithHMACAccessor(t *testing.T) {
+// TestOptions_withHMACAccessor exercises withHMACAccessor option to ensure it performs as expected.
+func TestOptions_withHMACAccessor(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -339,7 +339,7 @@ func TestOptions_WithHMACAccessor(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithHMACAccessor(tc.Value)
+ applyOption := withHMACAccessor(tc.Value)
err := applyOption(opts)
require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withHMACAccessor)
@@ -347,8 +347,8 @@ func TestOptions_WithHMACAccessor(t *testing.T) {
}
}
-// TestOptions_WithOmitTime exercises WithOmitTime Option to ensure it performs as expected.
-func TestOptions_WithOmitTime(t *testing.T) {
+// TestOptions_withOmitTime exercises withOmitTime option to ensure it performs as expected.
+func TestOptions_withOmitTime(t *testing.T) {
t.Parallel()
tests := map[string]struct {
@@ -371,7 +371,7 @@ func TestOptions_WithOmitTime(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
opts := &options{}
- applyOption := WithOmitTime(tc.Value)
+ applyOption := withOmitTime(tc.Value)
err := applyOption(opts)
require.NoError(t, err)
require.Equal(t, tc.ExpectedValue, opts.withOmitTime)
@@ -389,12 +389,12 @@ func TestOptions_Default(t *testing.T) {
require.False(t, opts.withNow.IsZero())
}
-// TestOptions_Opts exercises GetOpts with various Option values.
+// TestOptions_Opts exercises GetOpts with various option values.
func TestOptions_Opts(t *testing.T) {
t.Parallel()
tests := map[string]struct {
- opts []Option
+ opts []option
IsErrorExpected bool
ExpectedErrorMessage string
ExpectedID string
@@ -407,73 +407,73 @@ func TestOptions_Opts(t *testing.T) {
opts: nil,
IsErrorExpected: false,
IsNowExpected: true,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"empty-options": {
- opts: []Option{},
+ opts: []option{},
IsErrorExpected: false,
IsNowExpected: true,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"with-multiple-valid-id": {
- opts: []Option{
- WithID("qwerty"),
- WithID("juan"),
+ opts: []option{
+ withID("qwerty"),
+ withID("juan"),
},
IsErrorExpected: false,
ExpectedID: "juan",
IsNowExpected: true,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"with-multiple-valid-subtype": {
- opts: []Option{
- WithSubtype("AuditRequest"),
- WithSubtype("AuditResponse"),
+ opts: []option{
+ withSubtype("AuditRequest"),
+ withSubtype("AuditResponse"),
},
IsErrorExpected: false,
ExpectedSubtype: ResponseType,
IsNowExpected: true,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"with-multiple-valid-format": {
- opts: []Option{
- WithFormat("json"),
- WithFormat("jsonx"),
+ opts: []option{
+ withFormat("json"),
+ withFormat("jsonx"),
},
IsErrorExpected: false,
- ExpectedFormat: JSONxFormat,
+ ExpectedFormat: jsonxFormat,
IsNowExpected: true,
},
"with-multiple-valid-now": {
- opts: []Option{
- WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
- WithNow(time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local)),
+ opts: []option{
+ withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
+ withNow(time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local)),
},
IsErrorExpected: false,
ExpectedNow: time.Date(2023, time.July, 4, 13, 3, 0, 0, time.Local),
IsNowExpected: false,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"with-multiple-valid-then-invalid-now": {
- opts: []Option{
- WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
- WithNow(time.Time{}),
+ opts: []option{
+ withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
+ withNow(time.Time{}),
},
IsErrorExpected: true,
ExpectedErrorMessage: "cannot specify 'now' to be the zero time instant",
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
},
"with-multiple-valid-options": {
- opts: []Option{
- WithID("qwerty"),
- WithSubtype("AuditRequest"),
- WithFormat("json"),
- WithNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
+ opts: []option{
+ withID("qwerty"),
+ withSubtype("AuditRequest"),
+ withFormat("json"),
+ withNow(time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local)),
},
IsErrorExpected: false,
ExpectedID: "qwerty",
ExpectedSubtype: RequestType,
- ExpectedFormat: JSONFormat,
+ ExpectedFormat: jsonFormat,
ExpectedNow: time.Date(2023, time.July, 4, 12, 3, 0, 0, time.Local),
},
}
diff --git a/audit/sink_metric_labeler.go b/audit/sink_metric_labeler.go
index 1bd24be5a2..a433fe3257 100644
--- a/audit/sink_metric_labeler.go
+++ b/audit/sink_metric_labeler.go
@@ -24,6 +24,7 @@ type metricLabelerAuditSink struct{}
// Failure: 'vault.audit.sink.failure'
func (m metricLabelerAuditSink) Labels(_ *eventlogger.Event, err error) []string {
if err != nil {
+ // NOTE: a cancelled context would still result in an error.
return metricLabelAuditSinkFailure
}
diff --git a/audit/sink_metric_timer.go b/audit/sink_metric_timer.go
index cbb94d4f0a..461a6b3717 100644
--- a/audit/sink_metric_timer.go
+++ b/audit/sink_metric_timer.go
@@ -56,7 +56,7 @@ func newSinkMetricTimer(name string, sink eventlogger.Node) (*sinkMetricTimer, e
// 'vault.audit.{DEVICE}.log_response'
func (s *sinkMetricTimer) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
defer func() {
- auditEvent, ok := e.Payload.(*AuditEvent)
+ auditEvent, ok := e.Payload.(*Event)
if ok {
metrics.MeasureSince([]string{"audit", s.name, auditEvent.Subtype.MetricTag()}, e.CreatedAt)
}
diff --git a/audit/types.go b/audit/types.go
index 25652c7d03..f034c2e8ed 100644
--- a/audit/types.go
+++ b/audit/types.go
@@ -7,28 +7,20 @@ import (
"github.com/hashicorp/vault/sdk/logical"
)
-// RequestEntry is the structure of a request audit log entry.
-type RequestEntry struct {
- Auth *Auth `json:"auth,omitempty"`
- Error string `json:"error,omitempty"`
- ForwardedFrom string `json:"forwarded_from,omitempty"` // Populated in Enterprise when a request is forwarded
- Request *Request `json:"request,omitempty"`
- Time string `json:"time,omitempty"`
- Type string `json:"type,omitempty"`
+// entry represents an audit entry.
+// It could be an entry for a request or response.
+type entry struct {
+ Auth *auth `json:"auth,omitempty"`
+ Error string `json:"error,omitempty"`
+ Forwarded bool `json:"forwarded,omitempty"`
+ ForwardedFrom string `json:"forwarded_from,omitempty"` // Populated in Enterprise when a request is forwarded
+ Request *request `json:"request,omitempty"`
+ Response *response `json:"response,omitempty"`
+ Time string `json:"time,omitempty"`
+ Type string `json:"type,omitempty"`
}
-// ResponseEntry is the structure of a response audit log entry.
-type ResponseEntry struct {
- Auth *Auth `json:"auth,omitempty"`
- Error string `json:"error,omitempty"`
- Forwarded bool `json:"forwarded,omitempty"`
- Request *Request `json:"request,omitempty"`
- Response *Response `json:"response,omitempty"`
- Time string `json:"time,omitempty"`
- Type string `json:"type,omitempty"`
-}
-
-type Request struct {
+type request struct {
ClientCertificateSerialNumber string `json:"client_certificate_serial_number,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientToken string `json:"client_token,omitempty"`
@@ -43,7 +35,7 @@ type Request struct {
MountRunningSha256 string `json:"mount_running_sha256,omitempty"`
MountRunningVersion string `json:"mount_running_version,omitempty"`
MountType string `json:"mount_type,omitempty"`
- Namespace *Namespace `json:"namespace,omitempty"`
+ Namespace *namespace `json:"namespace,omitempty"`
Operation logical.Operation `json:"operation,omitempty"`
Path string `json:"path,omitempty"`
PolicyOverride bool `json:"policy_override,omitempty"`
@@ -54,8 +46,8 @@ type Request struct {
WrapTTL int `json:"wrap_ttl,omitempty"`
}
-type Response struct {
- Auth *Auth `json:"auth,omitempty"`
+type response struct {
+ Auth *auth `json:"auth,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
Headers map[string][]string `json:"headers,omitempty"`
MountAccessor string `json:"mount_accessor,omitempty"`
@@ -66,12 +58,12 @@ type Response struct {
MountRunningVersion string `json:"mount_running_plugin_version,omitempty"`
MountType string `json:"mount_type,omitempty"`
Redirect string `json:"redirect,omitempty"`
- Secret *Secret `json:"secret,omitempty"`
- WrapInfo *ResponseWrapInfo `json:"wrap_info,omitempty"`
+ Secret *secret `json:"secret,omitempty"`
+ WrapInfo *responseWrapInfo `json:"wrap_info,omitempty"`
Warnings []string `json:"warnings,omitempty"`
}
-type Auth struct {
+type auth struct {
Accessor string `json:"accessor,omitempty"`
ClientToken string `json:"client_token,omitempty"`
DisplayName string `json:"display_name,omitempty"`
@@ -83,7 +75,7 @@ type Auth struct {
NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
NumUses int `json:"num_uses,omitempty"`
Policies []string `json:"policies,omitempty"`
- PolicyResults *PolicyResults `json:"policy_results,omitempty"`
+ PolicyResults *policyResults `json:"policy_results,omitempty"`
RemainingUses int `json:"remaining_uses,omitempty"`
TokenPolicies []string `json:"token_policies,omitempty"`
TokenIssueTime string `json:"token_issue_time,omitempty"`
@@ -91,23 +83,23 @@ type Auth struct {
TokenType string `json:"token_type,omitempty"`
}
-type PolicyResults struct {
+type policyResults struct {
Allowed bool `json:"allowed"`
- GrantingPolicies []PolicyInfo `json:"granting_policies,omitempty"`
+ GrantingPolicies []policyInfo `json:"granting_policies,omitempty"`
}
-type PolicyInfo struct {
+type policyInfo struct {
Name string `json:"name,omitempty"`
NamespaceId string `json:"namespace_id,omitempty"`
NamespacePath string `json:"namespace_path,omitempty"`
Type string `json:"type"`
}
-type Secret struct {
+type secret struct {
LeaseID string `json:"lease_id,omitempty"`
}
-type ResponseWrapInfo struct {
+type responseWrapInfo struct {
Accessor string `json:"accessor,omitempty"`
CreationPath string `json:"creation_path,omitempty"`
CreationTime string `json:"creation_time,omitempty"`
@@ -116,7 +108,7 @@ type ResponseWrapInfo struct {
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
}
-type Namespace struct {
+type namespace struct {
ID string `json:"id,omitempty"`
Path string `json:"path,omitempty"`
}
diff --git a/builtin/credential/aws/backend_test.go b/builtin/credential/aws/backend_test.go
index 771dc0e311..5770b2c5ed 100644
--- a/builtin/credential/aws/backend_test.go
+++ b/builtin/credential/aws/backend_test.go
@@ -8,7 +8,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"os"
"strings"
@@ -1516,7 +1516,7 @@ func buildCallerIdentityLoginData(request *http.Request, roleName string) (map[s
if err != nil {
return nil, err
}
- requestBody, err := ioutil.ReadAll(request.Body)
+ requestBody, err := io.ReadAll(request.Body)
if err != nil {
return nil, err
}
diff --git a/builtin/credential/aws/client.go b/builtin/credential/aws/client.go
index cf2d39b7d8..5931984ca7 100644
--- a/builtin/credential/aws/client.go
+++ b/builtin/credential/aws/client.go
@@ -9,6 +9,8 @@ import (
"strconv"
"time"
+ "github.com/aws/aws-sdk-go/aws/credentials"
+
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/session"
@@ -130,7 +132,12 @@ func (b *backend) getClientConfig(ctx context.Context, s logical.Storage, region
if err != nil {
return nil, err
}
- assumedCredentials := stscreds.NewCredentials(sess, stsRole, func(p *stscreds.AssumeRoleProvider) { p.ExternalID = aws.String(externalID) })
+ var assumedCredentials *credentials.Credentials
+ if externalID != "" {
+ assumedCredentials = stscreds.NewCredentials(sess, stsRole, func(p *stscreds.AssumeRoleProvider) { p.ExternalID = aws.String(externalID) })
+ } else {
+ assumedCredentials = stscreds.NewCredentials(sess, stsRole)
+ }
// Test that we actually have permissions to assume the role
if _, err = assumedCredentials.Get(); err != nil {
return nil, err
diff --git a/builtin/credential/aws/path_login.go b/builtin/credential/aws/path_login.go
index a0e5a96505..fdb37da72b 100644
--- a/builtin/credential/aws/path_login.go
+++ b/builtin/credential/aws/path_login.go
@@ -12,7 +12,7 @@ import (
"encoding/xml"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"regexp"
@@ -1803,7 +1803,7 @@ func submitCallerIdentityRequest(ctx context.Context, maxRetries int, method, en
}
// we check for status code afterwards to also print out response body
- responseBody, err := ioutil.ReadAll(response.Body)
+ responseBody, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
}
diff --git a/builtin/credential/cert/backend.go b/builtin/credential/cert/backend.go
index d40a8de602..7c9b2ef55e 100644
--- a/builtin/credential/cert/backend.go
+++ b/builtin/credential/cert/backend.go
@@ -18,6 +18,7 @@ import (
"github.com/hashicorp/go-multierror"
lru "github.com/hashicorp/golang-lru/v2"
"github.com/hashicorp/vault/sdk/framework"
+ "github.com/hashicorp/vault/sdk/helper/locksutil"
"github.com/hashicorp/vault/sdk/helper/ocsp"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -28,7 +29,7 @@ const (
defaultRoleCacheSize = 200
defaultOcspMaxRetries = 4
- maxRoleCacheSize = 10000
+ maxRoleCacheSize = 100000
)
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
@@ -43,7 +44,8 @@ func Backend() *backend {
// ignoring the error as it only can occur with <= 0 size
cache, _ := lru.New[string, *trusted](defaultRoleCacheSize)
b := backend{
- trustedCache: cache,
+ trustedCache: cache,
+ trustedCacheLocks: locksutil.CreateLocks(),
}
b.Backend = &framework.Backend{
Help: backendHelp,
@@ -90,6 +92,8 @@ type backend struct {
trustedCache *lru.Cache[string, *trusted]
trustedCacheDisabled atomic.Bool
+ trustedCacheLocks []*locksutil.LockEntry
+ trustedCacheFull atomic.Pointer[trusted]
}
func (b *backend) initialize(ctx context.Context, req *logical.InitializationRequest) error {
@@ -137,7 +141,7 @@ func (b *backend) updatedConfig(config *config) {
case config.RoleCacheSize < 0:
// Just to clean up memory
b.trustedCacheDisabled.Store(true)
- b.trustedCache.Purge()
+ b.flushTrustedCache()
case config.RoleCacheSize == 0:
config.RoleCacheSize = defaultRoleCacheSize
fallthrough
@@ -200,6 +204,7 @@ func (b *backend) flushTrustedCache() {
if b.trustedCache != nil { // defensive
b.trustedCache.Purge()
}
+ b.trustedCacheFull.Store(nil)
}
const backendHelp = `
diff --git a/builtin/credential/cert/backend_test.go b/builtin/credential/cert/backend_test.go
index 6260c368e8..e4affa3b52 100644
--- a/builtin/credential/cert/backend_test.go
+++ b/builtin/credential/cert/backend_test.go
@@ -843,7 +843,7 @@ func TestBackend_NonCAExpiry(t *testing.T) {
time.Sleep(5 * time.Second)
// Login attempt after certificate expiry should fail
- resp, err = b.HandleRequest(context.Background(), loginReq)
+ _, err = b.HandleRequest(context.Background(), loginReq)
if err == nil {
t.Fatalf("expected error due to expired certificate")
}
@@ -2178,12 +2178,13 @@ func Test_Renew(t *testing.T) {
Raw: map[string]interface{}{
"name": "test",
"certificate": ca,
- "policies": "foo,bar",
+ // Uppercase B should not cause an issue during renewal
+ "token_policies": "foo,Bar",
},
Schema: pathCerts(b).Fields,
}
- resp, err := b.pathCertWrite(context.Background(), req, fd)
+ _, err = b.pathCertWrite(context.Background(), req, fd)
if err != nil {
t.Fatal(err)
}
@@ -2192,7 +2193,7 @@ func Test_Renew(t *testing.T) {
Raw: map[string]interface{}{},
Schema: pathLogin(b).Fields,
}
- resp, err = b.pathLogin(context.Background(), req, empty_login_fd)
+ resp, err := b.pathLogin(context.Background(), req, empty_login_fd)
if err != nil {
t.Fatal(err)
}
@@ -2219,20 +2220,20 @@ func Test_Renew(t *testing.T) {
}
// Change the policies -- this should fail
- fd.Raw["policies"] = "zip,zap"
- resp, err = b.pathCertWrite(context.Background(), req, fd)
+ fd.Raw["token_policies"] = "zip,zap"
+ _, err = b.pathCertWrite(context.Background(), req, fd)
if err != nil {
t.Fatal(err)
}
- resp, err = b.pathLoginRenew(context.Background(), req, empty_login_fd)
+ _, err = b.pathLoginRenew(context.Background(), req, empty_login_fd)
if err == nil {
t.Fatal("expected error")
}
// Put the policies back, this should be okay
- fd.Raw["policies"] = "bar,foo"
- resp, err = b.pathCertWrite(context.Background(), req, fd)
+ fd.Raw["token_policies"] = "bar,foo"
+ _, err = b.pathCertWrite(context.Background(), req, fd)
if err != nil {
t.Fatal(err)
}
@@ -2251,7 +2252,7 @@ func Test_Renew(t *testing.T) {
// Add period value to cert entry
period := 350 * time.Second
fd.Raw["period"] = period.String()
- resp, err = b.pathCertWrite(context.Background(), req, fd)
+ _, err = b.pathCertWrite(context.Background(), req, fd)
if err != nil {
t.Fatal(err)
}
@@ -2272,7 +2273,7 @@ func Test_Renew(t *testing.T) {
}
// Delete CA, make sure we can't renew
- resp, err = b.pathCertDelete(context.Background(), req, fd)
+ _, err = b.pathCertDelete(context.Background(), req, fd)
if err != nil {
t.Fatal(err)
}
diff --git a/builtin/credential/cert/path_login.go b/builtin/credential/cert/path_login.go
index 33f62818ec..d0476118e3 100644
--- a/builtin/credential/cert/path_login.go
+++ b/builtin/credential/cert/path_login.go
@@ -17,6 +17,8 @@ import (
"net/url"
"strings"
+ "github.com/hashicorp/vault/sdk/helper/locksutil"
+
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/framework"
@@ -34,6 +36,8 @@ type ParsedCert struct {
Certificates []*x509.Certificate
}
+const certAuthFailMsg = "failed to match all constraints for this login certificate"
+
func pathLogin(b *backend) *framework.Path {
return &framework.Path{
Pattern: "login",
@@ -312,10 +316,11 @@ func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, d
// If no trusted chain was found, client is not authenticated
// This check happens after checking for a matching configured non-CA certs
if len(trustedChains) == 0 {
- if retErr == nil {
- return nil, logical.ErrorResponse(fmt.Sprintf("invalid certificate or no client certificate supplied; additionally got errors during verification: %v", retErr)), nil
+ if retErr != nil {
+ return nil, logical.ErrorResponse(fmt.Sprintf("%s; additionally got errors during verification: %v", certAuthFailMsg, retErr)), nil
}
- return nil, logical.ErrorResponse("invalid certificate or no client certificate supplied"), nil
+
+ return nil, logical.ErrorResponse(certAuthFailMsg), nil
}
// Search for a ParsedCert that intersects with the validated chains and any additional constraints
@@ -350,10 +355,10 @@ func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, d
}
if retErr != nil {
- return nil, logical.ErrorResponse(fmt.Sprintf("no chain matching all constraints could be found for this login certificate; additionally got errors during verification: %v", retErr)), nil
+ return nil, logical.ErrorResponse(fmt.Sprintf("%s; additionally got errors during verification: %v", certAuthFailMsg, retErr)), nil
}
- return nil, logical.ErrorResponse("no chain matching all constraints could be found for this login certificate"), nil
+ return nil, logical.ErrorResponse(certAuthFailMsg), nil
}
func (b *backend) matchesConstraints(ctx context.Context, clientCert *x509.Certificate, trustedChain []*x509.Certificate,
@@ -593,15 +598,39 @@ func (b *backend) certificateExtensionsMetadata(clientCert *x509.Certificate, co
func (b *backend) getTrustedCerts(ctx context.Context, storage logical.Storage, certName string) (pool *x509.CertPool, trusted []*ParsedCert, trustedNonCAs []*ParsedCert, conf *ocsp.VerifyConfig) {
if !b.trustedCacheDisabled.Load() {
- if trusted, found := b.trustedCache.Get(certName); found {
+ trusted, found := b.getTrustedCertsFromCache(certName)
+ if found {
return trusted.pool, trusted.trusted, trusted.trustedNonCAs, trusted.ocspConf
}
}
return b.loadTrustedCerts(ctx, storage, certName)
}
+func (b *backend) getTrustedCertsFromCache(certName string) (*trusted, bool) {
+ if certName == "" {
+ trusted := b.trustedCacheFull.Load()
+ if trusted != nil {
+ return trusted, true
+ }
+ } else if trusted, found := b.trustedCache.Get(certName); found {
+ return trusted, true
+ }
+ return nil, false
+}
+
// loadTrustedCerts is used to load all the trusted certificates from the backend
func (b *backend) loadTrustedCerts(ctx context.Context, storage logical.Storage, certName string) (pool *x509.CertPool, trustedCerts []*ParsedCert, trustedNonCAs []*ParsedCert, conf *ocsp.VerifyConfig) {
+ lock := locksutil.LockForKey(b.trustedCacheLocks, certName)
+ lock.Lock()
+ defer lock.Unlock()
+
+ if !b.trustedCacheDisabled.Load() {
+ trusted, found := b.getTrustedCertsFromCache(certName)
+ if found {
+ return trusted.pool, trusted.trusted, trusted.trustedNonCAs, trusted.ocspConf
+ }
+ }
+
pool = x509.NewCertPool()
trustedCerts = make([]*ParsedCert, 0)
trustedNonCAs = make([]*ParsedCert, 0)
@@ -669,12 +698,17 @@ func (b *backend) loadTrustedCerts(ctx context.Context, storage logical.Storage,
}
if !b.trustedCacheDisabled.Load() {
- b.trustedCache.Add(certName, &trusted{
+ entry := &trusted{
pool: pool,
trusted: trustedCerts,
trustedNonCAs: trustedNonCAs,
ocspConf: conf,
- })
+ }
+ if certName == "" {
+ b.trustedCacheFull.Store(entry)
+ } else {
+ b.trustedCache.Add(certName, entry)
+ }
}
return
}
diff --git a/builtin/credential/cert/path_login_test.go b/builtin/credential/cert/path_login_test.go
index 508c20b157..51d670ce8c 100644
--- a/builtin/credential/cert/path_login_test.go
+++ b/builtin/credential/cert/path_login_test.go
@@ -202,7 +202,7 @@ func testAccStepResolveRoleExpectRoleResolutionToFail(t *testing.T, connState tl
t.Fatal("Error not part of response.")
}
- if !strings.Contains(errString, "invalid certificate") {
+ if !strings.Contains(errString, certAuthFailMsg) {
t.Fatalf("Error was not due to invalid role name. Error: %s", errString)
}
return nil
@@ -230,7 +230,7 @@ func testAccStepResolveRoleOCSPFail(t *testing.T, connState tls.ConnectionState,
t.Fatal("Error not part of response.")
}
- if !strings.Contains(errString, "no chain matching") {
+ if !strings.Contains(errString, certAuthFailMsg) {
t.Fatalf("Error was not due to OCSP failure. Error: %s", errString)
}
return nil
diff --git a/builtin/credential/cert/test_responder.go b/builtin/credential/cert/test_responder.go
index 2052736d33..56fb4727be 100644
--- a/builtin/credential/cert/test_responder.go
+++ b/builtin/credential/cert/test_responder.go
@@ -19,7 +19,7 @@ import (
"encoding/base64"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"time"
@@ -168,7 +168,7 @@ func (rs *Responder) ServeHTTP(response http.ResponseWriter, request *http.Reque
return
}
case "POST":
- requestBody, err = ioutil.ReadAll(request.Body)
+ requestBody, err = io.ReadAll(request.Body)
if err != nil {
rs.log.Log("Problem reading body of POST", err)
response.WriteHeader(http.StatusBadRequest)
diff --git a/builtin/logical/aws/backend_test.go b/builtin/logical/aws/backend_test.go
index b5376f6468..56cd095a3b 100644
--- a/builtin/logical/aws/backend_test.go
+++ b/builtin/logical/aws/backend_test.go
@@ -36,6 +36,23 @@ import (
var initSetup sync.Once
+// This looks a bit curious. The policy document and the role document act
+// as a logical intersection of policies. The role allows ec2:Describe*
+// (among other permissions). This policy allows everything BUT
+// ec2:DescribeAvailabilityZones. Thus, the logical intersection of the two
+// is all ec2:Describe* EXCEPT ec2:DescribeAvailabilityZones, and so the
+// describeAZs call should fail
+const allowAllButDescribeAzs = `{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "NotAction": "ec2:DescribeAvailabilityZones",
+ "Resource": "*"
+ }
+ ]
+}`
+
type mockIAMClient struct {
iamiface.IAMAPI
}
@@ -97,7 +114,7 @@ func TestAcceptanceBackend_basicSTS(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
createUser(t, userName, accessKey)
- createRole(t, roleName, awsAccountID, []string{ec2PolicyArn})
+ createRole(t, roleName, awsAccountID, []string{ec2PolicyArn}, nil)
// Sleep sometime because AWS is eventually consistent
// Both the createUser and createRole depend on this
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
@@ -123,7 +140,8 @@ func TestAcceptanceBackend_basicSTS(t *testing.T) {
})
}
-func TestBackend_policyCrud(t *testing.T) {
+// TestBackend_policyCRUD tests the CRUD operations for a policy.
+func TestBackend_policyCRUD(t *testing.T) {
t.Parallel()
compacted, err := compactJSON(testDynamoPolicy)
if err != nil {
@@ -252,23 +270,32 @@ func getAccountID() (string, error) {
return *res.Account, nil
}
-func createRole(t *testing.T, roleName, awsAccountID string, policyARNs []string) {
- const testRoleAssumePolicy = `{
+func createRole(t *testing.T, roleName, awsAccountID string, policyARNs, extraTrustPolicies []string) {
+ t.Helper()
+
+ trustPolicyStmts := append([]string{
+ fmt.Sprintf(`
+ {
+ "Effect":"Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::%s:root"
+ },
+ "Action": [
+ "sts:AssumeRole",
+ "sts:SetSourceIdentity"
+ ]
+ }`, awsAccountID),
+ },
+ extraTrustPolicies...)
+
+ testRoleAssumePolicy := fmt.Sprintf(`{
"Version": "2012-10-17",
"Statement": [
- {
- "Effect":"Allow",
- "Principal": {
- "AWS": "arn:aws:iam::%s:root"
- },
- "Action": [
- "sts:AssumeRole",
- "sts:SetSourceIdentity"
- ]
- }
+%s
]
}
-`
+`, strings.Join(trustPolicyStmts, ","))
+
awsConfig := &aws.Config{
Region: aws.String("us-east-1"),
HTTPClient: cleanhttp.DefaultClient(),
@@ -278,23 +305,23 @@ func createRole(t *testing.T, roleName, awsAccountID string, policyARNs []string
t.Fatal(err)
}
svc := iam.New(sess)
- trustPolicy := fmt.Sprintf(testRoleAssumePolicy, awsAccountID)
params := &iam.CreateRoleInput{
- AssumeRolePolicyDocument: aws.String(trustPolicy),
+ AssumeRolePolicyDocument: aws.String(testRoleAssumePolicy),
RoleName: aws.String(roleName),
Path: aws.String("/"),
}
log.Printf("[INFO] AWS CreateRole: %s", roleName)
- if _, err := svc.CreateRole(params); err != nil {
+ output, err := svc.CreateRole(params)
+ if err != nil {
t.Fatalf("AWS CreateRole failed: %v", err)
}
for _, policyARN := range policyARNs {
attachment := &iam.AttachRolePolicyInput{
PolicyArn: aws.String(policyARN),
- RoleName: aws.String(roleName), // Required
+ RoleName: output.Role.RoleName,
}
_, err = svc.AttachRolePolicy(attachment)
if err != nil {
@@ -315,21 +342,21 @@ func createUser(t *testing.T, userName string, accessKey *awsAccessKey) {
// do anything
// 4. Generate API creds to get an actual access key and secret key
timebombPolicyTemplate := `{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Deny",
- "Action": "*",
- "Resource": "*",
- "Condition": {
- "DateGreaterThan": {
- "aws:CurrentTime": "%s"
- }
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Deny",
+ "Action": "*",
+ "Resource": "*",
+ "Condition": {
+ "DateGreaterThan": {
+ "aws:CurrentTime": "%s"
}
}
- ]
- }
- `
+ }
+ ]
+}
+`
validity := time.Duration(2 * time.Hour)
expiry := time.Now().Add(validity)
timebombPolicy := fmt.Sprintf(timebombPolicyTemplate, expiry.Format(time.RFC3339))
@@ -657,7 +684,7 @@ func testAccStepRotateRoot(oldAccessKey *awsAccessKey) logicaltest.TestStep {
}
}
-func testAccStepRead(t *testing.T, path, name string, credentialTests []credentialTestFunc) logicaltest.TestStep {
+func testAccStepRead(_ *testing.T, path, name string, credentialTests []credentialTestFunc) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.ReadOperation,
Path: path + "/" + name,
@@ -909,6 +936,8 @@ func testAccStepReadPolicy(t *testing.T, name string, value string) logicaltest.
"iam_groups": []string(nil),
"iam_tags": map[string]string(nil),
"mfa_serial_number": "",
+ "session_tags": map[string]string(nil),
+ "external_id": "",
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
@@ -1107,22 +1136,7 @@ func TestAcceptanceBackend_iamUserGroups(t *testing.T) {
func TestAcceptanceBackend_AssumedRoleWithPolicyDoc(t *testing.T) {
t.Parallel()
roleName := generateUniqueRoleName(t.Name())
- // This looks a bit curious. The policy document and the role document act
- // as a logical intersection of policies. The role allows ec2:Describe*
- // (among other permissions). This policy allows everything BUT
- // ec2:DescribeAvailabilityZones. Thus, the logical intersection of the two
- // is all ec2:Describe* EXCEPT ec2:DescribeAvailabilityZones, and so the
- // describeAZs call should fail
- allowAllButDescribeAzs := `
-{
- "Version": "2012-10-17",
- "Statement": [{
- "Effect": "Allow",
- "NotAction": "ec2:DescribeAvailabilityZones",
- "Resource": "*"
- }]
-}
-`
+
awsAccountID, err := getAccountID()
if err != nil {
t.Logf("Unable to retrive user via sts:GetCallerIdentity: %#v", err)
@@ -1137,7 +1151,7 @@ func TestAcceptanceBackend_AssumedRoleWithPolicyDoc(t *testing.T) {
AcceptanceTest: true,
PreCheck: func() {
testAccPreCheck(t)
- createRole(t, roleName, awsAccountID, []string{ec2PolicyArn})
+ createRole(t, roleName, awsAccountID, []string{ec2PolicyArn}, nil)
// Sleep sometime because AWS is eventually consistent
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
time.Sleep(10 * time.Second)
@@ -1173,7 +1187,7 @@ func TestAcceptanceBackend_AssumedRoleWithPolicyARN(t *testing.T) {
AcceptanceTest: true,
PreCheck: func() {
testAccPreCheck(t)
- createRole(t, roleName, awsAccountID, []string{ec2PolicyArn, iamPolicyArn})
+ createRole(t, roleName, awsAccountID, []string{ec2PolicyArn, iamPolicyArn}, nil)
log.Printf("[WARN] Sleeping for 10 seconds waiting for AWS...")
time.Sleep(10 * time.Second)
},
@@ -1194,22 +1208,7 @@ func TestAcceptanceBackend_AssumedRoleWithGroups(t *testing.T) {
t.Parallel()
roleName := generateUniqueRoleName(t.Name())
groupName := generateUniqueGroupName(t.Name())
- // This looks a bit curious. The policy document and the role document act
- // as a logical intersection of policies. The role allows ec2:Describe*
- // (among other permissions). This policy allows everything BUT
- // ec2:DescribeAvailabilityZones. Thus, the logical intersection of the two
- // is all ec2:Describe* EXCEPT ec2:DescribeAvailabilityZones, and so the
- // describeAZs call should fail
- allowAllButDescribeAzs := `{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "NotAction": "ec2:DescribeAvailabilityZones",
- "Resource": "*"
- }
- ]
-}`
+
awsAccountID, err := getAccountID()
if err != nil {
t.Logf("Unable to retrive user via sts:GetCallerIdentity: %#v", err)
@@ -1225,7 +1224,7 @@ func TestAcceptanceBackend_AssumedRoleWithGroups(t *testing.T) {
AcceptanceTest: true,
PreCheck: func() {
testAccPreCheck(t)
- createRole(t, roleName, awsAccountID, []string{ec2PolicyArn})
+ createRole(t, roleName, awsAccountID, []string{ec2PolicyArn}, nil)
createGroup(t, groupName, allowAllButDescribeAzs, []string{})
// Sleep sometime because AWS is eventually consistent
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
@@ -1247,6 +1246,62 @@ func TestAcceptanceBackend_AssumedRoleWithGroups(t *testing.T) {
})
}
+// TestAcceptanceBackend_AssumedRoleWithSessionTags tests that session tags are
+// passed to the assumed role.
+func TestAcceptanceBackend_AssumedRoleWithSessionTags(t *testing.T) {
+ t.Parallel()
+ roleName := generateUniqueRoleName(t.Name())
+ awsAccountID, err := getAccountID()
+ if err != nil {
+ t.Logf("Unable to retrive user via sts:GetCallerIdentity: %#v", err)
+ t.Skip("Could not determine AWS account ID from sts:GetCallerIdentity for acceptance tests, skipping")
+ }
+
+ roleARN := fmt.Sprintf("arn:aws:iam::%s:role/%s", awsAccountID, roleName)
+ roleData := map[string]interface{}{
+ "policy_document": allowAllButDescribeAzs,
+ "role_arns": []string{roleARN},
+ "credential_type": assumedRoleCred,
+ "session_tags": map[string]string{
+ "foo": "bar",
+ "baz": "qux",
+ },
+ }
+
+ // allowSessionTagsPolicy allows the role to tag the session, it needs to be
+ // included in the trust policy.
+ allowSessionTagsPolicy := fmt.Sprintf(`
+ {
+ "Sid": "AllowPassSessionTagsAndTransitive",
+ "Effect": "Allow",
+ "Action": "sts:TagSession",
+ "Principal": {
+ "AWS": "arn:aws:iam::%s:root"
+ }
+ }
+`, awsAccountID)
+
+ logicaltest.Test(t, logicaltest.TestCase{
+ AcceptanceTest: true,
+ PreCheck: func() {
+ testAccPreCheck(t)
+ createRole(t, roleName, awsAccountID, []string{ec2PolicyArn}, []string{allowSessionTagsPolicy})
+ log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
+ time.Sleep(10 * time.Second)
+ },
+ LogicalBackend: getBackend(t),
+ Steps: []logicaltest.TestStep{
+ testAccStepConfig(t),
+ testAccStepWriteRole(t, "test", roleData),
+ testAccStepRead(t, "sts", "test", []credentialTestFunc{describeInstancesTest, describeAzsTestUnauthorized}),
+ testAccStepRead(t, "creds", "test", []credentialTestFunc{describeInstancesTest, describeAzsTestUnauthorized}),
+ },
+ Teardown: func() error {
+ return deleteTestRole(roleName)
+ },
+ })
+}
+
func TestAcceptanceBackend_FederationTokenWithPolicyARN(t *testing.T) {
t.Parallel()
userName := generateUniqueUserName(t.Name())
@@ -1328,6 +1383,7 @@ func TestAcceptanceBackend_FederationTokenWithGroups(t *testing.T) {
})
}
+// TestAcceptanceBackend_SessionToken
func TestAcceptanceBackend_SessionToken(t *testing.T) {
t.Parallel()
userName := generateUniqueUserName(t.Name())
@@ -1427,7 +1483,7 @@ func TestAcceptanceBackend_RoleDefaultSTSTTL(t *testing.T) {
AcceptanceTest: true,
PreCheck: func() {
testAccPreCheck(t)
- createRole(t, roleName, awsAccountID, []string{ec2PolicyArn})
+ createRole(t, roleName, awsAccountID, []string{ec2PolicyArn}, nil)
log.Println("[WARN] Sleeping for 10 seconds waiting for AWS...")
time.Sleep(10 * time.Second)
},
@@ -1443,7 +1499,8 @@ func TestAcceptanceBackend_RoleDefaultSTSTTL(t *testing.T) {
})
}
-func TestBackend_policyArnCrud(t *testing.T) {
+// TestBackend_policyArnCRUD test the CRUD operations for policy ARNs.
+func TestBackend_policyArnCRUD(t *testing.T) {
t.Parallel()
logicaltest.Test(t, logicaltest.TestCase{
AcceptanceTest: false,
@@ -1483,6 +1540,8 @@ func testAccStepReadArnPolicy(t *testing.T, name string, value string) logicalte
"iam_groups": []string(nil),
"iam_tags": map[string]string(nil),
"mfa_serial_number": "",
+ "session_tags": map[string]string(nil),
+ "external_id": "",
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
@@ -1503,7 +1562,8 @@ func testAccStepWriteArnRoleRef(t *testing.T, vaultRoleName, awsRoleName, awsAcc
}
}
-func TestBackend_iamGroupsCrud(t *testing.T) {
+// TestBackend_iamGroupsCRUD tests CRUD operations for IAM groups.
+func TestBackend_iamGroupsCRUD(t *testing.T) {
t.Parallel()
logicaltest.Test(t, logicaltest.TestCase{
AcceptanceTest: false,
@@ -1554,6 +1614,8 @@ func testAccStepReadIamGroups(t *testing.T, name string, groups []string) logica
"iam_groups": groups,
"iam_tags": map[string]string(nil),
"mfa_serial_number": "",
+ "session_tags": map[string]string(nil),
+ "external_id": "",
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
@@ -1564,7 +1626,8 @@ func testAccStepReadIamGroups(t *testing.T, name string, groups []string) logica
}
}
-func TestBackend_iamTagsCrud(t *testing.T) {
+// TestBackend_iamTagsCRUD tests the CRUD operations for IAM tags.
+func TestBackend_iamTagsCRUD(t *testing.T) {
logicaltest.Test(t, logicaltest.TestCase{
AcceptanceTest: false,
LogicalBackend: getBackend(t),
@@ -1614,6 +1677,176 @@ func testAccStepReadIamTags(t *testing.T, name string, tags map[string]string) l
"iam_groups": []string(nil),
"iam_tags": tags,
"mfa_serial_number": "",
+ "session_tags": map[string]string(nil),
+ "external_id": "",
+ }
+ if !reflect.DeepEqual(resp.Data, expected) {
+ return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
+ }
+
+ return nil
+ },
+ }
+}
+
+// TestBackend_stsSessionTagsCRUD tests the CRUD operations for STS session tags.
+func TestBackend_stsSessionTagsCRUD(t *testing.T) {
+ t.Parallel()
+
+ tagParams0 := map[string]string{"tag1": "value1", "tag2": "value2"}
+ tagParams1 := map[string]string{"tag1": "value1", "tag2": "value4", "tag3": "value3"}
+
+ // list of tags in the form of "key=value"
+ tagParamsList0 := []string{"key1=value1", "key2=value2"}
+ tagParamsList0Expect := map[string]string{"key1": "value1", "key2": "value2"}
+ tagParamsList1 := []string{"key1=value2", "key3=value4"}
+ tagParamsList1Expect := map[string]string{"key1": "value2", "key3": "value4"}
+
+ type testCase struct {
+ name string
+ expectTags []map[string]string
+ tagsParams []any
+ externalIDs []string
+ }
+
+ for _, tt := range []testCase{
+ {
+ name: "mapped-only",
+ tagsParams: []any{
+ tagParams0,
+ map[string]string{},
+ tagParams1,
+ },
+ expectTags: []map[string]string{
+ tagParams0,
+ {},
+ tagParams1,
+ },
+ externalIDs: []string{"foo", "", "bar"},
+ },
+ {
+ name: "string-list-only",
+ tagsParams: []any{
+ tagParamsList0,
+ tagParamsList1,
+ },
+ expectTags: []map[string]string{
+ tagParamsList0Expect,
+ tagParamsList1Expect,
+ },
+ externalIDs: []string{"foo"},
+ },
+ {
+ name: "mixed-param-types",
+ tagsParams: []any{
+ tagParams0,
+ tagParamsList0,
+ tagParams1,
+ tagParamsList1,
+ },
+ expectTags: []map[string]string{
+ tagParams0,
+ tagParamsList0Expect,
+ tagParams1,
+ tagParamsList1Expect,
+ },
+ externalIDs: []string{"foo", "bar"},
+ },
+ {
+ name: "unset-tags",
+ tagsParams: []any{
+ tagParams0,
+ map[string]string{},
+ },
+ expectTags: []map[string]string{
+ tagParams0,
+ {},
+ },
+ },
+ } {
+ t.Run(tt.name, func(t *testing.T) {
+ steps := []logicaltest.TestStep{
+ testAccStepConfig(t),
+ }
+
+ if len(tt.tagsParams) != len(tt.expectTags) {
+ t.Fatalf("invalid test case: test case params and expect must have the same length")
+ }
+
+ // lastNonEmptyExternalID is used to store the last non-empty external ID for the
+ // test case. The value will is expected to be set on the role. Setting the value
+ // to an empty string has no effect on update operations.
+ var lastNonEmptyExternalID string
+ for idx, params := range tt.tagsParams {
+ var externalID string
+ if len(tt.externalIDs) > idx {
+ externalID = tt.externalIDs[idx]
+ }
+ if externalID != "" {
+ lastNonEmptyExternalID = externalID
+ }
+ steps = append(steps, testAccStepWriteSTSSessionTags(t, tt.name, params, externalID))
+ steps = append(steps, testAccStepReadSTSSessionTags(t, tt.name, tt.expectTags[idx], lastNonEmptyExternalID, false))
+ }
+ steps = append(
+ steps,
+ testAccStepDeletePolicy(t, tt.name),
+ testAccStepReadSTSSessionTags(t, tt.name, nil, "", true),
+ )
+ logicaltest.Test(t, logicaltest.TestCase{
+ AcceptanceTest: false,
+ LogicalBackend: getBackend(t),
+ Steps: steps,
+ })
+ })
+ }
+}
+
+func testAccStepWriteSTSSessionTags(t *testing.T, name string, tags any, externalID string) logicaltest.TestStep {
+ t.Helper()
+
+ data := map[string]interface{}{
+ "credential_type": assumedRoleCred,
+ "session_tags": tags,
+ }
+ if externalID != "" {
+ data["external_id"] = externalID
+ }
+ return logicaltest.TestStep{
+ Operation: logical.UpdateOperation,
+ Path: "roles/" + name,
+ Data: data,
+ }
+}
+
+func testAccStepReadSTSSessionTags(t *testing.T, name string, tags any, externalID string, expectNilResp bool) logicaltest.TestStep {
+ t.Helper()
+
+ return logicaltest.TestStep{
+ Operation: logical.ReadOperation,
+ Path: "roles/" + name,
+ Check: func(resp *logical.Response) error {
+ if resp == nil {
+ if expectNilResp {
+ return nil
+ }
+ return fmt.Errorf("vault response not received")
+ }
+
+ expected := map[string]interface{}{
+ "policy_arns": []string(nil),
+ "role_arns": []string(nil),
+ "policy_document": "",
+ "credential_type": assumedRoleCred,
+ "default_sts_ttl": int64(0),
+ "max_sts_ttl": int64(0),
+ "user_path": "",
+ "permissions_boundary_arn": "",
+ "iam_groups": []string(nil),
+ "iam_tags": map[string]string(nil),
+ "mfa_serial_number": "",
+ "session_tags": tags,
+ "external_id": externalID,
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
diff --git a/builtin/logical/aws/path_roles.go b/builtin/logical/aws/path_roles.go
index abf24a072e..1c1ef3546a 100644
--- a/builtin/logical/aws/path_roles.go
+++ b/builtin/logical/aws/path_roles.go
@@ -115,7 +115,23 @@ delimited key pairs.`,
Value: "[key1=value1, key2=value2]",
},
},
-
+ "session_tags": {
+ Type: framework.TypeKVPairs,
+ Description: fmt.Sprintf(`Session tags to be set for %q creds created by this role. These must be presented
+as Key-Value pairs. This can be represented as a map or a list of equal sign
+delimited key pairs.`, assumedRoleCred),
+ DisplayAttrs: &framework.DisplayAttributes{
+ Name: "Session Tags",
+ Value: "[key1=value1, key2=value2]",
+ },
+ },
+ "external_id": {
+ Type: framework.TypeString,
+ Description: "External ID to set when assuming the role; only valid when credential_type is " + assumedRoleCred,
+ DisplayAttrs: &framework.DisplayAttributes{
+ Name: "External ID",
+ },
+ },
"default_sts_ttl": {
Type: framework.TypeDurationSecond,
Description: fmt.Sprintf("Default TTL for %s, %s, and %s credential types when no TTL is explicitly requested with the credentials", assumedRoleCred, federationTokenCred, sessionTokenCred),
@@ -341,6 +357,14 @@ func (b *backend) pathRolesWrite(ctx context.Context, req *logical.Request, d *f
roleEntry.SerialNumber = serialNumber.(string)
}
+ if sessionTags, ok := d.GetOk("session_tags"); ok {
+ roleEntry.SessionTags = sessionTags.(map[string]string)
+ }
+
+ if externalID, ok := d.GetOk("external_id"); ok {
+ roleEntry.ExternalID = externalID.(string)
+ }
+
if legacyRole != "" {
roleEntry = upgradeLegacyPolicyEntry(legacyRole)
if roleEntry.InvalidData != "" {
@@ -527,6 +551,8 @@ type awsRoleEntry struct {
PolicyDocument string `json:"policy_document"` // JSON-serialized inline policy to attach to IAM users and/or to specify as the Policy parameter in AssumeRole calls
IAMGroups []string `json:"iam_groups"` // Names of IAM groups that generated IAM users will be added to
IAMTags map[string]string `json:"iam_tags"` // IAM tags that will be added to the generated IAM users
+ SessionTags map[string]string `json:"session_tags"` // Session tags that will be added as Tags parameter in AssumedRole calls
+ ExternalID string `json:"external_id"` // External ID to added as ExternalID in AssumeRole calls
InvalidData string `json:"invalid_data,omitempty"` // Invalid role data. Exists to support converting the legacy role data into the new format
ProhibitFlexibleCredPath bool `json:"prohibit_flexible_cred_path,omitempty"` // Disallow accessing STS credentials via the creds path and vice verse
Version int `json:"version"` // Version number of the role format
@@ -545,6 +571,8 @@ func (r *awsRoleEntry) toResponseData() map[string]interface{} {
"policy_document": r.PolicyDocument,
"iam_groups": r.IAMGroups,
"iam_tags": r.IAMTags,
+ "session_tags": r.SessionTags,
+ "external_id": r.ExternalID,
"default_sts_ttl": int64(r.DefaultSTSTTL.Seconds()),
"max_sts_ttl": int64(r.MaxSTSTTL.Seconds()),
"user_path": r.UserPath,
@@ -612,6 +640,14 @@ func (r *awsRoleEntry) validate() error {
errors = multierror.Append(errors, fmt.Errorf("cannot supply role_arns when credential_type isn't %s", assumedRoleCred))
}
+ if len(r.SessionTags) > 0 && !strutil.StrListContains(r.CredentialTypes, assumedRoleCred) {
+ errors = multierror.Append(errors, fmt.Errorf("cannot supply session_tags when credential_type isn't %s", assumedRoleCred))
+ }
+
+ if r.ExternalID != "" && !strutil.StrListContains(r.CredentialTypes, assumedRoleCred) {
+ errors = multierror.Append(errors, fmt.Errorf("cannot supply external_id when credential_type isn't %s", assumedRoleCred))
+ }
+
return errors.ErrorOrNil()
}
diff --git a/builtin/logical/aws/path_roles_test.go b/builtin/logical/aws/path_roles_test.go
index 32d65da7bb..80328cc5f0 100644
--- a/builtin/logical/aws/path_roles_test.go
+++ b/builtin/logical/aws/path_roles_test.go
@@ -5,11 +5,13 @@ package aws
import (
"context"
+ "errors"
"reflect"
"strconv"
"strings"
"testing"
+ "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -366,22 +368,74 @@ func TestRoleEntryValidationIamUserCred(t *testing.T) {
CredentialTypes: []string{iamUserCred},
RoleArns: []string{"arn:aws:iam::123456789012:role/SomeRole"},
}
- if roleEntry.validate() == nil {
- t.Errorf("bad: invalid roleEntry with invalid RoleArns parameter %#v passed validation", roleEntry)
- }
+ assertMultiError(t, roleEntry.validate(),
+ []error{
+ errors.New(
+ "cannot supply role_arns when credential_type isn't assumed_role",
+ ),
+ })
roleEntry = awsRoleEntry{
CredentialTypes: []string{iamUserCred},
PolicyArns: []string{adminAccessPolicyARN},
DefaultSTSTTL: 1,
}
- if roleEntry.validate() == nil {
- t.Errorf("bad: invalid roleEntry with unrecognized DefaultSTSTTL %#v passed validation", roleEntry)
- }
+ assertMultiError(t, roleEntry.validate(),
+ []error{
+ errors.New(
+ "default_sts_ttl parameter only valid for assumed_role, federation_token, and session_token credential types",
+ ),
+ })
roleEntry.DefaultSTSTTL = 0
+
roleEntry.MaxSTSTTL = 1
- if roleEntry.validate() == nil {
- t.Errorf("bad: invalid roleEntry with unrecognized MaxSTSTTL %#v passed validation", roleEntry)
+ assertMultiError(t, roleEntry.validate(),
+ []error{
+ errors.New(
+ "max_sts_ttl parameter only valid for assumed_role, federation_token, and session_token credential types",
+ ),
+ })
+ roleEntry.MaxSTSTTL = 0
+
+ roleEntry.SessionTags = map[string]string{
+ "Key1": "Value1",
+ "Key2": "Value2",
+ }
+ assertMultiError(t, roleEntry.validate(),
+ []error{
+ errors.New(
+ "cannot supply session_tags when credential_type isn't assumed_role",
+ ),
+ })
+ roleEntry.SessionTags = nil
+
+ roleEntry.ExternalID = "my-ext-id"
+ assertMultiError(t, roleEntry.validate(),
+ []error{
+ errors.New(
+ "cannot supply external_id when credential_type isn't assumed_role"),
+ })
+}
+
+func assertMultiError(t *testing.T, err error, expected []error) {
+ t.Helper()
+
+ if err == nil {
+ t.Errorf("expected error, got nil")
+ return
+ }
+
+ var multiErr *multierror.Error
+ if errors.As(err, &multiErr) {
+ if multiErr.Len() != len(expected) {
+ t.Errorf("expected %d error, got %d", len(expected), multiErr.Len())
+ } else {
+ if !reflect.DeepEqual(expected, multiErr.Errors) {
+ t.Errorf("expected error %q, actual %q", expected, multiErr.Errors)
+ }
+ }
+ } else {
+ t.Errorf("expected multierror, got %T", err)
}
}
@@ -392,8 +446,13 @@ func TestRoleEntryValidationAssumedRoleCred(t *testing.T) {
RoleArns: []string{"arn:aws:iam::123456789012:role/SomeRole"},
PolicyArns: []string{adminAccessPolicyARN},
PolicyDocument: allowAllPolicyDocument,
- DefaultSTSTTL: 2,
- MaxSTSTTL: 3,
+ ExternalID: "my-ext-id",
+ SessionTags: map[string]string{
+ "Key1": "Value1",
+ "Key2": "Value2",
+ },
+ DefaultSTSTTL: 2,
+ MaxSTSTTL: 3,
}
if err := roleEntry.validate(); err != nil {
t.Errorf("bad: valid roleEntry %#v failed validation: %v", roleEntry, err)
diff --git a/builtin/logical/aws/path_user.go b/builtin/logical/aws/path_user.go
index 46b9c3e928..430f7754ee 100644
--- a/builtin/logical/aws/path_user.go
+++ b/builtin/logical/aws/path_user.go
@@ -157,7 +157,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
case !strutil.StrListContains(role.RoleArns, roleArn):
return logical.ErrorResponse(fmt.Sprintf("role_arn %q not in allowed role arns for Vault role %q", roleArn, roleName)), nil
}
- return b.assumeRole(ctx, req.Storage, req.DisplayName, roleName, roleArn, role.PolicyDocument, role.PolicyArns, role.IAMGroups, ttl, roleSessionName)
+ return b.assumeRole(ctx, req.Storage, req.DisplayName, roleName, roleArn, role.PolicyDocument, role.PolicyArns, role.IAMGroups, ttl, roleSessionName, role.SessionTags, role.ExternalID)
case federationTokenCred:
return b.getFederationToken(ctx, req.Storage, req.DisplayName, roleName, role.PolicyDocument, role.PolicyArns, role.IAMGroups, ttl)
case sessionTokenCred:
diff --git a/builtin/logical/aws/secret_access_keys.go b/builtin/logical/aws/secret_access_keys.go
index 151a9a5cd7..a9a9290cc5 100644
--- a/builtin/logical/aws/secret_access_keys.go
+++ b/builtin/logical/aws/secret_access_keys.go
@@ -238,7 +238,7 @@ func (b *backend) getSessionToken(ctx context.Context, s logical.Storage, serial
func (b *backend) assumeRole(ctx context.Context, s logical.Storage,
displayName, roleName, roleArn, policy string, policyARNs []string,
- iamGroups []string, lifeTimeInSeconds int64, roleSessionName string) (*logical.Response, error,
+ iamGroups []string, lifeTimeInSeconds int64, roleSessionName string, sessionTags map[string]string, externalID string) (*logical.Response, error,
) {
// grab any IAM group policies associated with the vault role, both inline
// and managed
@@ -295,6 +295,19 @@ func (b *backend) assumeRole(ctx context.Context, s logical.Storage,
if len(policyARNs) > 0 {
assumeRoleInput.SetPolicyArns(convertPolicyARNs(policyARNs))
}
+ if externalID != "" {
+ assumeRoleInput.SetExternalId(externalID)
+ }
+ var tags []*sts.Tag
+ for k, v := range sessionTags {
+ tags = append(tags,
+ &sts.Tag{
+ Key: aws.String(k),
+ Value: aws.String(v),
+ },
+ )
+ }
+ assumeRoleInput.SetTags(tags)
tokenResp, err := stsClient.AssumeRoleWithContext(ctx, assumeRoleInput)
if err != nil {
return logical.ErrorResponse("Error assuming role: %s", err), awsutil.CheckAWSError(err)
diff --git a/builtin/logical/database/backend_test.go b/builtin/logical/database/backend_test.go
index a1b96ad392..f5ba7246fc 100644
--- a/builtin/logical/database/backend_test.go
+++ b/builtin/logical/database/backend_test.go
@@ -23,6 +23,7 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/builtinplugins"
"github.com/hashicorp/vault/helper/namespace"
+ "github.com/hashicorp/vault/helper/testhelpers/certhelpers"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
postgreshelper "github.com/hashicorp/vault/helper/testhelpers/postgresql"
vaulthttp "github.com/hashicorp/vault/http"
@@ -345,6 +346,8 @@ func TestBackend_config_connection(t *testing.T) {
assert.Equal(t, "plugin-test", eventSender.Events[2].Event.Metadata.AsMap()["name"])
}
+// TestBackend_BadConnectionString tests that an error response resulting from
+// a failed connection does not expose the URL. The middleware should sanitize it.
func TestBackend_BadConnectionString(t *testing.T) {
cluster, sys := getClusterPostgresDB(t)
defer cluster.Cleanup()
@@ -359,7 +362,7 @@ func TestBackend_BadConnectionString(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, _ := postgreshelper.PrepareTestContainer(t, "13.4-buster")
+ cleanup, _ := postgreshelper.PrepareTestContainer(t)
defer cleanup()
respCheck := func(req *logical.Request) {
@@ -410,7 +413,7 @@ func TestBackend_basic(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// Configure a connection
@@ -658,6 +661,7 @@ func (s *singletonDBFactory) factory(context.Context, *logical.BackendConfig) (l
}
func TestBackend_connectionCrud(t *testing.T) {
+ t.Parallel()
dbFactory := &singletonDBFactory{}
cluster, sys := getClusterPostgresDBWithFactory(t, dbFactory.factory)
defer cluster.Cleanup()
@@ -665,7 +669,7 @@ func TestBackend_connectionCrud(t *testing.T) {
dbFactory.sys = sys
client := cluster.Cores[0].Client.Logical()
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// Mount the database plugin.
@@ -715,7 +719,6 @@ func TestBackend_connectionCrud(t *testing.T) {
"allowed_roles": []string{"plugin-role-test"},
"username": "postgres",
"password": "secret",
- "private_key": "PRIVATE_KEY",
})
if err != nil {
t.Fatalf("err:%s resp:%#v\n", err, resp)
@@ -736,9 +739,6 @@ func TestBackend_connectionCrud(t *testing.T) {
if _, exists := returnedConnectionDetails["password"]; exists {
t.Fatal("password should NOT be found in the returned config")
}
- if _, exists := returnedConnectionDetails["private_key"]; exists {
- t.Fatal("private_key should NOT be found in the returned config")
- }
// Replace connection url with templated version
templatedConnURL := strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}")
@@ -748,7 +748,6 @@ func TestBackend_connectionCrud(t *testing.T) {
"allowed_roles": []string{"plugin-role-test"},
"username": "postgres",
"password": "secret",
- "private_key": "PRIVATE_KEY",
})
if err != nil {
t.Fatalf("err:%s resp:%#v\n", err, resp)
@@ -854,6 +853,57 @@ func TestBackend_connectionCrud(t *testing.T) {
}
}
+func TestBackend_connectionSanitizePrivateKey(t *testing.T) {
+ t.Parallel()
+ dbFactory := &singletonDBFactory{}
+ cluster, sys := getClusterPostgresDBWithFactory(t, dbFactory.factory)
+ defer cluster.Cleanup()
+
+ dbFactory.sys = sys
+ client := cluster.Cores[0].Client.Logical()
+
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
+ defer cleanup()
+
+ // Mount the database plugin.
+ resp, err := client.Write("sys/mounts/database", map[string]interface{}{
+ "type": "database",
+ })
+ if err != nil {
+ t.Fatalf("err:%s resp:%#v\n", err, resp)
+ }
+
+ caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign())
+ clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert))
+
+ // Create a connection
+ resp, err = client.Write("database/config/plugin-test", map[string]interface{}{
+ "connection_url": connURL,
+ "plugin_name": "postgresql-database-plugin",
+ "allowed_roles": []string{"plugin-role-test"},
+ "username": "postgres",
+ "tls_certificate": string(clientCert.CombinedPEM()),
+ "private_key": string(clientCert.PrivateKeyPEM()),
+ "tls_ca": string(caCert.CombinedPEM()),
+ "verify_connection": false,
+ })
+ if err != nil {
+ t.Fatalf("err:%s resp:%#v\n", err, resp)
+ }
+
+ resp, err = client.Read("database/config/plugin-test")
+ if err != nil {
+ t.Fatalf("err:%s resp:%#v\n", err, resp)
+ }
+ returnedConnectionDetails := resp.Data["connection_details"].(map[string]interface{})
+ if strings.Contains(returnedConnectionDetails["connection_url"].(string), "secret") {
+ t.Fatal("password should not be found in the connection url")
+ }
+ if _, exists := returnedConnectionDetails["private_key"]; exists {
+ t.Fatal("private_key should NOT be found in the returned config")
+ }
+}
+
func TestBackend_roleCrud(t *testing.T) {
cluster, sys := getClusterPostgresDB(t)
defer cluster.Cleanup()
@@ -872,7 +922,7 @@ func TestBackend_roleCrud(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// Configure a connection
@@ -1121,7 +1171,7 @@ func TestBackend_allowedRoles(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// Configure a connection
@@ -1318,7 +1368,7 @@ func TestBackend_RotateRootCredentials(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}")
@@ -1451,7 +1501,7 @@ func TestBackend_ConnectionURL_redacted(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- cleanup, u := postgreshelper.PrepareTestContainerWithPassword(t, "13.4-buster", tt.password)
+ cleanup, u := postgreshelper.PrepareTestContainerWithPassword(t, tt.password)
t.Cleanup(cleanup)
p, err := url.Parse(u)
diff --git a/builtin/logical/database/path_roles_test.go b/builtin/logical/database/path_roles_test.go
index 91737da2cf..41a2e99758 100644
--- a/builtin/logical/database/path_roles_test.go
+++ b/builtin/logical/database/path_roles_test.go
@@ -222,7 +222,7 @@ func TestBackend_StaticRole_Config(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
@@ -487,7 +487,7 @@ func TestBackend_StaticRole_ReadCreds(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
@@ -667,7 +667,7 @@ func TestBackend_StaticRole_Updates(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
@@ -966,7 +966,7 @@ func TestBackend_StaticRole_Role_name_check(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
diff --git a/builtin/logical/database/rollback_test.go b/builtin/logical/database/rollback_test.go
index f60491a666..47c7683742 100644
--- a/builtin/logical/database/rollback_test.go
+++ b/builtin/logical/database/rollback_test.go
@@ -44,7 +44,7 @@ func TestBackend_RotateRootCredentials_WAL_rollback(t *testing.T) {
}
defer lb.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}")
@@ -183,7 +183,7 @@ func TestBackend_RotateRootCredentials_WAL_no_rollback_1(t *testing.T) {
}
defer lb.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}")
@@ -291,7 +291,7 @@ func TestBackend_RotateRootCredentials_WAL_no_rollback_2(t *testing.T) {
}
defer lb.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}")
diff --git a/builtin/logical/database/rotation_test.go b/builtin/logical/database/rotation_test.go
index c9917cb374..99fc3ddf00 100644
--- a/builtin/logical/database/rotation_test.go
+++ b/builtin/logical/database/rotation_test.go
@@ -63,7 +63,7 @@ func TestBackend_StaticRole_Rotation_basic(t *testing.T) {
b.schedule = &TestSchedule{}
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
@@ -274,7 +274,7 @@ func TestBackend_StaticRole_Rotation_Schedule_ErrorRecover(t *testing.T) {
b.schedule = &TestSchedule{}
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
t.Cleanup(cleanup)
// create the database user
@@ -458,7 +458,7 @@ func TestBackend_StaticRole_Rotation_NonStaticError(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
@@ -562,7 +562,7 @@ func TestBackend_StaticRole_Rotation_Revoke_user(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
@@ -783,7 +783,7 @@ func TestBackend_StaticRole_Rotation_QueueWAL_discard_role_newer_rotation_date(t
t.Fatal("could not convert to db backend")
}
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
@@ -952,7 +952,7 @@ func assertWALCount(t *testing.T, s logical.Storage, expected int, key string) {
type userCreator func(t *testing.T, username, password string)
func TestBackend_StaticRole_Rotation_PostgreSQL(t *testing.T) {
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
uc := userCreator(func(t *testing.T, username, password string) {
createTestPGUser(t, connURL, username, password, testRoleStaticCreate)
@@ -1246,7 +1246,7 @@ func TestBackend_StaticRole_Rotation_LockRegression(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// Configure a connection
@@ -1325,7 +1325,7 @@ func TestBackend_StaticRole_Rotation_Invalid_Role(t *testing.T) {
}
defer b.Cleanup(context.Background())
- cleanup, connURL := postgreshelper.PrepareTestContainer(t, "")
+ cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
// create the database user
diff --git a/builtin/logical/database/secret_creds.go b/builtin/logical/database/secret_creds.go
index e2130c1cf7..b485f7ca46 100644
--- a/builtin/logical/database/secret_creds.go
+++ b/builtin/logical/database/secret_creds.go
@@ -34,6 +34,9 @@ func (b *databaseBackend) secretCredsRenew() framework.OperationFunc {
return nil, fmt.Errorf("secret is missing username internal data")
}
username, ok := usernameRaw.(string)
+ if !ok {
+ return nil, fmt.Errorf("username not a string")
+ }
roleNameRaw, ok := req.Secret.InternalData["role"]
if !ok {
@@ -98,6 +101,9 @@ func (b *databaseBackend) secretCredsRevoke() framework.OperationFunc {
return nil, fmt.Errorf("secret is missing username internal data")
}
username, ok := usernameRaw.(string)
+ if !ok {
+ return nil, fmt.Errorf("username not a string")
+ }
var resp *logical.Response
diff --git a/builtin/logical/pki/acme_challenge_engine.go b/builtin/logical/pki/acme_challenge_engine.go
index 330a55b1cc..96663f2e1c 100644
--- a/builtin/logical/pki/acme_challenge_engine.go
+++ b/builtin/logical/pki/acme_challenge_engine.go
@@ -315,13 +315,13 @@ func (ace *ACMEChallengeEngine) AcceptChallenge(sc *storageContext, account stri
func (ace *ACMEChallengeEngine) VerifyChallenge(runnerSc *storageContext, id string, validationQueueRetries int, finished chan bool, config *acmeConfigEntry) {
sc, cancel := runnerSc.WithFreshTimeout(MaxChallengeTimeout)
defer cancel()
- runnerSc.Backend.Logger().Debug("Starting verification of challenge", "id", id)
+ runnerSc.Logger().Debug("Starting verification of challenge", "id", id)
if retry, retryAfter, err := ace._verifyChallenge(sc, id, config); err != nil {
// Because verification of this challenge failed, we need to retry
// it in the future. Log the error and re-add the item to the queue
// to try again later.
- sc.Backend.Logger().Error(fmt.Sprintf("ACME validation failed for %v: %v", id, err))
+ sc.Logger().Error(fmt.Sprintf("ACME validation failed for %v: %v", id, err))
if retry {
validationQueueRetries++
@@ -331,10 +331,10 @@ func (ace *ACMEChallengeEngine) VerifyChallenge(runnerSc *storageContext, id str
// we have a secondary check here to see if we are consistently looping within the validation
// queue that is larger than the normal retry attempts we would allow.
if validationQueueRetries > MaxRetryAttempts*2 {
- sc.Backend.Logger().Warn("reached max error attempts within challenge queue: %v, giving up", id)
+ sc.Logger().Warn("reached max error attempts within challenge queue: %v, giving up", id)
_, _, err = ace._verifyChallengeCleanup(sc, nil, id)
if err != nil {
- sc.Backend.Logger().Warn("Failed cleaning up challenge entry: %v", err)
+ sc.Logger().Warn("Failed cleaning up challenge entry: %v", err)
}
finished <- true
return
diff --git a/builtin/logical/pki/acme_state.go b/builtin/logical/pki/acme_state.go
index aa07010584..63962d933b 100644
--- a/builtin/logical/pki/acme_state.go
+++ b/builtin/logical/pki/acme_state.go
@@ -119,7 +119,7 @@ func (a *acmeState) reloadConfigIfRequired(sc *storageContext) error {
return nil
}
- config, err := sc.getAcmeConfig()
+ config, err := getAcmeConfig(sc)
if err != nil {
return fmt.Errorf("failed reading ACME config: %w", err)
}
diff --git a/builtin/logical/pki/acme_wrappers.go b/builtin/logical/pki/acme_wrappers.go
index febe48b9e4..88a1cee1d0 100644
--- a/builtin/logical/pki/acme_wrappers.go
+++ b/builtin/logical/pki/acme_wrappers.go
@@ -17,12 +17,13 @@ import (
)
type acmeContext struct {
+ issuing.IssuerRoleContext
+
// baseUrl is the combination of the configured cluster local URL and the acmePath up to /acme/
baseUrl *url.URL
clusterUrl *url.URL
sc *storageContext
- role *issuing.RoleEntry
- issuer *issuing.IssuerEntry
+ acmeState *acmeState
// acmeDirectory is a string that can distinguish the various acme directories we have configured
// if something needs to remain locked into a directory path structure.
acmeDirectory string
@@ -32,7 +33,7 @@ type acmeContext struct {
}
func (c acmeContext) getAcmeState() *acmeState {
- return c.sc.Backend.GetAcmeState()
+ return c.acmeState
}
type (
@@ -110,7 +111,7 @@ func (b *backend) acmeWrapper(opts acmeWrapperOpts, op acmeOperation) framework.
return acmeErrorWrapper(func(ctx context.Context, r *logical.Request, data *framework.FieldData) (*logical.Response, error) {
sc := b.makeStorageContext(ctx, r.Storage)
- config, err := sc.Backend.GetAcmeState().getConfigWithUpdate(sc)
+ config, err := b.GetAcmeState().getConfigWithUpdate(sc)
if err != nil {
return nil, fmt.Errorf("failed to fetch ACME configuration: %w", err)
}
@@ -144,7 +145,7 @@ func (b *backend) acmeWrapper(opts acmeWrapperOpts, op acmeOperation) framework.
return nil, err
}
- isCiepsEnabled, ciepsPolicy, err := getCiepsAcmeSettings(sc, opts, config, data)
+ isCiepsEnabled, ciepsPolicy, err := getCiepsAcmeSettings(b, sc, opts, config, data)
if err != nil {
return nil, err
}
@@ -160,15 +161,15 @@ func (b *backend) acmeWrapper(opts acmeWrapperOpts, op acmeOperation) framework.
}
acmeCtx := &acmeContext{
- baseUrl: acmeBaseUrl,
- clusterUrl: clusterBase,
- sc: sc,
- role: role,
- issuer: issuer,
- acmeDirectory: acmeDirectory,
- eabPolicy: eabPolicy,
- ciepsPolicy: ciepsPolicy,
- runtimeOpts: runtimeOpts,
+ IssuerRoleContext: issuing.NewIssuerRoleContext(ctx, issuer, role),
+ baseUrl: acmeBaseUrl,
+ clusterUrl: clusterBase,
+ sc: sc,
+ acmeState: b.acmeState,
+ acmeDirectory: acmeDirectory,
+ eabPolicy: eabPolicy,
+ ciepsPolicy: ciepsPolicy,
+ runtimeOpts: runtimeOpts,
}
return op(acmeCtx, r, data)
@@ -455,7 +456,7 @@ func getAcmeRoleAndIssuer(sc *storageContext, data *framework.FieldData, config
func getAndValidateAcmeRole(sc *storageContext, requestedRole string) (*issuing.RoleEntry, error) {
var err error
- role, err := sc.Backend.GetRole(sc.Context, sc.Storage, requestedRole)
+ role, err := sc.GetRole(requestedRole)
if err != nil {
return nil, fmt.Errorf("%w: err loading role", ErrServerInternal)
}
@@ -496,7 +497,7 @@ func isAcmeDisabled(sc *storageContext, config *acmeConfigEntry, policy EabPolic
disableAcme, nonFatalErr := isPublicACMEDisabledByEnv()
if nonFatalErr != nil {
- sc.Backend.Logger().Warn(fmt.Sprintf("could not parse env var '%s'", disableAcmeEnvVar), "error", nonFatalErr)
+ sc.Logger().Warn(fmt.Sprintf("could not parse env var '%s'", disableAcmeEnvVar), "error", nonFatalErr)
}
// The OS environment if true will override any configuration option.
diff --git a/builtin/logical/pki/acme_wrappers_test.go b/builtin/logical/pki/acme_wrappers_test.go
index cabca18094..569036deae 100644
--- a/builtin/logical/pki/acme_wrappers_test.go
+++ b/builtin/logical/pki/acme_wrappers_test.go
@@ -82,12 +82,12 @@ func TestACMEIssuerRoleLoading(t *testing.T) {
for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
f := b.acmeWrapper(acmeWrapperOpts{}, func(acmeCtx *acmeContext, r *logical.Request, _ *framework.FieldData) (*logical.Response, error) {
- if tt.roleName != acmeCtx.role.Name {
- return nil, fmt.Errorf("expected role %s but got %s", tt.roleName, acmeCtx.role.Name)
+ if tt.roleName != acmeCtx.Role.Name {
+ return nil, fmt.Errorf("expected role %s but got %s", tt.roleName, acmeCtx.Role.Name)
}
- if tt.expectedIssuerName != acmeCtx.issuer.Name {
- return nil, fmt.Errorf("expected issuer %s but got %s", tt.expectedIssuerName, acmeCtx.issuer.Name)
+ if tt.expectedIssuerName != acmeCtx.Issuer.Name {
+ return nil, fmt.Errorf("expected issuer %s but got %s", tt.expectedIssuerName, acmeCtx.Issuer.Name)
}
return nil, nil
diff --git a/builtin/logical/pki/backend.go b/builtin/logical/pki/backend.go
index 2931c089ed..f753563236 100644
--- a/builtin/logical/pki/backend.go
+++ b/builtin/logical/pki/backend.go
@@ -16,6 +16,7 @@ import (
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
"github.com/hashicorp/vault/builtin/logical/pki/managed_key"
"github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/helper/metricsutil"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/framework"
@@ -143,7 +144,7 @@ func Backend(conf *logical.BackendConfig) *backend {
WriteForwardedStorage: []string{
crossRevocationPath,
- unifiedRevocationWritePathPrefix,
+ revocation.UnifiedRevocationWritePathPrefix,
unifiedDeltaWALPath,
},
@@ -654,7 +655,7 @@ func (b *backend) periodicFunc(ctx context.Context, request *logical.Request) er
}
// Then attempt to rebuild the CRLs if required.
- warnings, err := b.CrlBuilder().rebuildIfForced(sc)
+ warnings, err := b.CrlBuilder().RebuildIfForced(sc)
if err != nil {
return err
}
diff --git a/builtin/logical/pki/backend_test.go b/builtin/logical/pki/backend_test.go
index a12daec707..0a8827f131 100644
--- a/builtin/logical/pki/backend_test.go
+++ b/builtin/logical/pki/backend_test.go
@@ -44,6 +44,7 @@ import (
"github.com/hashicorp/vault/builtin/credential/userpass"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
"github.com/hashicorp/vault/builtin/logical/pki/parsing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/helper/testhelpers"
logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical"
"github.com/hashicorp/vault/helper/testhelpers/teststorage"
@@ -6084,7 +6085,7 @@ func TestPKI_EmptyCRLConfigUpgraded(t *testing.T) {
b, s := CreateBackendWithStorage(t)
// Write an empty CRLConfig into storage.
- crlConfigEntry, err := logical.StorageEntryJSON("config/crl", &crlConfig{})
+ crlConfigEntry, err := logical.StorageEntryJSON("config/crl", &pki_backend.CrlConfig{})
require.NoError(t, err)
err = s.Put(ctx, crlConfigEntry)
require.NoError(t, err)
@@ -6093,13 +6094,13 @@ func TestPKI_EmptyCRLConfigUpgraded(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Data)
- require.Equal(t, resp.Data["expiry"], defaultCrlConfig.Expiry)
- require.Equal(t, resp.Data["disable"], defaultCrlConfig.Disable)
- require.Equal(t, resp.Data["ocsp_disable"], defaultCrlConfig.OcspDisable)
- require.Equal(t, resp.Data["auto_rebuild"], defaultCrlConfig.AutoRebuild)
- require.Equal(t, resp.Data["auto_rebuild_grace_period"], defaultCrlConfig.AutoRebuildGracePeriod)
- require.Equal(t, resp.Data["enable_delta"], defaultCrlConfig.EnableDelta)
- require.Equal(t, resp.Data["delta_rebuild_interval"], defaultCrlConfig.DeltaRebuildInterval)
+ require.Equal(t, resp.Data["expiry"], pki_backend.DefaultCrlConfig.Expiry)
+ require.Equal(t, resp.Data["disable"], pki_backend.DefaultCrlConfig.Disable)
+ require.Equal(t, resp.Data["ocsp_disable"], pki_backend.DefaultCrlConfig.OcspDisable)
+ require.Equal(t, resp.Data["auto_rebuild"], pki_backend.DefaultCrlConfig.AutoRebuild)
+ require.Equal(t, resp.Data["auto_rebuild_grace_period"], pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod)
+ require.Equal(t, resp.Data["enable_delta"], pki_backend.DefaultCrlConfig.EnableDelta)
+ require.Equal(t, resp.Data["delta_rebuild_interval"], pki_backend.DefaultCrlConfig.DeltaRebuildInterval)
}
func TestPKI_ListRevokedCerts(t *testing.T) {
@@ -6764,12 +6765,14 @@ const (
shouldBeAuthed pathAuthChecker = iota
shouldBeUnauthedReadList
shouldBeUnauthedWriteOnly
+ shouldBeUnauthedReadWriteOnly
)
var pathAuthChckerMap = map[pathAuthChecker]pathAuthCheckerFunc{
- shouldBeAuthed: pathShouldBeAuthed,
- shouldBeUnauthedReadList: pathShouldBeUnauthedReadList,
- shouldBeUnauthedWriteOnly: pathShouldBeUnauthedWriteOnly,
+ shouldBeAuthed: pathShouldBeAuthed,
+ shouldBeUnauthedReadList: pathShouldBeUnauthedReadList,
+ shouldBeUnauthedWriteOnly: pathShouldBeUnauthedWriteOnly,
+ shouldBeUnauthedReadWriteOnly: pathShouldBeUnauthedWriteOnly,
}
func TestProperAuthing(t *testing.T) {
@@ -7063,6 +7066,10 @@ func TestProperAuthing(t *testing.T) {
if hasGet || hasList {
t.Fatalf("Unauthed write-only endpoints should not have GET/LIST capabilities: %v->%v", openapi_path, raw_path)
}
+ } else if handler == shouldBeUnauthedReadWriteOnly {
+ if hasDelete || hasList {
+ t.Fatalf("Unauthed read-write-only endpoints should not have DELETE/LIST capabilities: %v->%v", openapi_path, raw_path)
+ }
}
}
diff --git a/builtin/logical/pki/ca_util.go b/builtin/logical/pki/ca_util.go
index 6f2f005217..9f803527c5 100644
--- a/builtin/logical/pki/ca_util.go
+++ b/builtin/logical/pki/ca_util.go
@@ -84,14 +84,13 @@ func getGenerationParams(sc *storageContext, data *framework.FieldData) (exporte
func generateCABundle(sc *storageContext, input *inputBundle, data *certutil.CreationBundle, randomSource io.Reader) (*certutil.ParsedCertBundle, error) {
ctx := sc.Context
- b := sc.Backend
if kmsRequested(input) {
keyId, err := getManagedKeyId(input.apiData)
if err != nil {
return nil, err
}
- return managed_key.GenerateManagedKeyCABundle(ctx, b, keyId, data, randomSource)
+ return managed_key.GenerateManagedKeyCABundle(ctx, sc.GetPkiManagedView(), keyId, data, randomSource)
}
if existingKeyRequested(input) {
@@ -110,7 +109,7 @@ func generateCABundle(sc *storageContext, input *inputBundle, data *certutil.Cre
if err != nil {
return nil, err
}
- return managed_key.GenerateManagedKeyCABundle(ctx, b, keyId, data, randomSource)
+ return managed_key.GenerateManagedKeyCABundle(ctx, sc.GetPkiManagedView(), keyId, data, randomSource)
}
return certutil.CreateCertificateWithKeyGenerator(data, randomSource, existingKeyGeneratorFromBytes(keyEntry))
@@ -121,7 +120,6 @@ func generateCABundle(sc *storageContext, input *inputBundle, data *certutil.Cre
func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.CreationBundle, addBasicConstraints bool, randomSource io.Reader) (*certutil.ParsedCSRBundle, error) {
ctx := sc.Context
- b := sc.Backend
if kmsRequested(input) {
keyId, err := getManagedKeyId(input.apiData)
@@ -129,7 +127,7 @@ func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.Cr
return nil, err
}
- return managed_key.GenerateManagedKeyCSRBundle(ctx, b, keyId, data, addBasicConstraints, randomSource)
+ return managed_key.GenerateManagedKeyCSRBundle(ctx, sc.GetPkiManagedView(), keyId, data, addBasicConstraints, randomSource)
}
if existingKeyRequested(input) {
@@ -148,7 +146,7 @@ func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.Cr
if err != nil {
return nil, err
}
- return managed_key.GenerateManagedKeyCSRBundle(ctx, b, keyId, data, addBasicConstraints, randomSource)
+ return managed_key.GenerateManagedKeyCSRBundle(ctx, sc.GetPkiManagedView(), keyId, data, addBasicConstraints, randomSource)
}
return certutil.CreateCSRWithKeyGenerator(data, addBasicConstraints, randomSource, existingKeyGeneratorFromBytes(key))
@@ -157,8 +155,8 @@ func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.Cr
return certutil.CreateCSRWithRandomSource(data, addBasicConstraints, randomSource)
}
-func parseCABundle(ctx context.Context, b *backend, bundle *certutil.CertBundle) (*certutil.ParsedCertBundle, error) {
- return issuing.ParseCABundle(ctx, b, bundle)
+func parseCABundle(ctx context.Context, mkv managed_key.PkiManagedKeyView, bundle *certutil.CertBundle) (*certutil.ParsedCertBundle, error) {
+ return issuing.ParseCABundle(ctx, mkv, bundle)
}
func (sc *storageContext) getKeyTypeAndBitsForRole(data *framework.FieldData) (string, int, error) {
@@ -190,7 +188,7 @@ func (sc *storageContext) getKeyTypeAndBitsForRole(data *framework.FieldData) (s
return "", 0, errors.New("unable to determine managed key id: " + err.Error())
}
- pubKeyManagedKey, err := managed_key.GetManagedKeyPublicKey(sc.Context, sc.Backend, keyId)
+ pubKeyManagedKey, err := managed_key.GetManagedKeyPublicKey(sc.Context, sc.GetPkiManagedView(), keyId)
if err != nil {
return "", 0, errors.New("failed to lookup public key from managed key: " + err.Error())
}
@@ -222,7 +220,7 @@ func (sc *storageContext) getExistingPublicKey(data *framework.FieldData) (crypt
if err != nil {
return nil, err
}
- return getPublicKey(sc.Context, sc.Backend, key)
+ return getPublicKey(sc.Context, sc.GetPkiManagedView(), key)
}
func getKeyTypeAndBitsFromPublicKeyForRole(pubKey crypto.PublicKey) (certutil.PrivateKeyType, int, error) {
@@ -235,7 +233,7 @@ func getKeyTypeAndBitsFromPublicKeyForRole(pubKey crypto.PublicKey) (certutil.Pr
keyBits = certutil.GetPublicKeySize(pubKey)
case *ecdsa.PublicKey:
keyType = certutil.ECPrivateKey
- case *ed25519.PublicKey:
+ case ed25519.PublicKey:
keyType = certutil.Ed25519PrivateKey
default:
return certutil.UnknownPrivateKey, 0, fmt.Errorf("unsupported public key: %#v", pubKey)
diff --git a/builtin/logical/pki/ca_util_test.go b/builtin/logical/pki/ca_util_test.go
new file mode 100644
index 0000000000..d4ef64e68f
--- /dev/null
+++ b/builtin/logical/pki/ca_util_test.go
@@ -0,0 +1,82 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package pki
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/ed25519"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "testing"
+
+ "github.com/hashicorp/vault/sdk/helper/certutil"
+)
+
+func TestGetKeyTypeAndBitsFromPublicKeyForRole(t *testing.T) {
+ rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ t.Fatalf("error generating rsa key: %s", err)
+ }
+
+ ecdsaKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+ if err != nil {
+ t.Fatalf("error generating ecdsa key: %s", err)
+ }
+
+ publicKey, _, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ t.Fatalf("error generating ed25519 key: %s", err)
+ }
+
+ testCases := map[string]struct {
+ publicKey crypto.PublicKey
+ expectedKeyType certutil.PrivateKeyType
+ expectedKeyBits int
+ expectError bool
+ }{
+ "rsa": {
+ publicKey: rsaKey.Public(),
+ expectedKeyType: certutil.RSAPrivateKey,
+ expectedKeyBits: 2048,
+ },
+ "ecdsa": {
+ publicKey: ecdsaKey.Public(),
+ expectedKeyType: certutil.ECPrivateKey,
+ expectedKeyBits: 0,
+ },
+ "ed25519": {
+ publicKey: publicKey,
+ expectedKeyType: certutil.Ed25519PrivateKey,
+ expectedKeyBits: 0,
+ },
+ "bad key type": {
+ publicKey: []byte{},
+ expectedKeyType: certutil.UnknownPrivateKey,
+ expectedKeyBits: 0,
+ expectError: true,
+ },
+ }
+
+ for name, tt := range testCases {
+ t.Run(name, func(t *testing.T) {
+ keyType, keyBits, err := getKeyTypeAndBitsFromPublicKeyForRole(tt.publicKey)
+ if err != nil && !tt.expectError {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if err == nil && tt.expectError {
+ t.Fatal("expected error, got nil")
+ }
+
+ if keyType != tt.expectedKeyType {
+ t.Fatalf("key type mismatch: expected %s, got %s", tt.expectedKeyType, keyType)
+ }
+
+ if keyBits != tt.expectedKeyBits {
+ t.Fatalf("key bits mismatch: expected %d, got %d", tt.expectedKeyBits, keyBits)
+ }
+ })
+ }
+}
diff --git a/builtin/logical/pki/cert_util.go b/builtin/logical/pki/cert_util.go
index 2a658f93ff..5304a54db8 100644
--- a/builtin/logical/pki/cert_util.go
+++ b/builtin/logical/pki/cert_util.go
@@ -22,6 +22,7 @@ import (
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
"github.com/hashicorp/vault/builtin/logical/pki/parsing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/errutil"
@@ -139,9 +140,9 @@ func (sc *storageContext) fetchCAInfo(issuerRef string, usage issuing.IssuerUsag
func (sc *storageContext) fetchCAInfoWithIssuer(issuerRef string, usage issuing.IssuerUsage) (*certutil.CAInfoBundle, issuing.IssuerID, error) {
var issuerId issuing.IssuerID
- if sc.Backend.UseLegacyBundleCaStorage() {
+ if sc.UseLegacyBundleCaStorage() {
// We have not completed the migration so attempt to load the bundle from the legacy location
- sc.Backend.Logger().Info("Using legacy CA bundle as PKI migration has not completed.")
+ sc.Logger().Info("Using legacy CA bundle as PKI migration has not completed.")
issuerId = legacyBundleShimID
} else {
var err error
@@ -163,24 +164,24 @@ func (sc *storageContext) fetchCAInfoWithIssuer(issuerRef string, usage issuing.
// fetchCAInfoByIssuerId will fetch the CA info, will return an error if no ca info exists for the given issuerId.
// This does support the loading using the legacyBundleShimID
func (sc *storageContext) fetchCAInfoByIssuerId(issuerId issuing.IssuerID, usage issuing.IssuerUsage) (*certutil.CAInfoBundle, error) {
- return issuing.FetchCAInfoByIssuerId(sc.Context, sc.Storage, sc.Backend, issuerId, usage)
+ return issuing.FetchCAInfoByIssuerId(sc.Context, sc.Storage, sc.GetPkiManagedView(), issuerId, usage)
}
func fetchCertBySerialBigInt(sc *storageContext, prefix string, serial *big.Int) (*logical.StorageEntry, error) {
return fetchCertBySerial(sc, prefix, serialFromBigInt(serial))
}
-// Allows fetching certificates from the backend; it handles the slightly
+// fetchCertBySerial allows fetching certificates from the backend; it handles the slightly
// separate pathing for CRL, and revoked certificates.
//
// Support for fetching CA certificates was removed, due to the new issuers
// changes.
-func fetchCertBySerial(sc *storageContext, prefix, serial string) (*logical.StorageEntry, error) {
+func fetchCertBySerial(sc pki_backend.StorageContext, prefix, serial string) (*logical.StorageEntry, error) {
var path, legacyPath string
var err error
var certEntry *logical.StorageEntry
- hyphenSerial := normalizeSerial(serial)
+ hyphenSerial := parsing.NormalizeSerialForStorage(serial)
colonSerial := strings.ReplaceAll(strings.ToLower(serial), "-", ":")
switch {
@@ -189,8 +190,8 @@ func fetchCertBySerial(sc *storageContext, prefix, serial string) (*logical.Stor
case strings.HasPrefix(prefix, "revoked/"):
legacyPath = "revoked/" + colonSerial
path = "revoked/" + hyphenSerial
- case serial == legacyCRLPath || serial == deltaCRLPath || serial == unifiedCRLPath || serial == unifiedDeltaCRLPath:
- warnings, err := sc.Backend.CrlBuilder().rebuildIfForced(sc)
+ case serial == issuing.LegacyCRLPath || serial == issuing.DeltaCRLPath || serial == issuing.UnifiedCRLPath || serial == issuing.UnifiedDeltaCRLPath:
+ warnings, err := sc.CrlBuilder().RebuildIfForced(sc)
if err != nil {
return nil, err
}
@@ -199,28 +200,28 @@ func fetchCertBySerial(sc *storageContext, prefix, serial string) (*logical.Stor
for index, warning := range warnings {
msg = fmt.Sprintf("%v\n %d. %v", msg, index+1, warning)
}
- sc.Backend.Logger().Warn(msg)
+ sc.Logger().Warn(msg)
}
- unified := serial == unifiedCRLPath || serial == unifiedDeltaCRLPath
- path, err = sc.resolveIssuerCRLPath(defaultRef, unified)
+ unified := serial == issuing.UnifiedCRLPath || serial == issuing.UnifiedDeltaCRLPath
+ path, err = issuing.ResolveIssuerCRLPath(sc.GetContext(), sc.GetStorage(), sc.UseLegacyBundleCaStorage(), issuing.DefaultRef, unified)
if err != nil {
return nil, err
}
- if serial == deltaCRLPath || serial == unifiedDeltaCRLPath {
- if sc.Backend.UseLegacyBundleCaStorage() {
+ if serial == issuing.DeltaCRLPath || serial == issuing.UnifiedDeltaCRLPath {
+ if sc.UseLegacyBundleCaStorage() {
return nil, fmt.Errorf("refusing to serve delta CRL with legacy CA bundle")
}
- path += deltaCRLPathSuffix
+ path += issuing.DeltaCRLPathSuffix
}
default:
legacyPath = issuing.PathCerts + colonSerial
path = issuing.PathCerts + hyphenSerial
}
- certEntry, err = sc.Storage.Get(sc.Context, path)
+ certEntry, err = sc.GetStorage().Get(sc.GetContext(), path)
if err != nil {
return nil, errutil.InternalError{Err: fmt.Sprintf("error fetching certificate %s: %s", serial, err)}
}
@@ -240,7 +241,7 @@ func fetchCertBySerial(sc *storageContext, prefix, serial string) (*logical.Stor
// always manifest on Windows, and thus the initial check for a revoked
// cert fails would return an error when the cert isn't revoked, preventing
// the happy path from working.
- certEntry, _ = sc.Storage.Get(sc.Context, legacyPath)
+ certEntry, _ = sc.GetStorage().Get(sc.GetContext(), legacyPath)
if certEntry == nil {
return nil, nil
}
@@ -250,12 +251,12 @@ func fetchCertBySerial(sc *storageContext, prefix, serial string) (*logical.Stor
// Update old-style paths to new-style paths
certEntry.Key = path
- certCounter := sc.Backend.GetCertificateCounter()
+ certCounter := sc.GetCertificateCounter()
certsCounted := certCounter.IsInitialized()
- if err = sc.Storage.Put(sc.Context, certEntry); err != nil {
+ if err = sc.GetStorage().Put(sc.GetContext(), certEntry); err != nil {
return nil, errutil.InternalError{Err: fmt.Sprintf("error saving certificate with serial %s to new location: %s", serial, err)}
}
- if err = sc.Storage.Delete(sc.Context, legacyPath); err != nil {
+ if err = sc.GetStorage().Delete(sc.GetContext(), legacyPath); err != nil {
// If we fail here, we have an extra (copy) of a cert in storage, add to metrics:
switch {
case strings.HasPrefix(prefix, "revoked/"):
@@ -327,7 +328,6 @@ func generateCert(sc *storageContext,
randomSource io.Reader) (*certutil.ParsedCertBundle, []string, error,
) {
ctx := sc.Context
- b := sc.Backend
if input.role == nil {
return nil, nil, errutil.InternalError{Err: "no role found in data bundle"}
@@ -337,7 +337,7 @@ func generateCert(sc *storageContext,
return nil, nil, errutil.UserError{Err: "RSA keys < 2048 bits are unsafe and not supported"}
}
- data, warnings, err := generateCreationBundle(b, input, caSign, nil)
+ data, warnings, err := generateCreationBundle(sc.System(), input, caSign, nil)
if err != nil {
return nil, nil, err
}
@@ -402,7 +402,7 @@ func generateCert(sc *storageContext,
// N.B.: This is only meant to be used for generating intermediate CAs.
// It skips some sanity checks.
func generateIntermediateCSR(sc *storageContext, input *inputBundle, randomSource io.Reader) (*certutil.ParsedCSRBundle, []string, error) {
- creation, warnings, err := generateCreationBundle(sc.Backend, input, nil, nil)
+ creation, warnings, err := generateCreationBundle(sc.System(), input, nil, nil)
if err != nil {
return nil, nil, err
}
@@ -468,7 +468,11 @@ func (i SignCertInputFromDataFields) GetPermittedDomains() []string {
return i.data.Get("permitted_dns_domains").([]string)
}
-func signCert(b *backend, data *inputBundle, caSign *certutil.CAInfoBundle, isCA bool, useCSRValues bool) (*certutil.ParsedCertBundle, []string, error) {
+func (i SignCertInputFromDataFields) IgnoreCSRSignature() bool {
+ return false
+}
+
+func signCert(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle, isCA bool, useCSRValues bool) (*certutil.ParsedCertBundle, []string, error) {
if data.role == nil {
return nil, nil, errutil.InternalError{Err: "no role found in data bundle"}
}
@@ -476,7 +480,7 @@ func signCert(b *backend, data *inputBundle, caSign *certutil.CAInfoBundle, isCA
entityInfo := issuing.NewEntityInfoFromReq(data.req)
signCertInput := NewSignCertInputFromDataFields(data.apiData, isCA, useCSRValues)
- return issuing.SignCert(b.System(), data.role, entityInfo, caSign, signCertInput)
+ return issuing.SignCert(sysView, data.role, entityInfo, caSign, signCertInput)
}
func getOtherSANsFromX509Extensions(exts []pkix.Extension) ([]certutil.OtherNameUtf8, error) {
@@ -498,6 +502,10 @@ type CreationBundleInputFromFieldData struct {
data *framework.FieldData
}
+func (cb CreationBundleInputFromFieldData) IgnoreCSRSignature() bool {
+ return false
+}
+
func (cb CreationBundleInputFromFieldData) GetCommonName() string {
return cb.data.Get("common_name").(string)
}
@@ -542,18 +550,18 @@ func (cb CreationBundleInputFromFieldData) GetUserIds() []string {
// generateCreationBundle is a shared function that reads parameters supplied
// from the various endpoints and generates a CreationParameters with the
// parameters that can be used to issue or sign
-func generateCreationBundle(b *backend, data *inputBundle, caSign *certutil.CAInfoBundle, csr *x509.CertificateRequest) (*certutil.CreationBundle, []string, error) {
+func generateCreationBundle(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle, csr *x509.CertificateRequest) (*certutil.CreationBundle, []string, error) {
entityInfo := issuing.NewEntityInfoFromReq(data.req)
creationBundleInput := NewCreationBundleInputFromFieldData(data.apiData)
- return issuing.GenerateCreationBundle(b.System(), data.role, entityInfo, creationBundleInput, caSign, csr)
+ return issuing.GenerateCreationBundle(sysView, data.role, entityInfo, creationBundleInput, caSign, csr)
}
// getCertificateNotAfter compute a certificate's NotAfter date based on the mount ttl, role, signing bundle and input
// api data being sent. Returns a NotAfter time, a set of warnings or an error.
-func getCertificateNotAfter(b *backend, data *inputBundle, caSign *certutil.CAInfoBundle) (time.Time, []string, error) {
+func getCertificateNotAfter(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle) (time.Time, []string, error) {
input := NewCertNotAfterInputFromFieldData(data.apiData)
- return issuing.GetCertificateNotAfter(b.System(), data.role, input, caSign)
+ return issuing.GetCertificateNotAfter(sysView, data.role, input, caSign)
}
// applyIssuerLeafNotAfterBehavior resets a certificate's notAfter time or errors out based on the
diff --git a/builtin/logical/pki/cert_util_test.go b/builtin/logical/pki/cert_util_test.go
index c5edda91c1..4f162aeb09 100644
--- a/builtin/logical/pki/cert_util_test.go
+++ b/builtin/logical/pki/cert_util_test.go
@@ -125,7 +125,7 @@ func TestPki_MultipleOUs(t *testing.T) {
OU: []string{"Z", "E", "V"},
},
}
- cb, _, err := generateCreationBundle(b, input, nil, nil)
+ cb, _, err := generateCreationBundle(b.System(), input, nil, nil)
if err != nil {
t.Fatalf("Error: %v", err)
}
@@ -245,7 +245,7 @@ func TestPki_PermitFQDNs(t *testing.T) {
name := name
testCase := testCase
t.Run(name, func(t *testing.T) {
- cb, _, err := generateCreationBundle(b, testCase.input, nil, nil)
+ cb, _, err := generateCreationBundle(b.System(), testCase.input, nil, nil)
if err != nil {
t.Fatalf("Error: %v", err)
}
diff --git a/builtin/logical/pki/cieps_util_oss.go b/builtin/logical/pki/cieps_util_oss.go
index 52524b9d4f..7efb1151ee 100644
--- a/builtin/logical/pki/cieps_util_oss.go
+++ b/builtin/logical/pki/cieps_util_oss.go
@@ -20,6 +20,6 @@ func issueAcmeCertUsingCieps(_ *backend, _ *acmeContext, _ *logical.Request, _ *
return nil, "", fmt.Errorf("cieps is an enterprise only feature")
}
-func getCiepsAcmeSettings(sc *storageContext, opts acmeWrapperOpts, config *acmeConfigEntry, data *framework.FieldData) (bool, string, error) {
+func getCiepsAcmeSettings(b *backend, sc *storageContext, opts acmeWrapperOpts, config *acmeConfigEntry, data *framework.FieldData) (bool, string, error) {
return false, "", nil
}
diff --git a/builtin/logical/pki/crl_test.go b/builtin/logical/pki/crl_test.go
index 7627a982c6..3c7848db78 100644
--- a/builtin/logical/pki/crl_test.go
+++ b/builtin/logical/pki/crl_test.go
@@ -15,6 +15,8 @@ import (
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/helper/constants"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
@@ -61,10 +63,10 @@ func TestBackend_CRLConfigUpdate(t *testing.T) {
require.Equal(t, "24h", resp.Data["expiry"])
require.Equal(t, false, resp.Data["disable"])
- require.Equal(t, defaultCrlConfig.OcspDisable, resp.Data["ocsp_disable"])
- require.Equal(t, defaultCrlConfig.OcspExpiry, resp.Data["ocsp_expiry"])
- require.Equal(t, defaultCrlConfig.AutoRebuild, resp.Data["auto_rebuild"])
- require.Equal(t, defaultCrlConfig.AutoRebuildGracePeriod, resp.Data["auto_rebuild_grace_period"])
+ require.Equal(t, pki_backend.DefaultCrlConfig.OcspDisable, resp.Data["ocsp_disable"])
+ require.Equal(t, pki_backend.DefaultCrlConfig.OcspExpiry, resp.Data["ocsp_expiry"])
+ require.Equal(t, pki_backend.DefaultCrlConfig.AutoRebuild, resp.Data["auto_rebuild"])
+ require.Equal(t, pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod, resp.Data["auto_rebuild_grace_period"])
}
func TestBackend_CRLConfig(t *testing.T) {
@@ -416,7 +418,7 @@ func TestCrlRebuilder(t *testing.T) {
cb := newCRLBuilder(true /* can rebuild and write CRLs */)
// Force an initial build
- warnings, err := cb.rebuild(sc, true)
+ warnings, err := cb.Rebuild(sc, true)
require.NoError(t, err, "Failed to rebuild CRL")
require.Empty(t, warnings, "unexpectedly got warnings rebuilding CRL")
@@ -424,7 +426,7 @@ func TestCrlRebuilder(t *testing.T) {
crl1 := parseCrlPemBytes(t, resp.Data["http_raw_body"].([]byte))
// We shouldn't rebuild within this call.
- warnings, err = cb.rebuildIfForced(sc)
+ warnings, err = cb.RebuildIfForced(sc)
require.NoError(t, err, "Failed to rebuild if forced CRL")
require.Empty(t, warnings, "unexpectedly got warnings rebuilding CRL")
@@ -443,7 +445,7 @@ func TestCrlRebuilder(t *testing.T) {
// This should rebuild the CRL
cb.requestRebuildIfActiveNode(b)
- warnings, err = cb.rebuildIfForced(sc)
+ warnings, err = cb.RebuildIfForced(sc)
require.NoError(t, err, "Failed to rebuild if forced CRL")
require.Empty(t, warnings, "unexpectedly got warnings rebuilding CRL")
resp = requestCrlFromBackend(t, s, b)
@@ -974,13 +976,13 @@ func TestAutoRebuild(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Data)
- require.Equal(t, resp.Data["expiry"], defaultCrlConfig.Expiry)
- require.Equal(t, resp.Data["disable"], defaultCrlConfig.Disable)
- require.Equal(t, resp.Data["ocsp_disable"], defaultCrlConfig.OcspDisable)
- require.Equal(t, resp.Data["auto_rebuild"], defaultCrlConfig.AutoRebuild)
- require.Equal(t, resp.Data["auto_rebuild_grace_period"], defaultCrlConfig.AutoRebuildGracePeriod)
- require.Equal(t, resp.Data["enable_delta"], defaultCrlConfig.EnableDelta)
- require.Equal(t, resp.Data["delta_rebuild_interval"], defaultCrlConfig.DeltaRebuildInterval)
+ require.Equal(t, resp.Data["expiry"], pki_backend.DefaultCrlConfig.Expiry)
+ require.Equal(t, resp.Data["disable"], pki_backend.DefaultCrlConfig.Disable)
+ require.Equal(t, resp.Data["ocsp_disable"], pki_backend.DefaultCrlConfig.OcspDisable)
+ require.Equal(t, resp.Data["auto_rebuild"], pki_backend.DefaultCrlConfig.AutoRebuild)
+ require.Equal(t, resp.Data["auto_rebuild_grace_period"], pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod)
+ require.Equal(t, resp.Data["enable_delta"], pki_backend.DefaultCrlConfig.EnableDelta)
+ require.Equal(t, resp.Data["delta_rebuild_interval"], pki_backend.DefaultCrlConfig.DeltaRebuildInterval)
// Safety guard: we play with rebuild timing below.
_, err = client.Logical().Write("pki/config/crl", map[string]interface{}{
@@ -1059,7 +1061,7 @@ func TestAutoRebuild(t *testing.T) {
require.NotNil(t, resp.Data)
require.NotEmpty(t, resp.Data["value"])
revEntryValue := resp.Data["value"].(string)
- var revInfo revocationInfo
+ var revInfo revocation.RevocationInfo
err = json.Unmarshal([]byte(revEntryValue), &revInfo)
require.NoError(t, err)
require.Equal(t, revInfo.CertificateIssuer, issuing.IssuerID(rootIssuer))
@@ -1232,7 +1234,7 @@ func TestTidyIssuerAssociation(t *testing.T) {
require.NotNil(t, entry)
require.NotNil(t, entry.Value)
- var leafInfo revocationInfo
+ var leafInfo revocation.RevocationInfo
err = entry.DecodeJSON(&leafInfo)
require.NoError(t, err)
require.Equal(t, rootID, leafInfo.CertificateIssuer)
diff --git a/builtin/logical/pki/crl_util.go b/builtin/logical/pki/crl_util.go
index 4085d59741..def00a5f11 100644
--- a/builtin/logical/pki/crl_util.go
+++ b/builtin/logical/pki/crl_util.go
@@ -17,6 +17,9 @@ import (
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/parsing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/errutil"
@@ -24,7 +27,7 @@ import (
)
const (
- revokedPath = "revoked/"
+ revokedPath = revocation.RevokedPath
crossRevocationPrefix = "cross-revocation-queue/"
crossRevocationPath = crossRevocationPrefix + "{{clusterId}}/"
deltaWALLastBuildSerialName = "last-build-serial"
@@ -38,13 +41,6 @@ const (
unifiedDeltaWALLastRevokedSerial = unifiedDeltaWALPath + deltaWALLastRevokedSerialName
)
-type revocationInfo struct {
- CertificateBytes []byte `json:"certificate_bytes"`
- RevocationTime int64 `json:"revocation_time"`
- RevocationTimeUTC time.Time `json:"revocation_time_utc"`
- CertificateIssuer issuing.IssuerID `json:"issuer_id"`
-}
-
type revocationRequest struct {
RequestedAt time.Time `json:"requested_at"`
}
@@ -97,7 +93,7 @@ type CrlBuilder struct {
_config sync.RWMutex
dirty *atomic.Bool
- config crlConfig
+ config pki_backend.CrlConfig
haveInitializedConfig bool
// Whether to invalidate our LastModifiedTime due to write on the
@@ -112,6 +108,8 @@ type CrlBuilder struct {
crossQueue *revocationQueue
}
+var _ pki_backend.CrlBuilderType = (*CrlBuilder)(nil)
+
const (
_ignoreForceFlag = true
_enforceForceFlag = false
@@ -126,7 +124,7 @@ func newCRLBuilder(canRebuild bool) *CrlBuilder {
// to stabilize.
lastDeltaRebuildCheck: time.Now(),
dirty: &atomic.Bool{},
- config: defaultCrlConfig,
+ config: pki_backend.DefaultCrlConfig,
invalidate: &atomic.Bool{},
haveInitializedQueue: &atomic.Bool{},
revQueue: newRevocationQueue(),
@@ -137,6 +135,14 @@ func newCRLBuilder(canRebuild bool) *CrlBuilder {
return builder
}
+func (cb *CrlBuilder) SetLastDeltaRebuildCheckTime(t time.Time) {
+ cb.lastDeltaRebuildCheck = t
+}
+
+func (cb *CrlBuilder) ShouldInvalidate() bool {
+ return cb.invalidate.Load()
+}
+
func (cb *CrlBuilder) markConfigDirty() {
cb.dirty.Store(true)
}
@@ -163,7 +169,7 @@ func (cb *CrlBuilder) reloadConfigIfRequired(sc *storageContext) error {
if config != nil {
cb.config = *config
} else {
- cb.config = defaultCrlConfig
+ cb.config = pki_backend.DefaultCrlConfig
}
// Updated the config; unset dirty.
@@ -174,7 +180,7 @@ func (cb *CrlBuilder) reloadConfigIfRequired(sc *storageContext) error {
triggerChangeNotification = false // do not trigger on the initial loading of configuration.
}
- // Certain things need to be triggered on all server types when crlConfig is loaded.
+ // Certain things need to be triggered on all server types when CrlConfig is loaded.
if triggerChangeNotification {
cb.notifyOnConfigChange(sc, previousConfig, cb.config)
}
@@ -183,12 +189,12 @@ func (cb *CrlBuilder) reloadConfigIfRequired(sc *storageContext) error {
return nil
}
-func (cb *CrlBuilder) notifyOnConfigChange(sc *storageContext, priorConfig crlConfig, newConfig crlConfig) {
+func (cb *CrlBuilder) notifyOnConfigChange(sc *storageContext, priorConfig pki_backend.CrlConfig, newConfig pki_backend.CrlConfig) {
// If you need to hook into a CRL configuration change across different server types
// such as primary clusters as well as performance replicas, it is easier to do here than
// in two places (API layer and in invalidateFunc)
if priorConfig.UnifiedCRL != newConfig.UnifiedCRL && newConfig.UnifiedCRL {
- sc.Backend.GetUnifiedTransferStatus().forceRun()
+ sc.GetUnifiedTransferStatus().forceRun()
}
if priorConfig.UseGlobalQueue != newConfig.UseGlobalQueue && newConfig.UseGlobalQueue {
@@ -196,10 +202,10 @@ func (cb *CrlBuilder) notifyOnConfigChange(sc *storageContext, priorConfig crlCo
}
}
-func (cb *CrlBuilder) getConfigWithUpdate(sc *storageContext) (*crlConfig, error) {
+func (cb *CrlBuilder) GetConfigWithUpdate(sc pki_backend.StorageContext) (*pki_backend.CrlConfig, error) {
// Config may mutate immediately after accessing, but will be freshly
// fetched if necessary.
- if err := cb.reloadConfigIfRequired(sc); err != nil {
+ if err := cb.reloadConfigIfRequired(sc.(*storageContext)); err != nil {
return nil, err
}
@@ -210,12 +216,12 @@ func (cb *CrlBuilder) getConfigWithUpdate(sc *storageContext) (*crlConfig, error
return &configCopy, nil
}
-func (cb *CrlBuilder) getConfigWithForcedUpdate(sc *storageContext) (*crlConfig, error) {
+func (cb *CrlBuilder) getConfigWithForcedUpdate(sc *storageContext) (*pki_backend.CrlConfig, error) {
cb.markConfigDirty()
- return cb.getConfigWithUpdate(sc)
+ return cb.GetConfigWithUpdate(sc)
}
-func (cb *CrlBuilder) writeConfig(sc *storageContext, config *crlConfig) (*crlConfig, error) {
+func (cb *CrlBuilder) writeConfig(sc *storageContext, config *pki_backend.CrlConfig) (*pki_backend.CrlConfig, error) {
cb._config.Lock()
defer cb._config.Unlock()
@@ -228,7 +234,7 @@ func (cb *CrlBuilder) writeConfig(sc *storageContext, config *crlConfig) (*crlCo
if config != nil {
cb.config = *config
} else {
- cb.config = defaultCrlConfig
+ cb.config = pki_backend.DefaultCrlConfig
}
triggerChangeNotification := true
@@ -237,7 +243,7 @@ func (cb *CrlBuilder) writeConfig(sc *storageContext, config *crlConfig) (*crlCo
triggerChangeNotification = false // do not trigger on the initial loading of configuration.
}
- // Certain things need to be triggered on all server types when crlConfig is loaded.
+ // Certain things need to be triggered on all server types when CrlConfig is loaded.
if triggerChangeNotification {
cb.notifyOnConfigChange(sc, previousConfig, cb.config)
}
@@ -246,7 +252,7 @@ func (cb *CrlBuilder) writeConfig(sc *storageContext, config *crlConfig) (*crlCo
}
func (cb *CrlBuilder) checkForAutoRebuild(sc *storageContext) error {
- cfg, err := cb.getConfigWithUpdate(sc)
+ cfg, err := cb.GetConfigWithUpdate(sc)
if err != nil {
return err
}
@@ -291,9 +297,9 @@ func (cb *CrlBuilder) checkForAutoRebuild(sc *storageContext) error {
// This may occur if the duration is empty; in that case
// assume the default. The default should be valid and shouldn't
// error.
- defaultPeriod, defaultErr := parseutil.ParseDurationSecond(defaultCrlConfig.AutoRebuildGracePeriod)
+ defaultPeriod, defaultErr := parseutil.ParseDurationSecond(pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod)
if defaultErr != nil {
- return fmt.Errorf("error checking for auto-rebuild status: unable to parse duration from both config's grace period (%v) and default grace period (%v):\n- config: %v\n- default: %w\n", cfg.AutoRebuildGracePeriod, defaultCrlConfig.AutoRebuildGracePeriod, err, defaultErr)
+ return fmt.Errorf("error checking for auto-rebuild status: unable to parse duration from both config's grace period (%v) and default grace period (%v):\n- config: %v\n- default: %w\n", cfg.AutoRebuildGracePeriod, pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod, err, defaultErr)
}
period = defaultPeriod
@@ -337,19 +343,19 @@ func (cb *CrlBuilder) flushCRLBuildTimeInvalidation(sc *storageContext) error {
return nil
}
-// rebuildIfForced is to be called by readers or periodic functions that might need to trigger
+// RebuildIfForced is to be called by readers or periodic functions that might need to trigger
// a refresh of the CRL before the read occurs.
-func (cb *CrlBuilder) rebuildIfForced(sc *storageContext) ([]string, error) {
+func (cb *CrlBuilder) RebuildIfForced(sc pki_backend.StorageContext) ([]string, error) {
if cb.forceRebuild.Load() {
- return cb._doRebuild(sc, true, _enforceForceFlag)
+ return cb._doRebuild(sc.(*storageContext), true, _enforceForceFlag)
}
return nil, nil
}
// rebuild is to be called by various write apis that know the CRL is to be updated and can be now.
-func (cb *CrlBuilder) rebuild(sc *storageContext, forceNew bool) ([]string, error) {
- return cb._doRebuild(sc, forceNew, _ignoreForceFlag)
+func (cb *CrlBuilder) Rebuild(sc pki_backend.StorageContext, forceNew bool) ([]string, error) {
+ return cb._doRebuild(sc.(*storageContext), forceNew, _ignoreForceFlag)
}
// requestRebuildIfActiveNode will schedule a rebuild of the CRL from the next read or write api call assuming we are the active node of a cluster
@@ -387,9 +393,9 @@ func (cb *CrlBuilder) _doRebuild(sc *storageContext, forceNew bool, ignoreForceF
return nil, nil
}
-func (cb *CrlBuilder) _getPresentDeltaWALForClearing(sc *storageContext, path string) ([]string, error) {
+func (cb *CrlBuilder) _getPresentDeltaWALForClearing(sc pki_backend.StorageContext, path string) ([]string, error) {
// Clearing of the delta WAL occurs after a new complete CRL has been built.
- walSerials, err := sc.Storage.List(sc.Context, path)
+ walSerials, err := sc.GetStorage().List(sc.GetContext(), path)
if err != nil {
return nil, fmt.Errorf("error fetching list of delta WAL certificates to clear: %w", err)
}
@@ -400,12 +406,12 @@ func (cb *CrlBuilder) _getPresentDeltaWALForClearing(sc *storageContext, path st
return walSerials, nil
}
-func (cb *CrlBuilder) getPresentLocalDeltaWALForClearing(sc *storageContext) ([]string, error) {
+func (cb *CrlBuilder) GetPresentLocalDeltaWALForClearing(sc pki_backend.StorageContext) ([]string, error) {
return cb._getPresentDeltaWALForClearing(sc, localDeltaWALPath)
}
-func (cb *CrlBuilder) getPresentUnifiedDeltaWALForClearing(sc *storageContext) ([]string, error) {
- walClusters, err := sc.Storage.List(sc.Context, unifiedDeltaWALPrefix)
+func (cb *CrlBuilder) GetPresentUnifiedDeltaWALForClearing(sc pki_backend.StorageContext) ([]string, error) {
+ walClusters, err := sc.GetStorage().List(sc.GetContext(), unifiedDeltaWALPrefix)
if err != nil {
return nil, fmt.Errorf("error fetching list of clusters with delta WAL entries: %w", err)
}
@@ -419,7 +425,7 @@ func (cb *CrlBuilder) getPresentUnifiedDeltaWALForClearing(sc *storageContext) (
}
// Here, we don't want to include the unifiedDeltaWALPrefix because
- // clearUnifiedDeltaWAL handles that for us. Instead, just include
+ // ClearUnifiedDeltaWAL handles that for us. Instead, just include
// the cluster identifier.
for _, clusterPath := range clusterPaths {
allPaths = append(allPaths, cluster+clusterPath)
@@ -429,7 +435,7 @@ func (cb *CrlBuilder) getPresentUnifiedDeltaWALForClearing(sc *storageContext) (
return allPaths, nil
}
-func (cb *CrlBuilder) _clearDeltaWAL(sc *storageContext, walSerials []string, path string) error {
+func (cb *CrlBuilder) _clearDeltaWAL(sc pki_backend.StorageContext, walSerials []string, path string) error {
// Clearing of the delta WAL occurs after a new complete CRL has been built.
for _, serial := range walSerials {
// Don't remove our special entries!
@@ -437,7 +443,7 @@ func (cb *CrlBuilder) _clearDeltaWAL(sc *storageContext, walSerials []string, pa
continue
}
- if err := sc.Storage.Delete(sc.Context, path+serial); err != nil {
+ if err := sc.GetStorage().Delete(sc.GetContext(), path+serial); err != nil {
return fmt.Errorf("error clearing delta WAL certificate: %w", err)
}
}
@@ -445,11 +451,11 @@ func (cb *CrlBuilder) _clearDeltaWAL(sc *storageContext, walSerials []string, pa
return nil
}
-func (cb *CrlBuilder) clearLocalDeltaWAL(sc *storageContext, walSerials []string) error {
+func (cb *CrlBuilder) ClearLocalDeltaWAL(sc pki_backend.StorageContext, walSerials []string) error {
return cb._clearDeltaWAL(sc, walSerials, localDeltaWALPath)
}
-func (cb *CrlBuilder) clearUnifiedDeltaWAL(sc *storageContext, walSerials []string) error {
+func (cb *CrlBuilder) ClearUnifiedDeltaWAL(sc pki_backend.StorageContext, walSerials []string) error {
return cb._clearDeltaWAL(sc, walSerials, unifiedDeltaWALPrefix)
}
@@ -463,7 +469,7 @@ func (cb *CrlBuilder) rebuildDeltaCRLsIfForced(sc *storageContext, override bool
// This guarantee means we can avoid checking delta CRL expiry. Thus,
// we only need to rebuild the delta CRL when we have new revocations,
// within our time window for updating it.
- cfg, err := cb.getConfigWithUpdate(sc)
+ cfg, err := cb.GetConfigWithUpdate(sc)
if err != nil {
return nil, err
}
@@ -516,7 +522,7 @@ func (cb *CrlBuilder) rebuildDeltaCRLsIfForced(sc *storageContext, override bool
}
// Finally, we must've needed to do the rebuild. Execute!
- return cb.rebuildDeltaCRLsHoldingLock(sc, false)
+ return cb.RebuildDeltaCRLsHoldingLock(sc, false)
}
func (cb *CrlBuilder) _shouldRebuildLocalCRLs(sc *storageContext, override bool) (bool, error) {
@@ -567,9 +573,9 @@ func (cb *CrlBuilder) _shouldRebuildLocalCRLs(sc *storageContext, override bool)
func (cb *CrlBuilder) _shouldRebuildUnifiedCRLs(sc *storageContext, override bool) (bool, error) {
// Unified CRL can only be built by the main cluster.
- b := sc.Backend
- if b.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) ||
- (!b.System().LocalMount() && b.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) {
+ sysView := sc.System()
+ if sysView.ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) ||
+ (!sysView.LocalMount() && sysView.ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) {
return false, nil
}
@@ -643,11 +649,11 @@ func (cb *CrlBuilder) rebuildDeltaCRLs(sc *storageContext, forceNew bool) ([]str
cb._builder.Lock()
defer cb._builder.Unlock()
- return cb.rebuildDeltaCRLsHoldingLock(sc, forceNew)
+ return cb.RebuildDeltaCRLsHoldingLock(sc, forceNew)
}
-func (cb *CrlBuilder) rebuildDeltaCRLsHoldingLock(sc *storageContext, forceNew bool) ([]string, error) {
- return buildAnyCRLs(sc, forceNew, true /* building delta */)
+func (cb *CrlBuilder) RebuildDeltaCRLsHoldingLock(sc pki_backend.StorageContext, forceNew bool) ([]string, error) {
+ return buildAnyCRLs(sc.(*storageContext), forceNew, true /* building delta */)
}
func (cb *CrlBuilder) addCertForRevocationCheck(cluster, serial string) {
@@ -680,14 +686,14 @@ func (cb *CrlBuilder) maybeGatherQueueForFirstProcess(sc *storageContext, isNotP
return nil
}
- sc.Backend.Logger().Debug(fmt.Sprintf("gathering first time existing revocations"))
+ sc.Logger().Debug(fmt.Sprintf("gathering first time existing revocations"))
clusters, err := sc.Storage.List(sc.Context, crossRevocationPrefix)
if err != nil {
return fmt.Errorf("failed to list cross-cluster revocation queue participating clusters: %w", err)
}
- sc.Backend.Logger().Debug(fmt.Sprintf("found %v clusters: %v", len(clusters), clusters))
+ sc.Logger().Debug(fmt.Sprintf("found %v clusters: %v", len(clusters), clusters))
for cIndex, cluster := range clusters {
cluster = cluster[0 : len(cluster)-1]
@@ -697,7 +703,7 @@ func (cb *CrlBuilder) maybeGatherQueueForFirstProcess(sc *storageContext, isNotP
return fmt.Errorf("failed to list cross-cluster revocation queue entries for cluster %v (%v): %w", cluster, cIndex, err)
}
- sc.Backend.Logger().Debug(fmt.Sprintf("found %v serials for cluster %v: %v", len(serials), cluster, serials))
+ sc.Logger().Debug(fmt.Sprintf("found %v serials for cluster %v: %v", len(serials), cluster, serials))
for _, serial := range serials {
if serial[len(serial)-1] == '/' {
@@ -731,10 +737,10 @@ func (cb *CrlBuilder) maybeGatherQueueForFirstProcess(sc *storageContext, isNotP
}
func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error {
- sc.Backend.Logger().Debug(fmt.Sprintf("starting to process revocation requests"))
+ sc.Logger().Debug(fmt.Sprintf("starting to process revocation requests"))
- isNotPerfPrimary := sc.Backend.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) ||
- (!sc.Backend.System().LocalMount() && sc.Backend.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary))
+ isNotPerfPrimary := sc.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) ||
+ (!sc.System().LocalMount() && sc.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary))
if err := cb.maybeGatherQueueForFirstProcess(sc, isNotPerfPrimary); err != nil {
return fmt.Errorf("failed to gather first queue: %w", err)
@@ -743,14 +749,14 @@ func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error {
revQueue := cb.revQueue.Iterate()
removalQueue := cb.removalQueue.Iterate()
- sc.Backend.Logger().Debug(fmt.Sprintf("gathered %v revocations and %v confirmation entries", len(revQueue), len(removalQueue)))
+ sc.Logger().Debug(fmt.Sprintf("gathered %v revocations and %v confirmation entries", len(revQueue), len(removalQueue)))
- crlConfig, err := cb.getConfigWithUpdate(sc)
+ crlConfig, err := cb.GetConfigWithUpdate(sc)
if err != nil {
return err
}
- ourClusterId, err := sc.Backend.System().ClusterID(sc.Context)
+ ourClusterId, err := sc.System().ClusterID(sc.Context)
if err != nil {
return fmt.Errorf("unable to fetch clusterID to ignore local revocation entries: %w", err)
}
@@ -812,7 +818,7 @@ func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error {
}
if isNotPerfPrimary {
- sc.Backend.Logger().Debug(fmt.Sprintf("not on perf primary so ignoring any revocation confirmations"))
+ sc.Logger().Debug(fmt.Sprintf("not on perf primary so ignoring any revocation confirmations"))
// See note in pki/backend.go; this should be empty.
cb.removalQueue.RemoveAll()
@@ -848,9 +854,9 @@ func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error {
}
func (cb *CrlBuilder) processCrossClusterRevocations(sc *storageContext) error {
- sc.Backend.Logger().Debug(fmt.Sprintf("starting to process unified revocations"))
+ sc.Logger().Debug(fmt.Sprintf("starting to process unified revocations"))
- crlConfig, err := cb.getConfigWithUpdate(sc)
+ crlConfig, err := cb.GetConfigWithUpdate(sc)
if err != nil {
return err
}
@@ -861,9 +867,9 @@ func (cb *CrlBuilder) processCrossClusterRevocations(sc *storageContext) error {
}
crossQueue := cb.crossQueue.Iterate()
- sc.Backend.Logger().Debug(fmt.Sprintf("gathered %v unified revocations entries", len(crossQueue)))
+ sc.Logger().Debug(fmt.Sprintf("gathered %v unified revocations entries", len(crossQueue)))
- ourClusterId, err := sc.Backend.System().ClusterID(sc.Context)
+ ourClusterId, err := sc.System().ClusterID(sc.Context)
if err != nil {
return fmt.Errorf("unable to fetch clusterID to ignore local unified revocation entries: %w", err)
}
@@ -909,56 +915,12 @@ func (cb *CrlBuilder) processCrossClusterRevocations(sc *storageContext) error {
return nil
}
-// Helper function to fetch a map of IssuerID->parsed cert for revocation
-// usage. Unlike other paths, this needs to handle the legacy bundle
-// more gracefully than rejecting it outright.
-func fetchIssuerMapForRevocationChecking(sc *storageContext) (map[issuing.IssuerID]*x509.Certificate, error) {
- var err error
- var issuers []issuing.IssuerID
-
- if !sc.Backend.UseLegacyBundleCaStorage() {
- issuers, err = sc.listIssuers()
- if err != nil {
- return nil, fmt.Errorf("could not fetch issuers list: %w", err)
- }
- } else {
- // Hack: this isn't a real IssuerID, but it works for fetchCAInfo
- // since it resolves the reference.
- issuers = []issuing.IssuerID{legacyBundleShimID}
- }
-
- issuerIDCertMap := make(map[issuing.IssuerID]*x509.Certificate, len(issuers))
- for _, issuer := range issuers {
- _, bundle, caErr := sc.fetchCertBundleByIssuerId(issuer, false)
- if caErr != nil {
- return nil, fmt.Errorf("error fetching CA certificate for issuer id %v: %w", issuer, caErr)
- }
-
- if bundle == nil {
- return nil, fmt.Errorf("faulty reference: %v - CA info not found", issuer)
- }
-
- parsedBundle, err := parseCABundle(sc.Context, sc.Backend, bundle)
- if err != nil {
- return nil, errutil.InternalError{Err: err.Error()}
- }
-
- if parsedBundle.Certificate == nil {
- return nil, errutil.InternalError{Err: "stored CA information not able to be parsed"}
- }
-
- issuerIDCertMap[issuer] = parsedBundle.Certificate
- }
-
- return issuerIDCertMap, nil
-}
-
// Revoke a certificate from a given serial number if it is present in local
// storage.
-func tryRevokeCertBySerial(sc *storageContext, config *crlConfig, serial string) (*logical.Response, error) {
+func tryRevokeCertBySerial(sc *storageContext, config *pki_backend.CrlConfig, serial string) (*logical.Response, error) {
// revokeCert requires us to hold these locks before calling it.
- sc.Backend.GetRevokeStorageLock().Lock()
- defer sc.Backend.GetRevokeStorageLock().Unlock()
+ sc.GetRevokeStorageLock().Lock()
+ defer sc.GetRevokeStorageLock().Unlock()
certEntry, err := fetchCertBySerial(sc, issuing.PathCerts, serial)
if err != nil {
@@ -983,24 +945,24 @@ func tryRevokeCertBySerial(sc *storageContext, config *crlConfig, serial string)
}
// Revokes a cert, and tries to be smart about error recovery
-func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (*logical.Response, error) {
+func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Certificate) (*logical.Response, error) {
// As this backend is self-contained and this function does not hook into
// third parties to manage users or resources, if the mount is tainted,
// revocation doesn't matter anyways -- the CRL that would be written will
// be immediately blown away by the view being cleared. So we can simply
// fast path a successful exit.
- if sc.Backend.System().Tainted() {
+ if sc.System().Tainted() {
return nil, nil
}
- colonSerial := serialFromCert(cert)
- hyphenSerial := normalizeSerial(colonSerial)
+ colonSerial := parsing.SerialFromCert(cert)
+ hyphenSerial := parsing.NormalizeSerialForStorage(colonSerial)
// Validate that no issuers match the serial number to be revoked. We need
// to gracefully degrade to the legacy cert bundle when it is required, as
// secondary PR clusters might not have been upgraded, but still need to
// handle revoking certs.
- issuerIDCertMap, err := fetchIssuerMapForRevocationChecking(sc)
+ issuerIDCertMap, err := revocation.FetchIssuerMapForRevocationChecking(sc)
if err != nil {
return nil, err
}
@@ -1013,7 +975,7 @@ func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (
}
}
- curRevInfo, err := sc.fetchRevocationInfo(colonSerial)
+ curRevInfo, err := fetchRevocationInfo(sc, colonSerial)
if err != nil {
return nil, err
}
@@ -1040,7 +1002,7 @@ func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (
}
currTime := time.Now()
- revInfo := revocationInfo{
+ revInfo := revocation.RevocationInfo{
CertificateBytes: cert.Raw,
RevocationTime: currTime.Unix(),
RevocationTimeUTC: currTime.UTC(),
@@ -1048,14 +1010,14 @@ func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (
// We may not find an issuer with this certificate; that's fine so
// ignore the return value.
- associateRevokedCertWithIsssuer(&revInfo, cert, issuerIDCertMap)
+ revInfo.AssociateRevokedCertWithIsssuer(cert, issuerIDCertMap)
revEntry, err := logical.StorageEntryJSON(revokedPath+hyphenSerial, revInfo)
if err != nil {
return nil, fmt.Errorf("error creating revocation entry: %w", err)
}
- certCounter := sc.Backend.GetCertificateCounter()
+ certCounter := sc.GetCertificateCounter()
certsCounted := certCounter.IsInitialized()
err = sc.Storage.Put(sc.Context, revEntry)
if err != nil {
@@ -1078,20 +1040,20 @@ func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (
// the unified storage space through a periodic function.
failedWritingUnifiedCRL := false
if config.UnifiedCRL {
- entry := &unifiedRevocationEntry{
+ entry := &revocation.UnifiedRevocationEntry{
SerialNumber: colonSerial,
CertExpiration: cert.NotAfter,
RevocationTimeUTC: revInfo.RevocationTimeUTC,
CertificateIssuer: revInfo.CertificateIssuer,
}
- ignoreErr := writeUnifiedRevocationEntry(sc, entry)
+ ignoreErr := revocation.WriteUnifiedRevocationEntry(sc.GetContext(), sc.GetStorage(), entry)
if ignoreErr != nil {
// Just log the error if we fail to write across clusters, a separate background
// thread will reattempt it later on as we have the local write done.
- sc.Backend.Logger().Error("Failed to write unified revocation entry, will re-attempt later",
+ sc.Logger().Error("Failed to write unified revocation entry, will re-attempt later",
"serial_number", colonSerial, "error", ignoreErr)
- sc.Backend.GetUnifiedTransferStatus().forceRun()
+ sc.GetUnifiedTransferStatus().forceRun()
resp.AddWarning(fmt.Sprintf("Failed to write unified revocation entry, will re-attempt later: %v", err))
failedWritingUnifiedCRL = true
@@ -1103,7 +1065,7 @@ func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (
// already rebuilt the full CRL so the Delta WAL will be cleared
// afterwards. Writing an entry only to immediately remove it
// isn't necessary.
- warnings, crlErr := sc.Backend.CrlBuilder().rebuild(sc, false)
+ warnings, crlErr := sc.CrlBuilder().Rebuild(sc, false)
if crlErr != nil {
switch crlErr.(type) {
case errutil.UserError:
@@ -1124,7 +1086,7 @@ func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (
return resp, nil
}
-func writeRevocationDeltaWALs(sc *storageContext, config *crlConfig, resp *logical.Response, failedWritingUnifiedCRL bool, hyphenSerial string, colonSerial string) error {
+func writeRevocationDeltaWALs(sc *storageContext, config *pki_backend.CrlConfig, resp *logical.Response, failedWritingUnifiedCRL bool, hyphenSerial string, colonSerial string) error {
if err := writeSpecificRevocationDeltaWALs(sc, hyphenSerial, colonSerial, localDeltaWALPath); err != nil {
return fmt.Errorf("failed to write local delta WAL entry: %w", err)
}
@@ -1146,9 +1108,9 @@ func writeRevocationDeltaWALs(sc *storageContext, config *crlConfig, resp *logic
if ignoredErr := writeSpecificRevocationDeltaWALs(sc, hyphenSerial, colonSerial, unifiedDeltaWALPath); ignoredErr != nil {
// Just log the error if we fail to write across clusters, a separate background
// thread will reattempt it later on as we have the local write done.
- sc.Backend.Logger().Error("Failed to write cross-cluster delta WAL entry, will re-attempt later",
+ sc.Logger().Error("Failed to write cross-cluster delta WAL entry, will re-attempt later",
"serial_number", colonSerial, "error", ignoredErr)
- sc.Backend.GetUnifiedTransferStatus().forceRun()
+ sc.GetUnifiedTransferStatus().forceRun()
resp.AddWarning(fmt.Sprintf("Failed to write cross-cluster delta WAL entry, will re-attempt later: %v", ignoredErr))
}
@@ -1243,8 +1205,7 @@ func buildAnyCRLs(sc *storageContext, forceNew bool, isDelta bool) ([]string, er
var wasLegacy bool
// First, fetch an updated copy of the CRL config. We'll pass this into buildCRL.
- crlBuilder := sc.Backend.CrlBuilder()
- globalCRLConfig, err := crlBuilder.getConfigWithUpdate(sc)
+ globalCRLConfig, err := sc.CrlBuilder().GetConfigWithUpdate(sc)
if err != nil {
return nil, fmt.Errorf("error building CRL: while updating config: %w", err)
}
@@ -1261,7 +1222,7 @@ func buildAnyCRLs(sc *storageContext, forceNew bool, isDelta bool) ([]string, er
return nil, nil
}
- if !sc.Backend.UseLegacyBundleCaStorage() {
+ if !sc.UseLegacyBundleCaStorage() {
issuers, err = sc.listIssuers()
if err != nil {
return nil, fmt.Errorf("error building CRL: while listing issuers: %w", err)
@@ -1369,13 +1330,13 @@ func buildAnyCRLs(sc *storageContext, forceNew bool, isDelta bool) ([]string, er
if !isDelta {
// After we've confirmed the primary CRLs have built OK, go ahead and
// clear the delta CRL WAL and rebuild it.
- if err := crlBuilder.clearLocalDeltaWAL(sc, currLocalDeltaSerials); err != nil {
+ if err := sc.CrlBuilder().ClearLocalDeltaWAL(sc, currLocalDeltaSerials); err != nil {
return nil, fmt.Errorf("error building CRLs: unable to clear Delta WAL: %w", err)
}
- if err := crlBuilder.clearUnifiedDeltaWAL(sc, currUnifiedDeltaSerials); err != nil {
+ if err := sc.CrlBuilder().ClearUnifiedDeltaWAL(sc, currUnifiedDeltaSerials); err != nil {
return nil, fmt.Errorf("error building CRLs: unable to clear Delta WAL: %w", err)
}
- deltaWarnings, err := crlBuilder.rebuildDeltaCRLsHoldingLock(sc, forceNew)
+ deltaWarnings, err := sc.CrlBuilder().RebuildDeltaCRLsHoldingLock(sc, forceNew)
if err != nil {
return nil, fmt.Errorf("error building CRLs: unable to rebuild empty Delta WAL: %w", err)
}
@@ -1409,7 +1370,7 @@ func getLastWALSerial(sc *storageContext, path string) (string, error) {
func buildAnyLocalCRLs(
sc *storageContext,
issuersConfig *issuing.IssuerConfigEntry,
- globalCRLConfig *crlConfig,
+ globalCRLConfig *pki_backend.CrlConfig,
issuers []issuing.IssuerID,
issuerIDEntryMap map[issuing.IssuerID]*issuing.IssuerEntry,
issuerIDCertMap map[issuing.IssuerID]*x509.Certificate,
@@ -1439,7 +1400,7 @@ func buildAnyLocalCRLs(
// visible now, should also be visible on the complete CRL we're writing.
var currDeltaCerts []string
if !isDelta {
- currDeltaCerts, err = sc.Backend.CrlBuilder().getPresentLocalDeltaWALForClearing(sc)
+ currDeltaCerts, err = sc.CrlBuilder().GetPresentLocalDeltaWALForClearing(sc)
if err != nil {
return nil, nil, fmt.Errorf("error building CRLs: unable to get present delta WAL entries for removal: %w", err)
}
@@ -1503,7 +1464,7 @@ func buildAnyLocalCRLs(
if isDelta {
// Update our last build time here so we avoid checking for new certs
// for a while.
- sc.Backend.CrlBuilder().lastDeltaRebuildCheck = time.Now()
+ sc.CrlBuilder().SetLastDeltaRebuildCheckTime(time.Now())
if len(lastDeltaSerial) > 0 {
// When we have a last delta serial, write out the relevant info
@@ -1528,7 +1489,7 @@ func buildAnyLocalCRLs(
func buildAnyUnifiedCRLs(
sc *storageContext,
issuersConfig *issuing.IssuerConfigEntry,
- globalCRLConfig *crlConfig,
+ globalCRLConfig *pki_backend.CrlConfig,
issuers []issuing.IssuerID,
issuerIDEntryMap map[issuing.IssuerID]*issuing.IssuerEntry,
issuerIDCertMap map[issuing.IssuerID]*x509.Certificate,
@@ -1541,9 +1502,9 @@ func buildAnyUnifiedCRLs(
var warnings []string
// Unified CRL can only be built by the main cluster.
- b := sc.Backend
- if b.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) ||
- (!b.System().LocalMount() && b.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) {
+ sysView := sc.System()
+ if sysView.ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) ||
+ (!sysView.LocalMount() && sysView.ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) {
return nil, nil, nil
}
@@ -1582,7 +1543,7 @@ func buildAnyUnifiedCRLs(
// visible now, should also be visible on the complete CRL we're writing.
var currDeltaCerts []string
if !isDelta {
- currDeltaCerts, err = sc.Backend.CrlBuilder().getPresentUnifiedDeltaWALForClearing(sc)
+ currDeltaCerts, err = sc.CrlBuilder().GetPresentUnifiedDeltaWALForClearing(sc)
if err != nil {
return nil, nil, fmt.Errorf("error building CRLs: unable to get present delta WAL entries for removal: %w", err)
}
@@ -1646,7 +1607,7 @@ func buildAnyUnifiedCRLs(
if isDelta {
// Update our last build time here so we avoid checking for new certs
// for a while.
- sc.Backend.CrlBuilder().lastDeltaRebuildCheck = time.Now()
+ sc.CrlBuilder().SetLastDeltaRebuildCheckTime(time.Now())
// Persist all of our known last revoked serial numbers here, as the
// last seen serial during build. This will allow us to detect if any
@@ -1679,7 +1640,7 @@ func buildAnyUnifiedCRLs(
func buildAnyCRLsWithCerts(
sc *storageContext,
issuersConfig *issuing.IssuerConfigEntry,
- globalCRLConfig *crlConfig,
+ globalCRLConfig *pki_backend.CrlConfig,
internalCRLConfig *issuing.InternalCRLConfigEntry,
issuers []issuing.IssuerID,
issuerIDEntryMap map[issuing.IssuerID]*issuing.IssuerEntry,
@@ -1868,7 +1829,7 @@ func buildAnyCRLsWithCerts(
return warnings, nil
}
-func isRevInfoIssuerValid(revInfo *revocationInfo, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool {
+func isRevInfoIssuerValid(revInfo *revocation.RevocationInfo, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool {
if len(revInfo.CertificateIssuer) > 0 {
issuerId := revInfo.CertificateIssuer
if _, issuerExists := issuerIDCertMap[issuerId]; issuerExists {
@@ -1879,20 +1840,6 @@ func isRevInfoIssuerValid(revInfo *revocationInfo, issuerIDCertMap map[issuing.I
return false
}
-func associateRevokedCertWithIsssuer(revInfo *revocationInfo, revokedCert *x509.Certificate, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool {
- for issuerId, issuerCert := range issuerIDCertMap {
- if bytes.Equal(revokedCert.RawIssuer, issuerCert.RawSubject) {
- if err := revokedCert.CheckSignatureFrom(issuerCert); err == nil {
- // Valid mapping. Add it to the specified entry.
- revInfo.CertificateIssuer = issuerId
- return true
- }
- }
- }
-
- return false
-}
-
func getLocalRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate, isDelta bool) ([]pkix.RevokedCertificate, map[issuing.IssuerID][]pkix.RevokedCertificate, error) {
var unassignedCerts []pkix.RevokedCertificate
revokedCertsMap := make(map[issuing.IssuerID][]pkix.RevokedCertificate)
@@ -1920,7 +1867,7 @@ func getLocalRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuing.
continue
}
- var revInfo revocationInfo
+ var revInfo revocation.RevocationInfo
revokedEntry, err := sc.Storage.Get(sc.Context, revokedPath+serial)
if err != nil {
return nil, nil, errutil.InternalError{Err: fmt.Sprintf("unable to fetch revoked cert with serial %s: %s", serial, err)}
@@ -1997,7 +1944,7 @@ func getLocalRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuing.
}
// Now we need to assign the revoked certificate to an issuer.
- foundParent := associateRevokedCertWithIsssuer(&revInfo, revokedCert, issuerIDCertMap)
+ foundParent := revInfo.AssociateRevokedCertWithIsssuer(revokedCert, issuerIDCertMap)
if !foundParent {
// If the parent isn't found, add it to the unassigned bucket.
unassignedCerts = append(unassignedCerts, newRevCert)
@@ -2084,7 +2031,7 @@ func getUnifiedRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuin
continue
}
- var xRevEntry unifiedRevocationEntry
+ var xRevEntry revocation.UnifiedRevocationEntry
if err := entryRaw.DecodeJSON(&xRevEntry); err != nil {
return nil, nil, fmt.Errorf("failed json decoding of unified revocation entry at path %v: %w ", serialPath, err)
}
@@ -2154,7 +2101,7 @@ func augmentWithRevokedIssuers(issuerIDEntryMap map[issuing.IssuerID]*issuing.Is
// Builds a CRL by going through the list of revoked certificates and building
// a new CRL with the stored revocation times and serial numbers.
-func buildCRL(sc *storageContext, crlInfo *crlConfig, forceNew bool, thisIssuerId issuing.IssuerID, revoked []pkix.RevokedCertificate, identifier issuing.CrlID, crlNumber int64, isUnified bool, isDelta bool, lastCompleteNumber int64) (*time.Time, error) {
+func buildCRL(sc *storageContext, crlInfo *pki_backend.CrlConfig, forceNew bool, thisIssuerId issuing.IssuerID, revoked []pkix.RevokedCertificate, identifier issuing.CrlID, crlNumber int64, isUnified bool, isDelta bool, lastCompleteNumber int64) (*time.Time, error) {
var revokedCerts []pkix.RevokedCertificate
crlLifetime, err := parseutil.ParseDurationSecond(crlInfo.Expiry)
@@ -2246,6 +2193,6 @@ WRITE:
// shouldLocalPathsUseUnified assuming a legacy path for a CRL/OCSP request, does our
// configuration say we should be returning the unified response or not
-func shouldLocalPathsUseUnified(cfg *crlConfig) bool {
+func shouldLocalPathsUseUnified(cfg *pki_backend.CrlConfig) bool {
return cfg.UnifiedCRL && cfg.UnifiedCRLOnExistingPaths
}
diff --git a/builtin/logical/pki/fields.go b/builtin/logical/pki/fields.go
index ba4edf7101..2888474268 100644
--- a/builtin/logical/pki/fields.go
+++ b/builtin/logical/pki/fields.go
@@ -166,11 +166,11 @@ Any values are added with OID 0.9.2342.19200300.100.1.1.`,
Name: "User ID(s)",
},
}
- fields["metadata"] = &framework.FieldSchema{
+ fields["cert_metadata"] = &framework.FieldSchema{
Type: framework.TypeString,
Description: `User supplied metadata to store associated with this certificate's serial number, base64 encoded`,
DisplayAttrs: &framework.DisplayAttributes{
- Name: "Metadata",
+ Name: "Certificate Metadata",
},
}
diff --git a/builtin/logical/pki/integration_test.go b/builtin/logical/pki/integration_test.go
index 73d7d113ad..1c3da7fa3a 100644
--- a/builtin/logical/pki/integration_test.go
+++ b/builtin/logical/pki/integration_test.go
@@ -718,6 +718,7 @@ func TestIntegrationOCSPClientWithPKI(t *testing.T) {
err = ocspClient.VerifyLeafCertificate(context.Background(), cert, issuer, conf)
require.Error(t, err)
+ require.Contains(t, err.Error(), serialNumber, "Expected revoked serial number to appear in err")
}
}
diff --git a/builtin/logical/pki/issuing/context.go b/builtin/logical/pki/issuing/context.go
new file mode 100644
index 0000000000..daa08a9ee7
--- /dev/null
+++ b/builtin/logical/pki/issuing/context.go
@@ -0,0 +1,22 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package issuing
+
+import "context"
+
+// IssuerRoleContext combines in a single struct an issuer and a role that we should
+// leverage to issue a certificate along with the
+type IssuerRoleContext struct {
+ context.Context
+ Role *RoleEntry
+ Issuer *IssuerEntry
+}
+
+func NewIssuerRoleContext(ctx context.Context, issuer *IssuerEntry, role *RoleEntry) IssuerRoleContext {
+ return IssuerRoleContext{
+ Context: ctx,
+ Role: role,
+ Issuer: issuer,
+ }
+}
diff --git a/builtin/logical/pki/issuing/issue_common.go b/builtin/logical/pki/issuing/issue_common.go
index a2db75d584..b1a67e2feb 100644
--- a/builtin/logical/pki/issuing/issue_common.go
+++ b/builtin/logical/pki/issuing/issue_common.go
@@ -17,7 +17,6 @@ import (
"github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/hashicorp/vault/builtin/logical/pki/parsing"
- "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/errutil"
@@ -64,6 +63,12 @@ type EntityInfo struct {
EntityID string
}
+type CertificateCounter interface {
+ IsInitialized() bool
+ IncrementTotalCertificatesCount(certsCounted bool, newSerial string)
+ IncrementTotalRevokedCertificatesCount(certsCounted bool, newSerial string)
+}
+
func NewEntityInfoFromReq(req *logical.Request) EntityInfo {
if req == nil {
return EntityInfo{}
@@ -86,6 +91,7 @@ type CreationBundleInput interface {
GetOptionalSkid() (interface{}, bool)
IsUserIdInSchema() (interface{}, bool)
GetUserIds() []string
+ IgnoreCSRSignature() bool
}
// GenerateCreationBundle is a shared function that reads parameters supplied
@@ -423,6 +429,7 @@ func GenerateCreationBundle(b logical.SystemView, role *RoleEntry, entityInfo En
NotBeforeDuration: role.NotBeforeDuration,
ForceAppendCaChain: caSign != nil,
SKID: skid,
+ IgnoreCSRSignature: cb.IgnoreCSRSignature(),
},
SigningBundle: caSign,
CSR: csr,
@@ -1012,7 +1019,7 @@ func ApplyIssuerLeafNotAfterBehavior(caSign *certutil.CAInfoBundle, notAfter tim
}
// StoreCertificate given a certificate bundle that was signed, persist the certificate to storage
-func StoreCertificate(ctx context.Context, s logical.Storage, certCounter pki_backend.CertificateCounter, certBundle *certutil.ParsedCertBundle) error {
+func StoreCertificate(ctx context.Context, s logical.Storage, certCounter CertificateCounter, certBundle *certutil.ParsedCertBundle) error {
hyphenSerialNumber := parsing.NormalizeSerialForStorageFromBigInt(certBundle.Certificate.SerialNumber)
key := PathCerts + hyphenSerialNumber
certsCounted := certCounter.IsInitialized()
diff --git a/builtin/logical/pki/issuing/issuers.go b/builtin/logical/pki/issuing/issuers.go
index a3e3658157..9ceff5b13c 100644
--- a/builtin/logical/pki/issuing/issuers.go
+++ b/builtin/logical/pki/issuing/issuers.go
@@ -4,6 +4,7 @@
package issuing
import (
+ "bytes"
"context"
"crypto/x509"
"fmt"
@@ -43,6 +44,13 @@ const (
LegacyCertBundlePath = "config/ca_bundle"
LegacyBundleShimID = IssuerID("legacy-entry-shim-id")
LegacyBundleShimKeyID = KeyID("legacy-entry-shim-key-id")
+
+ LegacyCRLPath = "crl"
+ DeltaCRLPath = "delta-crl"
+ DeltaCRLPathSuffix = "-delta"
+ UnifiedCRLPath = "unified-crl"
+ UnifiedDeltaCRLPath = "unified-delta-crl"
+ UnifiedCRLPathPrefix = "unified-"
)
type IssuerID string
@@ -131,8 +139,10 @@ type IssuerEntry struct {
Version uint `json:"version"`
}
+// GetCertificate returns a x509.Certificate of the CA certificate
+// represented by this issuer.
func (i IssuerEntry) GetCertificate() (*x509.Certificate, error) {
- cert, err := parsing.ParseCertificateFromBytes([]byte(i.Certificate))
+ cert, err := parsing.ParseCertificateFromString(i.Certificate)
if err != nil {
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse certificate from issuer: %s: %v", err.Error(), i.ID)}
}
@@ -140,6 +150,32 @@ func (i IssuerEntry) GetCertificate() (*x509.Certificate, error) {
return cert, nil
}
+// GetFullCaChain returns a slice of x509.Certificate values of this issuer full ca chain,
+// which starts with the CA certificate represented by this issuer followed by the entire CA chain
+func (i IssuerEntry) GetFullCaChain() ([]*x509.Certificate, error) {
+ var chains []*x509.Certificate
+ issuerCert, err := i.GetCertificate()
+ if err != nil {
+ return nil, err
+ }
+
+ chains = append(chains, issuerCert)
+
+ for rangeI, chainVal := range i.CAChain {
+ parsedChainVal, err := parsing.ParseCertificateFromString(chainVal)
+ if err != nil {
+ return nil, fmt.Errorf("error parsing issuer %s ca chain index value [%d]: %w", i.ID, rangeI, err)
+ }
+
+ if bytes.Equal(parsedChainVal.Raw, issuerCert.Raw) {
+ continue
+ }
+ chains = append(chains, parsedChainVal)
+ }
+
+ return chains, nil
+}
+
func (i IssuerEntry) EnsureUsage(usage IssuerUsage) error {
// We want to spit out a nice error message about missing usages.
if i.Usage.HasUsage(usage) {
@@ -209,6 +245,29 @@ func (i IssuerEntry) CanMaybeSignWithAlgo(algo x509.SignatureAlgorithm) error {
return fmt.Errorf("unable to use issuer of type %v to sign with %v key type", cert.PublicKeyAlgorithm.String(), algo.String())
}
+// ResolveAndFetchIssuerForIssuance takes a name or uuid referencing an issuer, loads the issuer
+// and validates that we have the associated private key and is allowed to perform issuance operations.
+func ResolveAndFetchIssuerForIssuance(ctx context.Context, s logical.Storage, issuerName string) (*IssuerEntry, error) {
+ if len(issuerName) == 0 {
+ return nil, fmt.Errorf("unable to fetch pki issuer: empty issuer name")
+ }
+ issuerId, err := ResolveIssuerReference(ctx, s, issuerName)
+ if err != nil {
+ return nil, fmt.Errorf("failed to resolve issuer %s: %w", issuerName, err)
+ }
+
+ issuer, err := FetchIssuerById(ctx, s, issuerId)
+ if err != nil {
+ return nil, fmt.Errorf("failed to load issuer %s: %w", issuerName, err)
+ }
+
+ if issuer.Usage.HasUsage(IssuanceUsage) && len(issuer.KeyID) > 0 {
+ return issuer, nil
+ }
+
+ return nil, fmt.Errorf("issuer %s missing proper issuance usage or doesn't have associated key", issuerName)
+}
+
func ResolveIssuerReference(ctx context.Context, s logical.Storage, reference string) (IssuerID, error) {
if reference == DefaultRef {
// Handle fetching the default issuer.
@@ -492,3 +551,38 @@ func GetLegacyCertBundle(ctx context.Context, s logical.Storage) (*IssuerEntry,
return issuer, cb, nil
}
+
+func ResolveIssuerCRLPath(ctx context.Context, storage logical.Storage, useLegacyBundleCaStorage bool, reference string, unified bool) (string, error) {
+ if useLegacyBundleCaStorage {
+ return "crl", nil
+ }
+
+ issuer, err := ResolveIssuerReference(ctx, storage, reference)
+ if err != nil {
+ return "crl", err
+ }
+
+ var crlConfig *InternalCRLConfigEntry
+ if unified {
+ crlConfig, err = GetUnifiedCRLConfig(ctx, storage)
+ if err != nil {
+ return "crl", err
+ }
+ } else {
+ crlConfig, err = GetLocalCRLConfig(ctx, storage)
+ if err != nil {
+ return "crl", err
+ }
+ }
+
+ if crlId, ok := crlConfig.IssuerIDCRLMap[issuer]; ok && len(crlId) > 0 {
+ path := fmt.Sprintf("crls/%v", crlId)
+ if unified {
+ path = ("unified-") + path
+ }
+
+ return path, nil
+ }
+
+ return "crl", fmt.Errorf("unable to find CRL for issuer: id:%v/ref:%v", issuer, reference)
+}
diff --git a/builtin/logical/pki/issuing/keys.go b/builtin/logical/pki/issuing/keys.go
index 0e703ddc6c..c008811743 100644
--- a/builtin/logical/pki/issuing/keys.go
+++ b/builtin/logical/pki/issuing/keys.go
@@ -5,6 +5,8 @@ package issuing
import (
"context"
+ "crypto"
+ "encoding/pem"
"fmt"
"github.com/hashicorp/vault/builtin/logical/pki/managed_key"
@@ -150,3 +152,34 @@ func GetManagedKeyUUID(key *KeyEntry) (managed_key.UUIDKey, error) {
}
return managed_key.ExtractManagedKeyId([]byte(key.PrivateKey))
}
+
+func GetSignerFromKeyEntry(ctx context.Context, mkv managed_key.PkiManagedKeyView, keyEntry *KeyEntry) (crypto.Signer, certutil.PrivateKeyType, error) {
+ if keyEntry.PrivateKeyType == certutil.UnknownPrivateKey {
+ return nil, certutil.UnknownPrivateKey, fmt.Errorf("unsupported unknown private key type for key: %s (%s)", keyEntry.ID, keyEntry.Name)
+ }
+
+ if keyEntry.IsManagedPrivateKey() {
+ managedKeyId, err := GetManagedKeyUUID(keyEntry)
+ if err != nil {
+ return nil, certutil.UnknownPrivateKey, fmt.Errorf("unable to get managed key uuid: %w", err)
+ }
+ bundle, actualKeyType, err := managed_key.CreateKmsKeyBundle(ctx, mkv, managedKeyId)
+ if err != nil {
+ return nil, certutil.UnknownPrivateKey, fmt.Errorf("failed to create kms key bundle from managed key uuid %s: %w", managedKeyId, err)
+ }
+
+ // The bundle's PrivateKeyType value is set to a ManagedKeyType so use the actual key type value
+ return bundle.PrivateKey, actualKeyType, nil
+ }
+
+ pemBlock, _ := pem.Decode([]byte(keyEntry.PrivateKey))
+ if pemBlock == nil {
+ return nil, certutil.UnknownPrivateKey, fmt.Errorf("no data found in PEM block")
+ }
+
+ signer, _, err := certutil.ParseDERKey(pemBlock.Bytes)
+ if err != nil {
+ return nil, certutil.UnknownPrivateKey, fmt.Errorf("failed to parse PEM block: %w", err)
+ }
+ return signer, keyEntry.PrivateKeyType, nil
+}
diff --git a/builtin/logical/pki/issuing/sign_cert.go b/builtin/logical/pki/issuing/sign_cert.go
index 773e8b2a96..c6548f6952 100644
--- a/builtin/logical/pki/issuing/sign_cert.go
+++ b/builtin/logical/pki/issuing/sign_cert.go
@@ -23,20 +23,26 @@ type SignCertInput interface {
GetPermittedDomains() []string
}
-func NewBasicSignCertInput(csr *x509.CertificateRequest, isCA bool, useCSRValues bool) BasicSignCertInput {
+func NewBasicSignCertInput(csr *x509.CertificateRequest, isCA, useCSRValues bool) BasicSignCertInput {
+ return NewBasicSignCertInputWithIgnore(csr, isCA, useCSRValues, false)
+}
+
+func NewBasicSignCertInputWithIgnore(csr *x509.CertificateRequest, isCA, useCSRValues, ignoreCsrSignature bool) BasicSignCertInput {
return BasicSignCertInput{
- isCA: isCA,
- useCSRValues: useCSRValues,
- csr: csr,
+ isCA: isCA,
+ useCSRValues: useCSRValues,
+ csr: csr,
+ ignoreCsrSignature: ignoreCsrSignature,
}
}
var _ SignCertInput = BasicSignCertInput{}
type BasicSignCertInput struct {
- isCA bool
- useCSRValues bool
- csr *x509.CertificateRequest
+ isCA bool
+ useCSRValues bool
+ csr *x509.CertificateRequest
+ ignoreCsrSignature bool
}
func (b BasicSignCertInput) GetTTL() int {
@@ -91,6 +97,10 @@ func (b BasicSignCertInput) GetCSR() (*x509.CertificateRequest, error) {
return b.csr, nil
}
+func (b BasicSignCertInput) IgnoreCSRSignature() bool {
+ return b.ignoreCsrSignature
+}
+
func (b BasicSignCertInput) IsCA() bool {
return b.isCA
}
diff --git a/builtin/logical/pki/key_util.go b/builtin/logical/pki/key_util.go
index c8538908aa..6fe17d41e1 100644
--- a/builtin/logical/pki/key_util.go
+++ b/builtin/logical/pki/key_util.go
@@ -17,7 +17,7 @@ import (
)
func comparePublicKey(sc *storageContext, key *issuing.KeyEntry, publicKey crypto.PublicKey) (bool, error) {
- publicKeyForKeyEntry, err := getPublicKey(sc.Context, sc.Backend, key)
+ publicKeyForKeyEntry, err := getPublicKey(sc.Context, sc.GetPkiManagedView(), key)
if err != nil {
return false, err
}
@@ -25,9 +25,9 @@ func comparePublicKey(sc *storageContext, key *issuing.KeyEntry, publicKey crypt
return certutil.ComparePublicKeysAndType(publicKeyForKeyEntry, publicKey)
}
-func getPublicKey(ctx context.Context, b *backend, key *issuing.KeyEntry) (crypto.PublicKey, error) {
+func getPublicKey(ctx context.Context, mkv managed_key.PkiManagedKeyView, key *issuing.KeyEntry) (crypto.PublicKey, error) {
if key.PrivateKeyType == certutil.ManagedPrivateKey {
- return managed_key.GetPublicKeyFromKeyBytes(ctx, b, []byte(key.PrivateKey))
+ return managed_key.GetPublicKeyFromKeyBytes(ctx, mkv, []byte(key.PrivateKey))
}
signer, _, _, err := getSignerFromKeyEntryBytes(key)
diff --git a/builtin/logical/pki/metadata.pb.go b/builtin/logical/pki/metadata.pb.go
index 412ae20ae6..209f5fcce0 100644
--- a/builtin/logical/pki/metadata.pb.go
+++ b/builtin/logical/pki/metadata.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: builtin/logical/pki/metadata.proto
@@ -134,7 +134,7 @@ func file_builtin_logical_pki_metadata_proto_rawDescGZIP() []byte {
}
var file_builtin_logical_pki_metadata_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_builtin_logical_pki_metadata_proto_goTypes = []interface{}{
+var file_builtin_logical_pki_metadata_proto_goTypes = []any{
(*CertificateMetadata)(nil), // 0: pki.CertificateMetadata
(*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp
}
@@ -153,7 +153,7 @@ func file_builtin_logical_pki_metadata_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_builtin_logical_pki_metadata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_builtin_logical_pki_metadata_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*CertificateMetadata); i {
case 0:
return &v.state
@@ -166,7 +166,7 @@ func file_builtin_logical_pki_metadata_proto_init() {
}
}
}
- file_builtin_logical_pki_metadata_proto_msgTypes[0].OneofWrappers = []interface{}{}
+ file_builtin_logical_pki_metadata_proto_msgTypes[0].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
diff --git a/builtin/logical/pki/metadata_oss.go b/builtin/logical/pki/metadata_oss.go
index d1ed74e8ba..fe64d57c30 100644
--- a/builtin/logical/pki/metadata_oss.go
+++ b/builtin/logical/pki/metadata_oss.go
@@ -9,7 +9,6 @@ import (
"context"
"crypto/x509"
"errors"
- "math/big"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
@@ -18,18 +17,14 @@ import (
var ErrMetadataIsEntOnly = errors.New("certificate metadata is only supported on Vault Enterprise")
-func storeMetadata(ctx context.Context, storage logical.Storage, issuerId issuing.IssuerID, role string, certificate *x509.Certificate, metadata interface{}) error {
+func storeCertMetadata(ctx context.Context, storage logical.Storage, issuerId issuing.IssuerID, role string, certificate *x509.Certificate, certMetadata interface{}) error {
return ErrMetadataIsEntOnly
}
-func GetCertificateMetadata(ctx context.Context, storage logical.Storage, serialNumber *big.Int) (*CertificateMetadata, error) {
- return nil, ErrMetadataIsEntOnly
-}
-
func (b *backend) doTidyCertMetadata(ctx context.Context, req *logical.Request, logger hclog.Logger, config *tidyConfig) error {
return ErrMetadataIsEntOnly
}
-func validateMetadataConfiguration(role *issuing.RoleEntry) error {
+func validateCertMetadataConfiguration(role *issuing.RoleEntry) error {
return ErrMetadataIsEntOnly
}
diff --git a/builtin/logical/pki/parsing/certificate.go b/builtin/logical/pki/parsing/certificate.go
index c8f68b98e9..9cd52af46e 100644
--- a/builtin/logical/pki/parsing/certificate.go
+++ b/builtin/logical/pki/parsing/certificate.go
@@ -12,6 +12,14 @@ import (
"github.com/hashicorp/vault/sdk/helper/certutil"
)
+func SerialFromCert(cert *x509.Certificate) string {
+ return SerialFromBigInt(cert.SerialNumber)
+}
+
+func SerialFromBigInt(serial *big.Int) string {
+ return strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":"))
+}
+
// NormalizeSerialForStorageFromBigInt given a serial number, format it as a string
// that is safe to store within a filesystem
func NormalizeSerialForStorageFromBigInt(serial *big.Int) string {
diff --git a/builtin/logical/pki/path_acme_order.go b/builtin/logical/pki/path_acme_order.go
index c0375e21bf..197b7d0916 100644
--- a/builtin/logical/pki/path_acme_order.go
+++ b/builtin/logical/pki/path_acme_order.go
@@ -271,7 +271,7 @@ func (b *backend) acmeFinalizeOrderHandler(ac *acmeContext, r *logical.Request,
return nil, err
}
- err = issuing.StoreCertificate(ac.sc.Context, ac.sc.Storage, ac.sc.Backend.GetCertificateCounter(), signedCertBundle)
+ err = issuing.StoreCertificate(ac.sc.Context, ac.sc.Storage, ac.sc.GetCertificateCounter(), signedCertBundle)
if err != nil {
return nil, err
}
@@ -476,7 +476,7 @@ func removeDuplicatesAndSortIps(ipIdentifiers []net.IP) []net.IP {
func maybeAugmentReqDataWithSuitableCN(ac *acmeContext, csr *x509.CertificateRequest, data *framework.FieldData) {
// Role doesn't require a CN, so we don't care.
- if !ac.role.RequireCN {
+ if !ac.Role.RequireCN {
return
}
@@ -522,9 +522,9 @@ func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil.
// (TLS) clients are mostly verifying against server's DNS SANs.
maybeAugmentReqDataWithSuitableCN(ac, csr, data)
- signingBundle, issuerId, err := ac.sc.fetchCAInfoWithIssuer(ac.issuer.ID.String(), issuing.IssuanceUsage)
+ signingBundle, issuerId, err := ac.sc.fetchCAInfoWithIssuer(ac.Issuer.ID.String(), issuing.IssuanceUsage)
if err != nil {
- return nil, "", fmt.Errorf("failed loading CA %s: %w", ac.issuer.ID.String(), err)
+ return nil, "", fmt.Errorf("failed loading CA %s: %w", ac.Issuer.ID.String(), err)
}
// ACME issued cert will override the TTL values to truncate to the issuer's
@@ -536,17 +536,17 @@ func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil.
input := &inputBundle{
req: &logical.Request{},
apiData: data,
- role: ac.role,
+ role: ac.Role,
}
- normalNotAfter, _, err := getCertificateNotAfter(ac.sc.Backend, input, signingBundle)
+ normalNotAfter, _, err := getCertificateNotAfter(ac.sc.System(), input, signingBundle)
if err != nil {
return nil, "", fmt.Errorf("failed computing certificate TTL from role/mount: %v: %w", err, ErrMalformed)
}
// We only allow ServerAuth key usage from ACME issued certs
// when configuration does not allow usage of ExtKeyusage field.
- config, err := ac.sc.Backend.GetAcmeState().getConfigWithUpdate(ac.sc)
+ config, err := ac.acmeState.getConfigWithUpdate(ac.sc)
if err != nil {
return nil, "", fmt.Errorf("failed to fetch ACME configuration: %w", err)
}
@@ -573,7 +573,7 @@ func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil.
// unit, we have no way of validating this (via ACME here, without perhaps
// an external policy engine), and thus should not be setting it on our
// final issued certificate.
- parsedBundle, _, err := signCert(ac.sc.Backend, input, signingBundle, false /* is_ca=false */, false /* use_csr_values */)
+ parsedBundle, _, err := signCert(ac.sc.System(), input, signingBundle, false /* is_ca=false */, false /* use_csr_values */)
if err != nil {
return nil, "", fmt.Errorf("%w: refusing to sign CSR: %s", ErrBadCSR, err.Error())
}
@@ -730,7 +730,7 @@ func (b *backend) acmeNewOrderHandler(ac *acmeContext, _ *logical.Request, _ *fr
return nil, err
}
- err = b.validateIdentifiersAgainstRole(ac.role, identifiers)
+ err = b.validateIdentifiersAgainstRole(ac.Role, identifiers)
if err != nil {
return nil, err
}
diff --git a/builtin/logical/pki/path_acme_revoke.go b/builtin/logical/pki/path_acme_revoke.go
index 8b4a90529c..70d700d7d4 100644
--- a/builtin/logical/pki/path_acme_revoke.go
+++ b/builtin/logical/pki/path_acme_revoke.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -83,7 +84,7 @@ func (b *backend) acmeRevocationHandler(acmeCtx *acmeContext, _ *logical.Request
// Fetch the CRL config as we need it to ultimately do the
// revocation. This should be cached and thus relatively fast.
- config, err := b.CrlBuilder().getConfigWithUpdate(acmeCtx.sc)
+ config, err := b.CrlBuilder().GetConfigWithUpdate(acmeCtx.sc)
if err != nil {
return nil, fmt.Errorf("unable to revoke certificate: failed reading revocation config: %v: %w", err, ErrServerInternal)
}
@@ -134,7 +135,7 @@ func (b *backend) acmeRevocationHandler(acmeCtx *acmeContext, _ *logical.Request
return b.acmeRevocationByAccount(acmeCtx, userCtx, cert, config)
}
-func (b *backend) acmeRevocationByPoP(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *crlConfig) (*logical.Response, error) {
+func (b *backend) acmeRevocationByPoP(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *pki_backend.CrlConfig) (*logical.Response, error) {
// Since this account does not exist, ensure we've gotten a private key
// matching the certificate's public key. This private key isn't
// explicitly provided, but instead provided by proxy (public key,
@@ -160,7 +161,7 @@ func (b *backend) acmeRevocationByPoP(acmeCtx *acmeContext, userCtx *jwsCtx, cer
return revokeCert(acmeCtx.sc, config, cert)
}
-func (b *backend) acmeRevocationByAccount(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *crlConfig) (*logical.Response, error) {
+func (b *backend) acmeRevocationByAccount(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *pki_backend.CrlConfig) (*logical.Response, error) {
// Fetch the account; disallow revocations from non-valid-status accounts.
_, err := requireValidAcmeAccount(acmeCtx, userCtx)
if err != nil {
diff --git a/builtin/logical/pki/path_config_acme.go b/builtin/logical/pki/path_config_acme.go
index ac021a4e9b..2a233cad74 100644
--- a/builtin/logical/pki/path_config_acme.go
+++ b/builtin/logical/pki/path_config_acme.go
@@ -57,7 +57,7 @@ var (
rolePrefixLength = len(rolePrefix)
)
-func (sc *storageContext) getAcmeConfig() (*acmeConfigEntry, error) {
+func getAcmeConfig(sc *storageContext) (*acmeConfigEntry, error) {
entry, err := sc.Storage.Get(sc.Context, storageAcmeConfig)
if err != nil {
return nil, err
diff --git a/builtin/logical/pki/path_config_crl.go b/builtin/logical/pki/path_config_crl.go
index cd28643f4a..81815ff215 100644
--- a/builtin/logical/pki/path_config_crl.go
+++ b/builtin/logical/pki/path_config_crl.go
@@ -9,46 +9,13 @@ import (
"net/http"
"github.com/hashicorp/go-secure-stdlib/parseutil"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/helper/constants"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/errutil"
"github.com/hashicorp/vault/sdk/logical"
)
-const latestCrlConfigVersion = 1
-
-// CRLConfig holds basic CRL configuration information
-type crlConfig struct {
- Version int `json:"version"`
- Expiry string `json:"expiry"`
- Disable bool `json:"disable"`
- OcspDisable bool `json:"ocsp_disable"`
- AutoRebuild bool `json:"auto_rebuild"`
- AutoRebuildGracePeriod string `json:"auto_rebuild_grace_period"`
- OcspExpiry string `json:"ocsp_expiry"`
- EnableDelta bool `json:"enable_delta"`
- DeltaRebuildInterval string `json:"delta_rebuild_interval"`
- UseGlobalQueue bool `json:"cross_cluster_revocation"`
- UnifiedCRL bool `json:"unified_crl"`
- UnifiedCRLOnExistingPaths bool `json:"unified_crl_on_existing_paths"`
-}
-
-// Implicit default values for the config if it does not exist.
-var defaultCrlConfig = crlConfig{
- Version: latestCrlConfigVersion,
- Expiry: "72h",
- Disable: false,
- OcspDisable: false,
- OcspExpiry: "12h",
- AutoRebuild: false,
- AutoRebuildGracePeriod: "12h",
- EnableDelta: false,
- DeltaRebuildInterval: "15m",
- UseGlobalQueue: false,
- UnifiedCRL: false,
- UnifiedCRLOnExistingPaths: false,
-}
-
func pathConfigCRL(b *backend) *framework.Path {
return &framework.Path{
Pattern: "config/crl",
@@ -424,7 +391,7 @@ func (b *backend) pathCRLWrite(ctx context.Context, req *logical.Request, d *fra
// auto-rebuild and we aren't now or equivalently, we changed our
// mind about delta CRLs and need a new complete one or equivalently,
// we changed our mind about unified CRLs), rotate the CRLs.
- warnings, crlErr := b.CrlBuilder().rebuild(sc, true)
+ warnings, crlErr := b.CrlBuilder().Rebuild(sc, true)
if crlErr != nil {
switch crlErr.(type) {
case errutil.UserError:
@@ -441,7 +408,7 @@ func (b *backend) pathCRLWrite(ctx context.Context, req *logical.Request, d *fra
return resp, nil
}
-func genResponseFromCrlConfig(config *crlConfig) *logical.Response {
+func genResponseFromCrlConfig(config *pki_backend.CrlConfig) *logical.Response {
return &logical.Response{
Data: map[string]interface{}{
"expiry": config.Expiry,
diff --git a/builtin/logical/pki/path_fetch.go b/builtin/logical/pki/path_fetch.go
index 646998c9c7..c18c73a1ce 100644
--- a/builtin/logical/pki/path_fetch.go
+++ b/builtin/logical/pki/path_fetch.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/helper/constants"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/errutil"
@@ -306,7 +307,7 @@ func (b *backend) pathFetchRead(ctx context.Context, req *logical.Request, data
contentType = "application/pkix-cert"
}
case req.Path == "crl" || req.Path == "crl/pem" || req.Path == "crl/delta" || req.Path == "crl/delta/pem" || req.Path == "cert/crl" || req.Path == "cert/crl/raw" || req.Path == "cert/crl/raw/pem" || req.Path == "cert/delta-crl" || req.Path == "cert/delta-crl/raw" || req.Path == "cert/delta-crl/raw/pem" || req.Path == "unified-crl" || req.Path == "unified-crl/pem" || req.Path == "unified-crl/delta" || req.Path == "unified-crl/delta/pem" || req.Path == "cert/unified-crl" || req.Path == "cert/unified-crl/raw" || req.Path == "cert/unified-crl/raw/pem" || req.Path == "cert/unified-delta-crl" || req.Path == "cert/unified-delta-crl/raw" || req.Path == "cert/unified-delta-crl/raw/pem":
- config, err := b.CrlBuilder().getConfigWithUpdate(sc)
+ config, err := b.CrlBuilder().GetConfigWithUpdate(sc)
if err != nil {
retErr = err
goto reply
@@ -360,7 +361,9 @@ func (b *backend) pathFetchRead(ctx context.Context, req *logical.Request, data
contentType = "application/pem-certificate-chain"
}
default:
- serial = data.Get("serial").(string)
+ if ser, ok := data.GetOk("serial"); ok {
+ serial = ser.(string)
+ }
pemType = "CERTIFICATE"
}
if len(serial) == 0 {
@@ -452,7 +455,7 @@ func (b *backend) pathFetchRead(ctx context.Context, req *logical.Request, data
}
}
if revokedEntry != nil {
- var revInfo revocationInfo
+ var revInfo revocation.RevocationInfo
err := revokedEntry.DecodeJSON(&revInfo)
if err != nil {
return logical.ErrorResponse(fmt.Sprintf("Error decoding revocation entry for serial %s: %s", serial, err)), nil
diff --git a/builtin/logical/pki/path_fetch_issuers.go b/builtin/logical/pki/path_fetch_issuers.go
index bd5d8e6356..6e6cf42010 100644
--- a/builtin/logical/pki/path_fetch_issuers.go
+++ b/builtin/logical/pki/path_fetch_issuers.go
@@ -1121,7 +1121,7 @@ func (b *backend) pathDeleteIssuer(ctx context.Context, req *logical.Request, da
// Finally, we need to rebuild both the local and the unified CRLs. This
// will free up any now unnecessary space used in both the CRL config
// and for the underlying CRL.
- warnings, err := b.CrlBuilder().rebuild(sc, true)
+ warnings, err := b.CrlBuilder().Rebuild(sc, true)
if err != nil {
return nil, err
}
@@ -1231,7 +1231,7 @@ func (b *backend) pathGetIssuerCRL(ctx context.Context, req *logical.Request, da
}
sc := b.makeStorageContext(ctx, req.Storage)
- warnings, err := b.CrlBuilder().rebuildIfForced(sc)
+ warnings, err := b.CrlBuilder().RebuildIfForced(sc)
if err != nil {
return nil, err
}
@@ -1271,7 +1271,7 @@ func (b *backend) pathGetIssuerCRL(ctx context.Context, req *logical.Request, da
return response, nil
}
- crlPath, err := sc.resolveIssuerCRLPath(issuerName, isUnified)
+ crlPath, err := issuing.ResolveIssuerCRLPath(sc.GetContext(), sc.GetStorage(), sc.UseLegacyBundleCaStorage(), issuerName, isUnified)
if err != nil {
return nil, err
}
diff --git a/builtin/logical/pki/path_fetch_keys.go b/builtin/logical/pki/path_fetch_keys.go
index 0cf826d6f2..b0d1d9d680 100644
--- a/builtin/logical/pki/path_fetch_keys.go
+++ b/builtin/logical/pki/path_fetch_keys.go
@@ -267,7 +267,7 @@ func (b *backend) pathGetKeyHandler(ctx context.Context, req *logical.Request, d
return nil, errutil.InternalError{Err: fmt.Sprintf("failed fetching managed key info from key id %s (%s): %v", key.ID, key.Name, err)}
}
- pkForSkid, err = managed_key.GetManagedKeyPublicKey(sc.Context, sc.Backend, managedKeyUUID)
+ pkForSkid, err = managed_key.GetManagedKeyPublicKey(sc.Context, sc.GetPkiManagedView(), managedKeyUUID)
if err != nil {
return nil, err
}
diff --git a/builtin/logical/pki/path_issue_sign.go b/builtin/logical/pki/path_issue_sign.go
index fde485ecb3..57ae2caef7 100644
--- a/builtin/logical/pki/path_issue_sign.go
+++ b/builtin/logical/pki/path_issue_sign.go
@@ -341,17 +341,17 @@ func (b *backend) pathSignVerbatim(ctx context.Context, req *logical.Request, da
func (b *backend) pathIssueSignCert(ctx context.Context, req *logical.Request, data *framework.FieldData, role *issuing.RoleEntry, useCSR, useCSRValues bool) (*logical.Response, error) {
// Error out early if incompatible fields set:
- metadata, metadataInRequest := data.GetOk("metadata")
+ certMetadata, metadataInRequest := data.GetOk("cert_metadata")
if metadataInRequest {
- err := validateMetadataConfiguration(role)
+ err := validateCertMetadataConfiguration(role)
if err != nil {
return nil, err
}
}
- // If storing the certificate or metadata about this certificate and on a performance standby, forward this request
+ // If storing the certificate or certMetadata about this certificate and on a performance standby, forward this request
// on to the primary
- // Allow performance secondaries to generate and store certificates and metadata locally to them.
+ // Allow performance secondaries to generate and store certificates and certMetadata locally to them.
needsStorage := !role.NoStore || (metadataInRequest && !role.NoStoreMetadata && issuing.MetadataPermitted)
if needsStorage && b.System().ReplicationState().HasState(consts.ReplicationPerformanceStandby) {
return nil, logical.ErrReadOnly
@@ -417,7 +417,7 @@ func (b *backend) pathIssueSignCert(ctx context.Context, req *logical.Request, d
var parsedBundle *certutil.ParsedCertBundle
var warnings []string
if useCSR {
- parsedBundle, warnings, err = signCert(b, input, signingBundle, false, useCSRValues)
+ parsedBundle, warnings, err = signCert(b.System(), input, signingBundle, false, useCSRValues)
} else {
parsedBundle, warnings, err = generateCert(sc, input, signingBundle, false, rand.Reader)
}
@@ -449,13 +449,13 @@ func (b *backend) pathIssueSignCert(ctx context.Context, req *logical.Request, d
}
}
- if metadataInRequest && len(metadata.(string)) > 0 {
- metadataBytes, err := base64.StdEncoding.DecodeString(metadata.(string))
+ if metadataInRequest {
+ metadataBytes, err := base64.StdEncoding.DecodeString(certMetadata.(string))
if err != nil {
// TODO: Should we clean up the original cert here?
return nil, err
}
- err = storeMetadata(ctx, req.Storage, issuerId, role.Name, parsedBundle.Certificate, metadataBytes)
+ err = storeCertMetadata(ctx, req.Storage, issuerId, role.Name, parsedBundle.Certificate, metadataBytes)
if err != nil {
// TODO: Should we clean up the original cert here?
return nil, err
diff --git a/builtin/logical/pki/path_manage_issuers.go b/builtin/logical/pki/path_manage_issuers.go
index e5bb045031..0a0d4ff21b 100644
--- a/builtin/logical/pki/path_manage_issuers.go
+++ b/builtin/logical/pki/path_manage_issuers.go
@@ -14,6 +14,7 @@ import (
"time"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/errutil"
"github.com/hashicorp/vault/sdk/logical"
@@ -407,7 +408,7 @@ func (b *backend) pathImportIssuers(ctx context.Context, req *logical.Request, d
}
if len(createdIssuers) > 0 {
- warnings, err := b.CrlBuilder().rebuild(sc, true)
+ warnings, err := b.CrlBuilder().Rebuild(sc, true)
if err != nil {
// Before returning, check if the error message includes the
// string "PSS". If so, it indicates we might've wanted to modify
@@ -677,7 +678,7 @@ func (b *backend) pathRevokeIssuer(ctx context.Context, req *logical.Request, da
// Now, if the parent issuer exists within this mount, we'd have written
// a storage entry for this certificate, making it appear as any other
- // leaf. We need to add a revocationInfo entry for this into storage,
+ // leaf. We need to add a RevocationInfo entry for this into storage,
// so that it appears as if it was revoked.
//
// This is a _necessary_ but not necessarily _sufficient_ step to
@@ -712,7 +713,7 @@ func (b *backend) pathRevokeIssuer(ctx context.Context, req *logical.Request, da
//
// We'll let a cleanup pass or CRL build identify the issuer for
// us.
- revInfo := revocationInfo{
+ revInfo := revocation.RevocationInfo{
CertificateBytes: issuerCert.Raw,
RevocationTime: issuer.RevocationTime,
RevocationTimeUTC: issuer.RevocationTimeUTC,
@@ -731,7 +732,7 @@ func (b *backend) pathRevokeIssuer(ctx context.Context, req *logical.Request, da
}
// Rebuild the CRL to include the newly revoked issuer.
- warnings, crlErr := b.CrlBuilder().rebuild(sc, false)
+ warnings, crlErr := b.CrlBuilder().Rebuild(sc, false)
if crlErr != nil {
switch crlErr.(type) {
case errutil.UserError:
diff --git a/builtin/logical/pki/path_ocsp.go b/builtin/logical/pki/path_ocsp.go
index 2a5a1b8dc7..ea93b5da4a 100644
--- a/builtin/logical/pki/path_ocsp.go
+++ b/builtin/logical/pki/path_ocsp.go
@@ -19,8 +19,11 @@ import (
"strings"
"time"
+ "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/errutil"
@@ -156,7 +159,7 @@ func buildOcspPostWithPath(b *backend, pattern string, displayAttrs *framework.D
func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, data *framework.FieldData) (*logical.Response, error) {
sc := b.makeStorageContext(ctx, request.Storage)
- cfg, err := b.CrlBuilder().getConfigWithUpdate(sc)
+ cfg, err := b.CrlBuilder().GetConfigWithUpdate(sc)
if err != nil || cfg.OcspDisable || (isUnifiedOcspPath(request) && !cfg.UnifiedCRL) {
return OcspUnauthorizedResponse, nil
}
@@ -175,7 +178,7 @@ func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, dat
ocspStatus, err := getOcspStatus(sc, ocspReq, useUnifiedStorage)
if err != nil {
- return logAndReturnInternalError(b, err), nil
+ return logAndReturnInternalError(b.Logger(), err), nil
}
caBundle, issuer, err := lookupOcspIssuer(sc, ocspReq, ocspStatus.issuerID)
@@ -193,12 +196,12 @@ func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, dat
// https://www.rfc-editor.org/rfc/rfc5019#section-2.2.3
return OcspUnauthorizedResponse, nil
}
- return logAndReturnInternalError(b, err), nil
+ return logAndReturnInternalError(b.Logger(), err), nil
}
byteResp, err := genResponse(cfg, caBundle, ocspStatus, ocspReq.HashAlgorithm, issuer.RevocationSigAlg)
if err != nil {
- return logAndReturnInternalError(b, err), nil
+ return logAndReturnInternalError(b.Logger(), err), nil
}
return &logical.Response{
@@ -210,7 +213,7 @@ func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, dat
}, nil
}
-func canUseUnifiedStorage(req *logical.Request, cfg *crlConfig) bool {
+func canUseUnifiedStorage(req *logical.Request, cfg *pki_backend.CrlConfig) bool {
if isUnifiedOcspPath(req) {
return true
}
@@ -224,13 +227,13 @@ func isUnifiedOcspPath(req *logical.Request) bool {
return strings.HasPrefix(req.Path, "unified-ocsp")
}
-func generateUnknownResponse(cfg *crlConfig, sc *storageContext, ocspReq *ocsp.Request) *logical.Response {
+func generateUnknownResponse(cfg *pki_backend.CrlConfig, sc *storageContext, ocspReq *ocsp.Request) *logical.Response {
// Generate an Unknown OCSP response, signing with the default issuer from the mount as we did
// not match the request's issuer. If no default issuer can be used, return with Unauthorized as there
// isn't much else we can do at this point.
config, err := sc.getIssuersConfig()
if err != nil {
- return logAndReturnInternalError(sc.Backend, err)
+ return logAndReturnInternalError(sc.Logger(), err)
}
if config.DefaultIssuerId == "" {
@@ -245,7 +248,7 @@ func generateUnknownResponse(cfg *crlConfig, sc *storageContext, ocspReq *ocsp.R
// no way to sign a response so Unauthorized it is.
return OcspUnauthorizedResponse
}
- return logAndReturnInternalError(sc.Backend, err)
+ return logAndReturnInternalError(sc.Logger(), err)
}
if !issuer.Usage.HasUsage(issuing.OCSPSigningUsage) {
@@ -260,7 +263,7 @@ func generateUnknownResponse(cfg *crlConfig, sc *storageContext, ocspReq *ocsp.R
byteResp, err := genResponse(cfg, caBundle, info, ocspReq.HashAlgorithm, issuer.RevocationSigAlg)
if err != nil {
- return logAndReturnInternalError(sc.Backend, err)
+ return logAndReturnInternalError(sc.Logger(), err)
}
return &logical.Response{
@@ -313,12 +316,12 @@ func fetchDerEncodedRequest(request *logical.Request, data *framework.FieldData)
}
}
-func logAndReturnInternalError(b *backend, err error) *logical.Response {
+func logAndReturnInternalError(logger hclog.Logger, err error) *logical.Response {
// Since OCSP might be a high traffic endpoint, we will log at debug level only
// any internal errors we do get. There is no way for us to return to the end-user
// errors, so we rely on the log statement to help in debugging possible
// issues in the field.
- b.Logger().Debug("OCSP internal error", "error", err)
+ logger.Debug("OCSP internal error", "error", err)
return OcspInternalErrorResponse
}
@@ -334,7 +337,7 @@ func getOcspStatus(sc *storageContext, ocspReq *ocsp.Request, useUnifiedStorage
}
if revEntryRaw != nil {
- var revEntry revocationInfo
+ var revEntry revocation.RevocationInfo
if err := revEntryRaw.DecodeJSON(&revEntry); err != nil {
return nil, err
}
@@ -433,7 +436,7 @@ func getOcspIssuerParsedBundle(sc *storageContext, issuerId issuing.IssuerID) (*
return nil, nil, ErrIssuerHasNoKey
}
- caBundle, err := parseCABundle(sc.Context, sc.Backend, bundle)
+ caBundle, err := parseCABundle(sc.Context, sc.GetPkiManagedView(), bundle)
if err != nil {
return nil, nil, err
}
@@ -446,7 +449,7 @@ func lookupIssuerIds(sc *storageContext, optRevokedIssuer issuing.IssuerID) ([]i
return []issuing.IssuerID{optRevokedIssuer}, nil
}
- if sc.Backend.UseLegacyBundleCaStorage() {
+ if sc.UseLegacyBundleCaStorage() {
return []issuing.IssuerID{legacyBundleShimID}, nil
}
@@ -474,7 +477,7 @@ func doesRequestMatchIssuer(parsedBundle *certutil.ParsedCertBundle, req *ocsp.R
return bytes.Equal(req.IssuerKeyHash, issuerKeyHash) && bytes.Equal(req.IssuerNameHash, issuerNameHash), nil
}
-func genResponse(cfg *crlConfig, caBundle *certutil.ParsedCertBundle, info *ocspRespInfo, reqHash crypto.Hash, revSigAlg x509.SignatureAlgorithm) ([]byte, error) {
+func genResponse(cfg *pki_backend.CrlConfig, caBundle *certutil.ParsedCertBundle, info *ocspRespInfo, reqHash crypto.Hash, revSigAlg x509.SignatureAlgorithm) ([]byte, error) {
curTime := time.Now()
duration, err := parseutil.ParseDurationSecond(cfg.OcspExpiry)
if err != nil {
diff --git a/builtin/logical/pki/path_ocsp_test.go b/builtin/logical/pki/path_ocsp_test.go
index baeb49cb1d..517b55de79 100644
--- a/builtin/logical/pki/path_ocsp_test.go
+++ b/builtin/logical/pki/path_ocsp_test.go
@@ -19,6 +19,8 @@ import (
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
"github.com/hashicorp/vault/sdk/logical"
@@ -163,7 +165,7 @@ func TestOcsp_InvalidIssuerIdInRevocationEntry(t *testing.T) {
// Twiddle the entry so that the issuer id is no longer valid.
storagePath := revokedPath + normalizeSerial(serial)
- var revInfo revocationInfo
+ var revInfo revocation.RevocationInfo
revEntry, err := s.Get(ctx, storagePath)
require.NoError(t, err, "failed looking up storage path: %s", storagePath)
err = revEntry.DecodeJSON(&revInfo)
@@ -207,7 +209,7 @@ func TestOcsp_UnknownIssuerIdWithDefaultHavingOcspUsageRemoved(t *testing.T) {
// Twiddle the entry so that the issuer id is no longer valid.
storagePath := revokedPath + normalizeSerial(serial)
- var revInfo revocationInfo
+ var revInfo revocation.RevocationInfo
revEntry, err := s.Get(ctx, storagePath)
require.NoError(t, err, "failed looking up storage path: %s", storagePath)
err = revEntry.DecodeJSON(&revInfo)
@@ -607,7 +609,7 @@ func runOcspRequestTest(t *testing.T, requestType string, caKeyType string,
nextUpdateDiff := nextUpdate.Sub(thisUpdate)
require.Equal(t, expectedDiff, nextUpdateDiff,
fmt.Sprintf("the delta between thisUpdate %s and nextUpdate: %s should have been around: %s but was %s",
- thisUpdate, nextUpdate, defaultCrlConfig.OcspExpiry, nextUpdateDiff))
+ thisUpdate, nextUpdate, pki_backend.DefaultCrlConfig.OcspExpiry, nextUpdateDiff))
} else {
// With the config value set to 0, we shouldn't have a NextUpdate field set
require.True(t, ocspResp.NextUpdate.IsZero(), "nextUpdate value was not zero as expected was: %v", ocspResp.NextUpdate)
diff --git a/builtin/logical/pki/path_resign_crls.go b/builtin/logical/pki/path_resign_crls.go
index 6c2810db82..65563dc7f7 100644
--- a/builtin/logical/pki/path_resign_crls.go
+++ b/builtin/logical/pki/path_resign_crls.go
@@ -22,6 +22,7 @@ import (
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/logical"
@@ -73,7 +74,7 @@ to the issuer.`,
Type: framework.TypeString,
Description: `The amount of time the generated CRL should be
valid; defaults to 72 hours.`,
- Default: defaultCrlConfig.Expiry,
+ Default: pki_backend.DefaultCrlConfig.Expiry,
},
crlsParam: {
Type: framework.TypeStringSlice,
@@ -142,7 +143,7 @@ to the issuer.`,
Type: framework.TypeString,
Description: `The amount of time the generated CRL should be
valid; defaults to 72 hours.`,
- Default: defaultCrlConfig.Expiry,
+ Default: pki_backend.DefaultCrlConfig.Expiry,
},
formatParam: {
Type: framework.TypeString,
diff --git a/builtin/logical/pki/path_revoke.go b/builtin/logical/pki/path_revoke.go
index a8dc789187..f6c35e67f7 100644
--- a/builtin/logical/pki/path_revoke.go
+++ b/builtin/logical/pki/path_revoke.go
@@ -18,6 +18,7 @@ import (
"time"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/consts"
@@ -497,7 +498,7 @@ func validatePublicKeyMatchesCert(verifier crypto.PublicKey, certReference *x509
return nil
}
-func (b *backend) maybeRevokeCrossCluster(sc *storageContext, config *crlConfig, serial string, havePrivateKey bool) (*logical.Response, error) {
+func (b *backend) maybeRevokeCrossCluster(sc *storageContext, config *pki_backend.CrlConfig, serial string, havePrivateKey bool) (*logical.Response, error) {
if !config.UseGlobalQueue {
return logical.ErrorResponse(fmt.Sprintf("certificate with serial %s not found.", serial)), nil
}
@@ -563,7 +564,7 @@ func (b *backend) pathRevokeWrite(ctx context.Context, req *logical.Request, dat
var cert *x509.Certificate
var serial string
- config, err := sc.Backend.CrlBuilder().getConfigWithUpdate(sc)
+ config, err := sc.CrlBuilder().GetConfigWithUpdate(sc)
if err != nil {
return nil, fmt.Errorf("error revoking serial: %s: failed reading config: %w", serial, err)
}
@@ -658,7 +659,7 @@ func (b *backend) pathRotateCRLRead(ctx context.Context, req *logical.Request, _
defer b.GetRevokeStorageLock().RUnlock()
sc := b.makeStorageContext(ctx, req.Storage)
- warnings, crlErr := b.CrlBuilder().rebuild(sc, false)
+ warnings, crlErr := b.CrlBuilder().Rebuild(sc, false)
if crlErr != nil {
switch crlErr.(type) {
case errutil.UserError:
@@ -684,7 +685,7 @@ func (b *backend) pathRotateCRLRead(ctx context.Context, req *logical.Request, _
func (b *backend) pathRotateDeltaCRLRead(ctx context.Context, req *logical.Request, _ *framework.FieldData) (*logical.Response, error) {
sc := b.makeStorageContext(ctx, req.Storage)
- cfg, err := b.CrlBuilder().getConfigWithUpdate(sc)
+ cfg, err := b.CrlBuilder().GetConfigWithUpdate(sc)
if err != nil {
return nil, fmt.Errorf("error fetching CRL configuration: %w", err)
}
diff --git a/builtin/logical/pki/path_root.go b/builtin/logical/pki/path_root.go
index 53b8c81389..e5633b81c6 100644
--- a/builtin/logical/pki/path_root.go
+++ b/builtin/logical/pki/path_root.go
@@ -293,7 +293,7 @@ func (b *backend) pathCAGenerateRoot(ctx context.Context, req *logical.Request,
}
// Build a fresh CRL
- warnings, err = b.CrlBuilder().rebuild(sc, true)
+ warnings, err = b.CrlBuilder().Rebuild(sc, true)
if err != nil {
return nil, err
}
@@ -399,7 +399,7 @@ func (b *backend) pathIssuerSignIntermediate(ctx context.Context, req *logical.R
apiData: data,
role: role,
}
- parsedBundle, warnings, err := signCert(b, input, signingBundle, true, useCSRValues)
+ parsedBundle, warnings, err := signCert(b.System(), input, signingBundle, true, useCSRValues)
if err != nil {
switch err.(type) {
case errutil.UserError:
diff --git a/builtin/logical/pki/path_tidy.go b/builtin/logical/pki/path_tidy.go
index 98564d8ca8..a768ca8836 100644
--- a/builtin/logical/pki/path_tidy.go
+++ b/builtin/logical/pki/path_tidy.go
@@ -16,6 +16,7 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/helper/constants"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
@@ -1072,7 +1073,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques
// Fetch and parse our issuers so we can associate them if necessary.
sc := b.makeStorageContext(ctx, req.Storage)
- issuerIDCertMap, err := fetchIssuerMapForRevocationChecking(sc)
+ issuerIDCertMap, err := revocation.FetchIssuerMapForRevocationChecking(sc)
if err != nil {
return err
}
@@ -1089,7 +1090,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques
fixedIssuers := 0
- var revInfo revocationInfo
+ var revInfo revocation.RevocationInfo
for i, serial := range revokedSerials {
b.tidyStatusMessage(fmt.Sprintf("Tidying revoked certificates: checking certificate %d of %d", i, len(revokedSerials)))
metrics.SetGauge([]string{"secrets", "pki", "tidy", "revoked_cert_current_entry"}, float32(i))
@@ -1148,7 +1149,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques
b.tidyStatusIncMissingIssuerCertCount()
revInfo.CertificateIssuer = issuing.IssuerID("")
storeCert = true
- if associateRevokedCertWithIsssuer(&revInfo, revokedCert, issuerIDCertMap) {
+ if revInfo.AssociateRevokedCertWithIsssuer(revokedCert, issuerIDCertMap) {
fixedIssuers += 1
}
}
@@ -1204,7 +1205,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques
}
if !config.AutoRebuild {
- warnings, err := b.CrlBuilder().rebuild(sc, false)
+ warnings, err := b.CrlBuilder().Rebuild(sc, false)
if err != nil {
return err
}
@@ -1243,7 +1244,7 @@ func (b *backend) doTidyExpiredIssuers(ctx context.Context, req *logical.Request
// Fetch and parse our issuers so we have their expiration date.
sc := b.makeStorageContext(ctx, req.Storage)
- issuerIDCertMap, err := fetchIssuerMapForRevocationChecking(sc)
+ issuerIDCertMap, err := revocation.FetchIssuerMapForRevocationChecking(sc)
if err != nil {
return err
}
@@ -1316,7 +1317,7 @@ func (b *backend) doTidyExpiredIssuers(ctx context.Context, req *logical.Request
b.GetRevokeStorageLock().Lock()
defer b.GetRevokeStorageLock().Unlock()
- warnings, err := b.CrlBuilder().rebuild(sc, false)
+ warnings, err := b.CrlBuilder().Rebuild(sc, false)
if err != nil {
return err
}
@@ -1565,7 +1566,7 @@ func (b *backend) doTidyCrossRevocationStore(ctx context.Context, req *logical.R
continue
}
- var details unifiedRevocationEntry
+ var details revocation.UnifiedRevocationEntry
if err := entry.DecodeJSON(&details); err != nil {
return fmt.Errorf("error decoding cross-cluster revocation entry (%v) to tidy: %w", ePath, err)
}
diff --git a/builtin/logical/pki/periodic.go b/builtin/logical/pki/periodic.go
index b5c6209b14..05c37b660e 100644
--- a/builtin/logical/pki/periodic.go
+++ b/builtin/logical/pki/periodic.go
@@ -10,6 +10,7 @@ import (
"sync/atomic"
"time"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -36,19 +37,18 @@ func newUnifiedTransferStatus() *UnifiedTransferStatus {
// send all missing local revocation entries to the unified space if the feature
// is enabled.
func runUnifiedTransfer(sc *storageContext) {
- b := sc.Backend
- status := b.GetUnifiedTransferStatus()
+ status := sc.GetUnifiedTransferStatus()
- isPerfStandby := b.System().ReplicationState().HasState(consts.ReplicationDRSecondary | consts.ReplicationPerformanceStandby)
+ isPerfStandby := sc.System().ReplicationState().HasState(consts.ReplicationDRSecondary | consts.ReplicationPerformanceStandby)
- if isPerfStandby || b.System().LocalMount() {
+ if isPerfStandby || sc.System().LocalMount() {
// We only do this on active enterprise nodes, when we aren't a local mount
return
}
- config, err := b.CrlBuilder().getConfigWithUpdate(sc)
+ config, err := sc.CrlBuilder().GetConfigWithUpdate(sc)
if err != nil {
- b.Logger().Error("failed to retrieve crl config from storage for unified transfer background process",
+ sc.Logger().Error("failed to retrieve crl config from storage for unified transfer background process",
"error", err)
return
}
@@ -58,15 +58,15 @@ func runUnifiedTransfer(sc *storageContext) {
return
}
- clusterId, err := b.System().ClusterID(sc.Context)
+ clusterId, err := sc.System().ClusterID(sc.Context)
if err != nil {
- b.Logger().Error("failed to fetch cluster id for unified transfer background process",
+ sc.Logger().Error("failed to fetch cluster id for unified transfer background process",
"error", err)
return
}
if !status.isRunning.CompareAndSwap(false, true) {
- b.Logger().Debug("an existing unified transfer process is already running")
+ sc.Logger().Debug("an existing unified transfer process is already running")
return
}
defer status.isRunning.Store(false)
@@ -91,13 +91,13 @@ func runUnifiedTransfer(sc *storageContext) {
err = doUnifiedTransferMissingLocalSerials(sc, clusterId)
if err != nil {
- b.Logger().Error("an error occurred running unified transfer", "error", err.Error())
+ sc.Logger().Error("an error occurred running unified transfer", "error", err.Error())
status.forceRerun.Store(true)
} else {
if config.EnableDelta {
err = doUnifiedTransferMissingDeltaWALSerials(sc, clusterId)
if err != nil {
- b.Logger().Error("an error occurred running unified transfer", "error", err.Error())
+ sc.Logger().Error("an error occurred running unified transfer", "error", err.Error())
status.forceRerun.Store(true)
}
}
@@ -125,7 +125,7 @@ func doUnifiedTransferMissingLocalSerials(sc *storageContext, clusterId string)
errCount := 0
for i, serialNum := range localRevokedSerialNums {
if i%25 == 0 {
- config, _ := sc.Backend.CrlBuilder().getConfigWithUpdate(sc)
+ config, _ := sc.CrlBuilder().GetConfigWithUpdate(sc)
if config != nil && !config.UnifiedCRL {
return errors.New("unified crl has been disabled after we started, stopping")
}
@@ -134,14 +134,14 @@ func doUnifiedTransferMissingLocalSerials(sc *storageContext, clusterId string)
err := readRevocationEntryAndTransfer(sc, serialNum)
if err != nil {
errCount++
- sc.Backend.Logger().Error("Failed transferring local revocation to unified space",
+ sc.Logger().Error("Failed transferring local revocation to unified space",
"serial", serialNum, "error", err)
}
}
}
if errCount > 0 {
- sc.Backend.Logger().Warn(fmt.Sprintf("Failed transfering %d local serials to unified storage", errCount))
+ sc.Logger().Warn(fmt.Sprintf("Failed transfering %d local serials to unified storage", errCount))
}
return nil
@@ -224,7 +224,7 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin
errCount := 0
for index, serial := range localWALEntries {
if index%25 == 0 {
- config, _ := sc.Backend.CrlBuilder().getConfigWithUpdate(sc)
+ config, _ := sc.CrlBuilder().GetConfigWithUpdate(sc)
if config != nil && (!config.UnifiedCRL || !config.EnableDelta) {
return errors.New("unified or delta CRLs have been disabled after we started, stopping")
}
@@ -247,7 +247,7 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin
if !isRevokedCopied {
// We need to wait here to copy over.
errCount += 1
- sc.Backend.Logger().Debug("Delta WAL exists locally, but corresponding cross-cluster full revocation entry is missing; skipping", "serial", serial)
+ sc.Logger().Debug("Delta WAL exists locally, but corresponding cross-cluster full revocation entry is missing; skipping", "serial", serial)
continue
}
@@ -258,7 +258,7 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin
entry, err := sc.Storage.Get(sc.Context, localPath)
if err != nil || entry == nil {
errCount += 1
- sc.Backend.Logger().Error("Failed reading local delta WAL entry to copy to cross-cluster", "serial", serial, "err", err)
+ sc.Logger().Error("Failed reading local delta WAL entry to copy to cross-cluster", "serial", serial, "err", err)
continue
}
@@ -266,14 +266,14 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin
err = sc.Storage.Put(sc.Context, entry)
if err != nil {
errCount += 1
- sc.Backend.Logger().Error("Failed sync local delta WAL entry to cross-cluster unified delta WAL location", "serial", serial, "err", err)
+ sc.Logger().Error("Failed sync local delta WAL entry to cross-cluster unified delta WAL location", "serial", serial, "err", err)
continue
}
}
if errCount > 0 {
// See note above about why we don't fail here.
- sc.Backend.Logger().Warn(fmt.Sprintf("Failed transfering %d local delta WAL serials to unified storage", errCount))
+ sc.Logger().Warn(fmt.Sprintf("Failed transfering %d local delta WAL serials to unified storage", errCount))
return nil
}
@@ -295,17 +295,17 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin
func readRevocationEntryAndTransfer(sc *storageContext, serial string) error {
hyphenSerial := normalizeSerial(serial)
- revInfo, err := sc.fetchRevocationInfo(hyphenSerial)
+ revInfo, err := fetchRevocationInfo(sc, hyphenSerial)
if err != nil {
return fmt.Errorf("failed loading revocation entry for serial: %s: %w", serial, err)
}
if revInfo == nil {
- sc.Backend.Logger().Debug("no certificate revocation entry for serial", "serial", serial)
+ sc.Logger().Debug("no certificate revocation entry for serial", "serial", serial)
return nil
}
cert, err := x509.ParseCertificate(revInfo.CertificateBytes)
if err != nil {
- sc.Backend.Logger().Debug("failed parsing certificate stored in revocation entry for serial",
+ sc.Logger().Debug("failed parsing certificate stored in revocation entry for serial",
"serial", serial, "error", err)
return nil
}
@@ -326,12 +326,12 @@ func readRevocationEntryAndTransfer(sc *storageContext, serial string) error {
return nil
}
- entry := &unifiedRevocationEntry{
+ entry := &revocation.UnifiedRevocationEntry{
SerialNumber: hyphenSerial,
CertExpiration: cert.NotAfter,
RevocationTimeUTC: revocationTime,
CertificateIssuer: revInfo.CertificateIssuer,
}
- return writeUnifiedRevocationEntry(sc, entry)
+ return revocation.WriteUnifiedRevocationEntry(sc.GetContext(), sc.GetStorage(), entry)
}
diff --git a/builtin/logical/pki/pki_backend/common.go b/builtin/logical/pki/pki_backend/common.go
index b34fda0761..6b7c642ada 100644
--- a/builtin/logical/pki/pki_backend/common.go
+++ b/builtin/logical/pki/pki_backend/common.go
@@ -4,7 +4,13 @@
package pki_backend
import (
+ "context"
+ "fmt"
+ "strings"
+
log "github.com/hashicorp/go-hclog"
+ "github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -20,7 +26,80 @@ type Logger interface {
Logger() log.Logger
}
-type CertificateCounter interface {
- IsInitialized() bool
- IncrementTotalCertificatesCount(certsCounted bool, newSerial string)
+//go:generate enumer -type=RolePathPolicy -text -json -transform=kebab-case
+type RolePathPolicy int
+
+const (
+ RPPUnknown RolePathPolicy = iota
+ RPPSignVerbatim
+ RPPRole
+)
+
+var (
+ pathPolicyRolePrefix = "role:"
+ pathPolicyRolePrefixLength = len(pathPolicyRolePrefix)
+)
+
+// GetRoleByPathOrPathPolicy loads an existing role based on if the data field data contains a 'role' parameter
+// or by the values within the pathPolicy
+func GetRoleByPathOrPathPolicy(ctx context.Context, s logical.Storage, data *framework.FieldData, pathPolicy string) (*issuing.RoleEntry, error) {
+ var role *issuing.RoleEntry
+
+ // The role name from the path is the highest priority
+ if roleName, ok := getRoleNameFromPath(data); ok {
+ var err error
+ role, err = issuing.GetRole(ctx, s, roleName)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ policyType, policyVal, err := GetPathPolicyType(pathPolicy)
+ if err != nil {
+ return nil, err
+ }
+
+ switch policyType {
+ case RPPRole:
+ role, err = issuing.GetRole(ctx, s, policyVal)
+ if err != nil {
+ return nil, err
+ }
+ case RPPSignVerbatim:
+ role = issuing.SignVerbatimRole()
+ default:
+ return nil, fmt.Errorf("unsupported policy type returned: %s from policy path: %s", policyType, pathPolicy)
+ }
+ }
+
+ return role, nil
+}
+
+func GetPathPolicyType(pathPolicy string) (RolePathPolicy, string, error) {
+ policy := strings.TrimSpace(pathPolicy)
+
+ switch {
+ case policy == "sign-verbatim":
+ return RPPSignVerbatim, "", nil
+ case strings.HasPrefix(policy, pathPolicyRolePrefix):
+ if policy == pathPolicyRolePrefix {
+ return RPPUnknown, "", fmt.Errorf("no role specified by policy %v", pathPolicy)
+ }
+ roleName := pathPolicy[pathPolicyRolePrefixLength:]
+ return RPPRole, roleName, nil
+ default:
+ return RPPUnknown, "", fmt.Errorf("string %v was not a valid default path policy", pathPolicy)
+ }
+}
+
+func getRoleNameFromPath(data *framework.FieldData) (string, bool) {
+ // If our schema doesn't include the parameter bail
+ if _, ok := data.Schema["role"]; !ok {
+ return "", false
+ }
+
+ if roleName, ok := data.GetOk("role"); ok {
+ return roleName.(string), true
+ }
+
+ return "", false
}
diff --git a/builtin/logical/pki/pki_backend/crl_builder.go b/builtin/logical/pki/pki_backend/crl_builder.go
new file mode 100644
index 0000000000..58c048094a
--- /dev/null
+++ b/builtin/logical/pki/pki_backend/crl_builder.go
@@ -0,0 +1,20 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package pki_backend
+
+import "time"
+
+type CrlBuilderType interface {
+ RebuildIfForced(sc StorageContext) ([]string, error)
+ Rebuild(sc StorageContext, forceNew bool) ([]string, error)
+ RebuildDeltaCRLsHoldingLock(sc StorageContext, forceNew bool) ([]string, error)
+ GetPresentLocalDeltaWALForClearing(sc StorageContext) ([]string, error)
+ GetPresentUnifiedDeltaWALForClearing(sc StorageContext) ([]string, error)
+ GetConfigWithUpdate(sc StorageContext) (*CrlConfig, error)
+ ClearLocalDeltaWAL(sc StorageContext, walSerials []string) error
+ ClearUnifiedDeltaWAL(sc StorageContext, walSerials []string) error
+
+ SetLastDeltaRebuildCheckTime(t time.Time)
+ ShouldInvalidate() bool
+}
diff --git a/builtin/logical/pki/pki_backend/crl_config.go b/builtin/logical/pki/pki_backend/crl_config.go
new file mode 100644
index 0000000000..f37fbbbb33
--- /dev/null
+++ b/builtin/logical/pki/pki_backend/crl_config.go
@@ -0,0 +1,38 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package pki_backend
+
+const latestCrlConfigVersion = 1
+
+// CRLConfig holds basic CRL configuration information
+type CrlConfig struct {
+ Version int `json:"version"`
+ Expiry string `json:"expiry"`
+ Disable bool `json:"disable"`
+ OcspDisable bool `json:"ocsp_disable"`
+ AutoRebuild bool `json:"auto_rebuild"`
+ AutoRebuildGracePeriod string `json:"auto_rebuild_grace_period"`
+ OcspExpiry string `json:"ocsp_expiry"`
+ EnableDelta bool `json:"enable_delta"`
+ DeltaRebuildInterval string `json:"delta_rebuild_interval"`
+ UseGlobalQueue bool `json:"cross_cluster_revocation"`
+ UnifiedCRL bool `json:"unified_crl"`
+ UnifiedCRLOnExistingPaths bool `json:"unified_crl_on_existing_paths"`
+}
+
+// Implicit default values for the config if it does not exist.
+var DefaultCrlConfig = CrlConfig{
+ Version: latestCrlConfigVersion,
+ Expiry: "72h",
+ Disable: false,
+ OcspDisable: false,
+ OcspExpiry: "12h",
+ AutoRebuild: false,
+ AutoRebuildGracePeriod: "12h",
+ EnableDelta: false,
+ DeltaRebuildInterval: "15m",
+ UseGlobalQueue: false,
+ UnifiedCRL: false,
+ UnifiedCRLOnExistingPaths: false,
+}
diff --git a/builtin/logical/pki/pki_backend/rolepathpolicy_enumer.go b/builtin/logical/pki/pki_backend/rolepathpolicy_enumer.go
new file mode 100644
index 0000000000..305e34a6b5
--- /dev/null
+++ b/builtin/logical/pki/pki_backend/rolepathpolicy_enumer.go
@@ -0,0 +1,80 @@
+// Code generated by "enumer -type=RolePathPolicy -text -json -transform=kebab-case"; DO NOT EDIT.
+
+package pki_backend
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+const _RolePathPolicyName = "RPPUnknownRPPSignVerbatimRPPRole"
+
+var _RolePathPolicyIndex = [...]uint8{0, 10, 25, 32}
+
+func (i RolePathPolicy) String() string {
+ if i < 0 || i >= RolePathPolicy(len(_RolePathPolicyIndex)-1) {
+ return fmt.Sprintf("RolePathPolicy(%d)", i)
+ }
+ return _RolePathPolicyName[_RolePathPolicyIndex[i]:_RolePathPolicyIndex[i+1]]
+}
+
+var _RolePathPolicyValues = []RolePathPolicy{0, 1, 2}
+
+var _RolePathPolicyNameToValueMap = map[string]RolePathPolicy{
+ _RolePathPolicyName[0:10]: 0,
+ _RolePathPolicyName[10:25]: 1,
+ _RolePathPolicyName[25:32]: 2,
+}
+
+// RolePathPolicyString retrieves an enum value from the enum constants string name.
+// Throws an error if the param is not part of the enum.
+func RolePathPolicyString(s string) (RolePathPolicy, error) {
+ if val, ok := _RolePathPolicyNameToValueMap[s]; ok {
+ return val, nil
+ }
+ return 0, fmt.Errorf("%s does not belong to RolePathPolicy values", s)
+}
+
+// RolePathPolicyValues returns all values of the enum
+func RolePathPolicyValues() []RolePathPolicy {
+ return _RolePathPolicyValues
+}
+
+// IsARolePathPolicy returns "true" if the value is listed in the enum definition. "false" otherwise
+func (i RolePathPolicy) IsARolePathPolicy() bool {
+ for _, v := range _RolePathPolicyValues {
+ if i == v {
+ return true
+ }
+ }
+ return false
+}
+
+// MarshalJSON implements the json.Marshaler interface for RolePathPolicy
+func (i RolePathPolicy) MarshalJSON() ([]byte, error) {
+ return json.Marshal(i.String())
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface for RolePathPolicy
+func (i *RolePathPolicy) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return fmt.Errorf("RolePathPolicy should be a string, got %s", data)
+ }
+
+ var err error
+ *i, err = RolePathPolicyString(s)
+ return err
+}
+
+// MarshalText implements the encoding.TextMarshaler interface for RolePathPolicy
+func (i RolePathPolicy) MarshalText() ([]byte, error) {
+ return []byte(i.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface for RolePathPolicy
+func (i *RolePathPolicy) UnmarshalText(text []byte) error {
+ var err error
+ *i, err = RolePathPolicyString(string(text))
+ return err
+}
diff --git a/builtin/logical/pki/pki_backend/storage_context.go b/builtin/logical/pki/pki_backend/storage_context.go
new file mode 100644
index 0000000000..d05b533062
--- /dev/null
+++ b/builtin/logical/pki/pki_backend/storage_context.go
@@ -0,0 +1,25 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package pki_backend
+
+import (
+ "context"
+
+ "github.com/hashicorp/go-hclog"
+ "github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/managed_key"
+ "github.com/hashicorp/vault/sdk/logical"
+)
+
+type StorageContext interface {
+ GetContext() context.Context
+ GetStorage() logical.Storage
+
+ UseLegacyBundleCaStorage() bool
+ GetPkiManagedView() managed_key.PkiManagedKeyView
+ CrlBuilder() CrlBuilderType
+ GetCertificateCounter() issuing.CertificateCounter
+
+ Logger() hclog.Logger
+}
diff --git a/builtin/logical/pki/revocation/revocation_entry.go b/builtin/logical/pki/revocation/revocation_entry.go
new file mode 100644
index 0000000000..bdbd3c389c
--- /dev/null
+++ b/builtin/logical/pki/revocation/revocation_entry.go
@@ -0,0 +1,34 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package revocation
+
+import (
+ "context"
+ "time"
+
+ "github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/parsing"
+ "github.com/hashicorp/vault/sdk/logical"
+)
+
+type UnifiedRevocationEntry struct {
+ SerialNumber string `json:"-"`
+ CertExpiration time.Time `json:"certificate_expiration_utc"`
+ RevocationTimeUTC time.Time `json:"revocation_time_utc"`
+ CertificateIssuer issuing.IssuerID `json:"issuer_id"`
+}
+
+const (
+ UnifiedRevocationReadPathPrefix = "unified-revocation/"
+ UnifiedRevocationWritePathPrefix = UnifiedRevocationReadPathPrefix + "{{clusterId}}/"
+)
+
+func WriteUnifiedRevocationEntry(ctx context.Context, storage logical.Storage, ure *UnifiedRevocationEntry) error {
+ json, err := logical.StorageEntryJSON(UnifiedRevocationWritePathPrefix+parsing.NormalizeSerialForStorage(ure.SerialNumber), ure)
+ if err != nil {
+ return err
+ }
+
+ return storage.Put(ctx, json)
+}
diff --git a/builtin/logical/pki/revocation/revoke.go b/builtin/logical/pki/revocation/revoke.go
new file mode 100644
index 0000000000..67272786e8
--- /dev/null
+++ b/builtin/logical/pki/revocation/revoke.go
@@ -0,0 +1,84 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package revocation
+
+import (
+ "bytes"
+ "crypto/x509"
+ "fmt"
+ "time"
+
+ "github.com/hashicorp/vault/builtin/logical/pki/issuing"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
+ "github.com/hashicorp/vault/sdk/helper/errutil"
+)
+
+const (
+ RevokedPath = "revoked/"
+)
+
+type RevocationInfo struct {
+ CertificateBytes []byte `json:"certificate_bytes"`
+ RevocationTime int64 `json:"revocation_time"`
+ RevocationTimeUTC time.Time `json:"revocation_time_utc"`
+ CertificateIssuer issuing.IssuerID `json:"issuer_id"`
+}
+
+func (ri *RevocationInfo) AssociateRevokedCertWithIsssuer(revokedCert *x509.Certificate, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool {
+ for issuerId, issuerCert := range issuerIDCertMap {
+ if bytes.Equal(revokedCert.RawIssuer, issuerCert.RawSubject) {
+ if err := revokedCert.CheckSignatureFrom(issuerCert); err == nil {
+ // Valid mapping. Add it to the specified entry.
+ ri.CertificateIssuer = issuerId
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+// FetchIssuerMapForRevocationChecking fetches a map of IssuerID->parsed cert for revocation
+// usage. Unlike other paths, this needs to handle the legacy bundle
+// more gracefully than rejecting it outright.
+func FetchIssuerMapForRevocationChecking(sc pki_backend.StorageContext) (map[issuing.IssuerID]*x509.Certificate, error) {
+ var err error
+ var issuers []issuing.IssuerID
+
+ if !sc.UseLegacyBundleCaStorage() {
+ issuers, err = issuing.ListIssuers(sc.GetContext(), sc.GetStorage())
+ if err != nil {
+ return nil, fmt.Errorf("could not fetch issuers list: %w", err)
+ }
+ } else {
+ // Hack: this isn't a real IssuerID, but it works for fetchCAInfo
+ // since it resolves the reference.
+ issuers = []issuing.IssuerID{issuing.LegacyBundleShimID}
+ }
+
+ issuerIDCertMap := make(map[issuing.IssuerID]*x509.Certificate, len(issuers))
+ for _, issuer := range issuers {
+ _, bundle, caErr := issuing.FetchCertBundleByIssuerId(sc.GetContext(), sc.GetStorage(), issuer, false)
+ if caErr != nil {
+ return nil, fmt.Errorf("error fetching CA certificate for issuer id %v: %w", issuer, caErr)
+ }
+
+ if bundle == nil {
+ return nil, fmt.Errorf("faulty reference: %v - CA info not found", issuer)
+ }
+
+ parsedBundle, err := issuing.ParseCABundle(sc.GetContext(), sc.GetPkiManagedView(), bundle)
+ if err != nil {
+ return nil, errutil.InternalError{Err: err.Error()}
+ }
+
+ if parsedBundle.Certificate == nil {
+ return nil, errutil.InternalError{Err: "stored CA information not able to be parsed"}
+ }
+
+ issuerIDCertMap[issuer] = parsedBundle.Certificate
+ }
+
+ return issuerIDCertMap, nil
+}
diff --git a/builtin/logical/pki/secret_certs.go b/builtin/logical/pki/secret_certs.go
index 0cf0ad0c6d..7f75203b1f 100644
--- a/builtin/logical/pki/secret_certs.go
+++ b/builtin/logical/pki/secret_certs.go
@@ -78,7 +78,7 @@ func (b *backend) secretCredsRevoke(ctx context.Context, req *logical.Request, _
return nil, nil
}
- config, err := sc.Backend.CrlBuilder().getConfigWithUpdate(sc)
+ config, err := sc.CrlBuilder().GetConfigWithUpdate(sc)
if err != nil {
return nil, fmt.Errorf("error revoking serial: %s: failed reading config: %w", serial, err)
}
diff --git a/builtin/logical/pki/storage.go b/builtin/logical/pki/storage.go
index 67a0ff1c15..990d4af686 100644
--- a/builtin/logical/pki/storage.go
+++ b/builtin/logical/pki/storage.go
@@ -11,11 +11,15 @@ import (
"errors"
"fmt"
"strings"
+ "sync"
"time"
+ "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
"github.com/hashicorp/vault/builtin/logical/pki/managed_key"
+ "github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
"github.com/hashicorp/vault/helper/constants"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/errutil"
@@ -35,12 +39,13 @@ const (
legacyMigrationBundleLogKey = "config/legacyMigrationBundleLog"
legacyCertBundlePath = issuing.LegacyCertBundlePath
legacyCertBundleBackupPath = "config/ca_bundle.bak"
- legacyCRLPath = "crl"
- deltaCRLPath = "delta-crl"
- deltaCRLPathSuffix = "-delta"
- unifiedCRLPath = "unified-crl"
- unifiedDeltaCRLPath = "unified-delta-crl"
- unifiedCRLPathPrefix = "unified-"
+
+ legacyCRLPath = issuing.LegacyCRLPath
+ deltaCRLPath = issuing.DeltaCRLPath
+ deltaCRLPathSuffix = issuing.DeltaCRLPathSuffix
+ unifiedCRLPath = issuing.UnifiedCRLPath
+ unifiedDeltaCRLPath = issuing.UnifiedDeltaCRLPath
+ unifiedCRLPathPrefix = issuing.UnifiedCRLPathPrefix
autoTidyConfigPath = "config/auto-tidy"
clusterConfigPath = "config/cluster"
@@ -59,6 +64,8 @@ type storageContext struct {
Backend *backend
}
+var _ pki_backend.StorageContext = (*storageContext)(nil)
+
func (b *backend) makeStorageContext(ctx context.Context, s logical.Storage) *storageContext {
return &storageContext{
Context: ctx,
@@ -76,6 +83,50 @@ func (sc *storageContext) WithFreshTimeout(timeout time.Duration) (*storageConte
}, cancel
}
+func (sc *storageContext) GetContext() context.Context {
+ return sc.Context
+}
+
+func (sc *storageContext) GetStorage() logical.Storage {
+ return sc.Storage
+}
+
+func (sc *storageContext) Logger() hclog.Logger {
+ return sc.Backend.Logger()
+}
+
+func (sc *storageContext) System() logical.SystemView {
+ return sc.Backend.System()
+}
+
+func (sc *storageContext) CrlBuilder() pki_backend.CrlBuilderType {
+ return sc.Backend.CrlBuilder()
+}
+
+func (sc *storageContext) GetUnifiedTransferStatus() *UnifiedTransferStatus {
+ return sc.Backend.GetUnifiedTransferStatus()
+}
+
+func (sc *storageContext) GetPkiManagedView() managed_key.PkiManagedKeyView {
+ return sc.Backend
+}
+
+func (sc *storageContext) GetCertificateCounter() issuing.CertificateCounter {
+ return sc.Backend.GetCertificateCounter()
+}
+
+func (sc *storageContext) UseLegacyBundleCaStorage() bool {
+ return sc.Backend.UseLegacyBundleCaStorage()
+}
+
+func (sc *storageContext) GetRevokeStorageLock() *sync.RWMutex {
+ return sc.Backend.GetRevokeStorageLock()
+}
+
+func (sc *storageContext) GetRole(name string) (*issuing.RoleEntry, error) {
+ return sc.Backend.GetRole(sc.Context, sc.Storage, name)
+}
+
func (sc *storageContext) listKeys() ([]issuing.KeyID, error) {
return issuing.ListKeys(sc.Context, sc.Storage)
}
@@ -467,41 +518,6 @@ func (sc *storageContext) resolveIssuerReference(reference string) (issuing.Issu
return issuing.ResolveIssuerReference(sc.Context, sc.Storage, reference)
}
-func (sc *storageContext) resolveIssuerCRLPath(reference string, unified bool) (string, error) {
- if sc.Backend.UseLegacyBundleCaStorage() {
- return legacyCRLPath, nil
- }
-
- issuer, err := sc.resolveIssuerReference(reference)
- if err != nil {
- return legacyCRLPath, err
- }
-
- var crlConfig *issuing.InternalCRLConfigEntry
- if unified {
- crlConfig, err = issuing.GetUnifiedCRLConfig(sc.Context, sc.Storage)
- if err != nil {
- return legacyCRLPath, err
- }
- } else {
- crlConfig, err = issuing.GetLocalCRLConfig(sc.Context, sc.Storage)
- if err != nil {
- return legacyCRLPath, err
- }
- }
-
- if crlId, ok := crlConfig.IssuerIDCRLMap[issuer]; ok && len(crlId) > 0 {
- path := fmt.Sprintf("crls/%v", crlId)
- if unified {
- path = unifiedCRLPathPrefix + path
- }
-
- return path, nil
- }
-
- return legacyCRLPath, fmt.Errorf("unable to find CRL for issuer: id:%v/ref:%v", issuer, reference)
-}
-
// Builds a certutil.CertBundle from the specified issuer identifier,
// optionally loading the key or not. This method supports loading legacy
// bundles using the legacyBundleShimID issuerId, and if no entry is found will return an error.
@@ -613,15 +629,15 @@ func (sc *storageContext) checkForRolesReferencing(issuerId string) (timeout boo
return false, inUseBy, nil
}
-func (sc *storageContext) getRevocationConfig() (*crlConfig, error) {
+func (sc *storageContext) getRevocationConfig() (*pki_backend.CrlConfig, error) {
entry, err := sc.Storage.Get(sc.Context, "config/crl")
if err != nil {
return nil, err
}
- var result crlConfig
+ var result pki_backend.CrlConfig
if entry == nil {
- result = defaultCrlConfig
+ result = pki_backend.DefaultCrlConfig
return &result, nil
}
@@ -631,15 +647,15 @@ func (sc *storageContext) getRevocationConfig() (*crlConfig, error) {
if result.Version == 0 {
// Automatically update existing configurations.
- result.OcspDisable = defaultCrlConfig.OcspDisable
- result.OcspExpiry = defaultCrlConfig.OcspExpiry
- result.AutoRebuild = defaultCrlConfig.AutoRebuild
- result.AutoRebuildGracePeriod = defaultCrlConfig.AutoRebuildGracePeriod
+ result.OcspDisable = pki_backend.DefaultCrlConfig.OcspDisable
+ result.OcspExpiry = pki_backend.DefaultCrlConfig.OcspExpiry
+ result.AutoRebuild = pki_backend.DefaultCrlConfig.AutoRebuild
+ result.AutoRebuildGracePeriod = pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod
result.Version = 1
}
if result.Version == 1 {
if result.DeltaRebuildInterval == "" {
- result.DeltaRebuildInterval = defaultCrlConfig.DeltaRebuildInterval
+ result.DeltaRebuildInterval = pki_backend.DefaultCrlConfig.DeltaRebuildInterval
}
result.Version = 2
}
@@ -647,13 +663,13 @@ func (sc *storageContext) getRevocationConfig() (*crlConfig, error) {
// Depending on client version, it's possible that the expiry is unset.
// This sets the default value to prevent issues in downstream code.
if result.Expiry == "" {
- result.Expiry = defaultCrlConfig.Expiry
+ result.Expiry = pki_backend.DefaultCrlConfig.Expiry
}
- isLocalMount := sc.Backend.System().LocalMount()
+ isLocalMount := sc.System().LocalMount()
if (!constants.IsEnterprise || isLocalMount) && (result.UnifiedCRLOnExistingPaths || result.UnifiedCRL || result.UseGlobalQueue) {
// An end user must have had Enterprise, enabled the unified config args and then downgraded to OSS.
- sc.Backend.Logger().Warn("Not running Vault Enterprise or using a local mount, " +
+ sc.Logger().Warn("Not running Vault Enterprise or using a local mount, " +
"disabling unified_crl, unified_crl_on_existing_paths and cross_cluster_revocation config flags.")
result.UnifiedCRLOnExistingPaths = false
result.UnifiedCRL = false
@@ -663,7 +679,7 @@ func (sc *storageContext) getRevocationConfig() (*crlConfig, error) {
return &result, nil
}
-func (sc *storageContext) setRevocationConfig(config *crlConfig) error {
+func (sc *storageContext) setRevocationConfig(config *pki_backend.CrlConfig) error {
entry, err := logical.StorageEntryJSON("config/crl", config)
if err != nil {
return fmt.Errorf("failed building storage entry JSON: %w", err)
@@ -753,9 +769,9 @@ func (sc *storageContext) writeClusterConfig(config *issuing.ClusterConfigEntry)
return sc.Storage.Put(sc.Context, entry)
}
-func (sc *storageContext) fetchRevocationInfo(serial string) (*revocationInfo, error) {
- var revInfo *revocationInfo
- revEntry, err := fetchCertBySerial(sc, revokedPath, serial)
+func fetchRevocationInfo(sc pki_backend.StorageContext, serial string) (*revocation.RevocationInfo, error) {
+ var revInfo *revocation.RevocationInfo
+ revEntry, err := fetchCertBySerial(sc, revocation.RevokedPath, serial)
if err != nil {
return nil, err
}
diff --git a/builtin/logical/pki/storage_unified.go b/builtin/logical/pki/storage_unified.go
index c279c26191..63f39f1c59 100644
--- a/builtin/logical/pki/storage_unified.go
+++ b/builtin/logical/pki/storage_unified.go
@@ -6,25 +6,15 @@ package pki
import (
"fmt"
"strings"
- "time"
- "github.com/hashicorp/vault/builtin/logical/pki/issuing"
- "github.com/hashicorp/vault/sdk/logical"
+ "github.com/hashicorp/vault/builtin/logical/pki/revocation"
)
const (
- unifiedRevocationReadPathPrefix = "unified-revocation/"
- unifiedRevocationWritePathPrefix = unifiedRevocationReadPathPrefix + "{{clusterId}}/"
+ unifiedRevocationReadPathPrefix = revocation.UnifiedRevocationReadPathPrefix
)
-type unifiedRevocationEntry struct {
- SerialNumber string `json:"-"`
- CertExpiration time.Time `json:"certificate_expiration_utc"`
- RevocationTimeUTC time.Time `json:"revocation_time_utc"`
- CertificateIssuer issuing.IssuerID `json:"issuer_id"`
-}
-
-func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*unifiedRevocationEntry, error) {
+func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*revocation.UnifiedRevocationEntry, error) {
clusterPaths, err := lookupUnifiedClusterPaths(sc)
if err != nil {
return nil, err
@@ -38,7 +28,7 @@ func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*unifiedRe
}
if entryRaw != nil {
- var revEntry unifiedRevocationEntry
+ var revEntry revocation.UnifiedRevocationEntry
if err := entryRaw.DecodeJSON(&revEntry); err != nil {
return nil, fmt.Errorf("failed json decoding of unified entry at path %s: %w", serialPath, err)
}
@@ -50,15 +40,6 @@ func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*unifiedRe
return nil, nil
}
-func writeUnifiedRevocationEntry(sc *storageContext, ure *unifiedRevocationEntry) error {
- json, err := logical.StorageEntryJSON(unifiedRevocationWritePathPrefix+normalizeSerial(ure.SerialNumber), ure)
- if err != nil {
- return err
- }
-
- return sc.Storage.Put(sc.Context, json)
-}
-
// listClusterSpecificUnifiedRevokedCerts returns a list of revoked certificates from a given cluster
func listClusterSpecificUnifiedRevokedCerts(sc *storageContext, clusterId string) ([]string, error) {
path := unifiedRevocationReadPathPrefix + clusterId + "/"
diff --git a/builtin/logical/pki/util.go b/builtin/logical/pki/util.go
index f2e7c534f1..76f7bfcefc 100644
--- a/builtin/logical/pki/util.go
+++ b/builtin/logical/pki/util.go
@@ -17,7 +17,6 @@ import (
"github.com/hashicorp/vault/builtin/logical/pki/managed_key"
"github.com/hashicorp/vault/builtin/logical/pki/parsing"
"github.com/hashicorp/vault/sdk/framework"
- "github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/errutil"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -40,11 +39,11 @@ var (
)
func serialFromCert(cert *x509.Certificate) string {
- return serialFromBigInt(cert.SerialNumber)
+ return parsing.SerialFromCert(cert)
}
func serialFromBigInt(serial *big.Int) string {
- return strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":"))
+ return parsing.SerialFromBigInt(serial)
}
func normalizeSerialFromBigInt(serial *big.Int) string {
@@ -308,7 +307,7 @@ func (sc *storageContext) isIfModifiedSinceBeforeLastModified(helper *IfModified
switch helper.reqType {
case ifModifiedCRL, ifModifiedDeltaCRL:
- if sc.Backend.CrlBuilder().invalidate.Load() {
+ if sc.CrlBuilder().ShouldInvalidate() {
// When we see the CRL is invalidated, respond with false
// regardless of what the local CRL state says. We've likely
// renamed some issuers or are about to rebuild a new CRL....
@@ -328,7 +327,7 @@ func (sc *storageContext) isIfModifiedSinceBeforeLastModified(helper *IfModified
lastModified = crlConfig.DeltaLastModified
}
case ifModifiedUnifiedCRL, ifModifiedUnifiedDeltaCRL:
- if sc.Backend.CrlBuilder().invalidate.Load() {
+ if sc.CrlBuilder().ShouldInvalidate() {
// When we see the CRL is invalidated, respond with false
// regardless of what the local CRL state says. We've likely
// renamed some issuers or are about to rebuild a new CRL....
diff --git a/builtin/logical/pkiext/zlint_test.go b/builtin/logical/pkiext/zlint_test.go
index 206d23cb03..981d62bf1e 100644
--- a/builtin/logical/pkiext/zlint_test.go
+++ b/builtin/logical/pkiext/zlint_test.go
@@ -23,7 +23,7 @@ func buildZLintContainer(t *testing.T) {
containerfile := `
FROM docker.mirror.hashicorp.services/library/golang:latest
-RUN go install github.com/zmap/zlint/v3/cmd/zlint@latest
+RUN go install github.com/zmap/zlint/v3/cmd/zlint@v3.6.2
`
bCtx := docker.NewBuildContext()
diff --git a/builtin/logical/rabbitmq/path_role_create.go b/builtin/logical/rabbitmq/path_role_create.go
index 956a016720..c06e824428 100644
--- a/builtin/logical/rabbitmq/path_role_create.go
+++ b/builtin/logical/rabbitmq/path_role_create.go
@@ -6,7 +6,7 @@ package rabbitmq
import (
"context"
"fmt"
- "io/ioutil"
+ "io"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/template"
@@ -113,7 +113,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
}
}()
if !isIn200s(resp.StatusCode) {
- body, _ := ioutil.ReadAll(resp.Body)
+ body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("error creating user %s - %d: %s", username, resp.StatusCode, body)
}
@@ -128,7 +128,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
b.Logger().Error(fmt.Sprintf("deleting %s due to permissions being in an unknown state, but failed: %s", username, err))
}
if !isIn200s(resp.StatusCode) {
- body, _ := ioutil.ReadAll(resp.Body)
+ body, _ := io.ReadAll(resp.Body)
b.Logger().Error(fmt.Sprintf("deleting %s due to permissions being in an unknown state, but error deleting: %d: %s", username, resp.StatusCode, body))
}
}()
@@ -151,7 +151,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
}
}()
if !isIn200s(resp.StatusCode) {
- body, _ := ioutil.ReadAll(resp.Body)
+ body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("error updating vhost permissions for %s - %d: %s", vhost, resp.StatusCode, body)
}
return nil
@@ -180,7 +180,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
}
}()
if !isIn200s(resp.StatusCode) {
- body, _ := ioutil.ReadAll(resp.Body)
+ body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("error updating vhost permissions for %s - %d: %s", vhost, resp.StatusCode, body)
}
return nil
diff --git a/builtin/logical/transit/path_hmac.go b/builtin/logical/transit/path_hmac.go
index 0465b8dfa2..f71c9516ea 100644
--- a/builtin/logical/transit/path_hmac.go
+++ b/builtin/logical/transit/path_hmac.go
@@ -257,7 +257,19 @@ func (b *backend) pathHMACVerify(ctx context.Context, req *logical.Request, d *f
name := d.Get("name").(string)
algorithm := d.Get("urlalgorithm").(string)
if algorithm == "" {
- algorithm = d.Get("algorithm").(string)
+ hashAlgorithmRaw, hasHashAlgorithm := d.GetOk("hash_algorithm")
+ algorithmRaw, hasAlgorithm := d.GetOk("algorithm")
+
+ // As `algorithm` is deprecated, make sure we only read it if
+ // `hash_algorithm` is not present.
+ switch {
+ case hasHashAlgorithm:
+ algorithm = hashAlgorithmRaw.(string)
+ case hasAlgorithm:
+ algorithm = algorithmRaw.(string)
+ default:
+ algorithm = d.Get("hash_algorithm").(string)
+ }
}
// Get the policy
diff --git a/builtin/logical/transit/path_hmac_test.go b/builtin/logical/transit/path_hmac_test.go
index 4fa0fbce31..3f21106c4c 100644
--- a/builtin/logical/transit/path_hmac_test.go
+++ b/builtin/logical/transit/path_hmac_test.go
@@ -94,17 +94,40 @@ func TestTransit_HMAC(t *testing.T) {
}
// Now verify
+ verify := func() {
+ t.Helper()
+
+ resp, err = b.HandleRequest(context.Background(), req)
+ if err != nil {
+ t.Fatalf("%v: %v", err, resp)
+ }
+ if resp == nil {
+ t.Fatal("expected non-nil response")
+ }
+ if errStr, ok := resp.Data["error"]; ok {
+ t.Fatalf("error validating hmac: %s", errStr)
+ }
+ if resp.Data["valid"].(bool) == false {
+ t.Fatalf(fmt.Sprintf("error validating hmac;\nreq:\n%#v\nresp:\n%#v", *req, *resp))
+ }
+ }
req.Path = strings.ReplaceAll(req.Path, "hmac", "verify")
req.Data["hmac"] = value.(string)
- resp, err = b.HandleRequest(context.Background(), req)
- if err != nil {
- t.Fatalf("%v: %v", err, resp)
- }
- if resp == nil {
- t.Fatal("expected non-nil response")
- }
- if resp.Data["valid"].(bool) == false {
- panic(fmt.Sprintf("error validating hmac;\nreq:\n%#v\nresp:\n%#v", *req, *resp))
+ verify()
+
+ // If `algorithm` parameter is used, try with `hash_algorithm` as well
+ if algorithm, ok := req.Data["algorithm"]; ok {
+ // Note that `hash_algorithm` takes precedence over `algorithm`, since the
+ // latter is deprecated.
+ req.Data["hash_algorithm"] = algorithm
+ req.Data["algorithm"] = "xxx"
+ defer func() {
+ // Restore the req fields, since it is re-used by the tests below
+ delete(req.Data, "hash_algorithm")
+ req.Data["algorithm"] = algorithm
+ }()
+
+ verify()
}
}
diff --git a/changelog/10624.txt b/changelog/10624.txt
new file mode 100644
index 0000000000..fdb473b80d
--- /dev/null
+++ b/changelog/10624.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+storage/azure: Updated metadata endpoint to `GetMSIEndpoint`, which supports more than just the metadata service.
+```
diff --git a/changelog/11084.txt b/changelog/11084.txt
new file mode 100644
index 0000000000..444c93da99
--- /dev/null
+++ b/changelog/11084.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+serviceregistration: Added support for Consul ServiceMeta tags from config file from the new `service_meta` config field.
+```
diff --git a/changelog/14723.txt b/changelog/14723.txt
new file mode 100644
index 0000000000..04953430d8
--- /dev/null
+++ b/changelog/14723.txt
@@ -0,0 +1,4 @@
+```release-note:improvement
+core/identity: allow identity backend to be tuned using standard secrets backend tuning parameters.
+```
+
diff --git a/changelog/16484.txt b/changelog/16484.txt
new file mode 100644
index 0000000000..055f214dab
--- /dev/null
+++ b/changelog/16484.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+auth/appid, auth/cert, auth/github, auth/ldap, auth/okta, auth/radius, auth/userpass: fixed an issue with policy name normalization that would prevent a token associated with a policy containing an uppercase character to be renewed.
+```
diff --git a/changelog/16974.txt b/changelog/16974.txt
new file mode 100644
index 0000000000..202670ea43
--- /dev/null
+++ b/changelog/16974.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+cli: Add a `--dev-no-kv` flag to prevent auto mounting a key-value secret backend when running a dev server
+```
diff --git a/changelog/17007.txt b/changelog/17007.txt
new file mode 100644
index 0000000000..6c2a2801b2
--- /dev/null
+++ b/changelog/17007.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+auth/token: fixes an edge case bug that "identity_policies" is nil and causes cli vault login error
+```
diff --git a/changelog/19064.txt b/changelog/19064.txt
new file mode 100644
index 0000000000..cf31525e25
--- /dev/null
+++ b/changelog/19064.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+core/cli: Example 'help' pages for vault read / write docs improved.
+```
diff --git a/changelog/21159.txt b/changelog/21159.txt
new file mode 100644
index 0000000000..25c1e53d90
--- /dev/null
+++ b/changelog/21159.txt
@@ -0,0 +1,4 @@
+```release-note:improvement
+storage/dynamodb: Speed up list and delete of large directories by only requesting keys from DynamoDB
+```
+
diff --git a/changelog/21993.txt b/changelog/21993.txt
new file mode 100644
index 0000000000..856cfc9662
--- /dev/null
+++ b/changelog/21993.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+cli: Allow vault CLI HTTP headers to be specified using the JSON-encoded VAULT_HEADERS environment variable
+```
\ No newline at end of file
diff --git a/changelog/25080.txt b/changelog/25080.txt
new file mode 100644
index 0000000000..ad43618d82
--- /dev/null
+++ b/changelog/25080.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+storage/raft: Fix auto_join not working with mDNS provider.
+```
diff --git a/changelog/26020.txt b/changelog/26020.txt
index 5ce91856bf..2833bf64df 100644
--- a/changelog/26020.txt
+++ b/changelog/26020.txt
@@ -1,3 +1,7 @@
```release-note:improvement
core/activity: Include ACME clients in activity log responses
```
+
+```release-note:improvement
+ui: Display ACME clients on a separate page in the UI.
+```
diff --git a/changelog/26073.txt b/changelog/26073.txt
new file mode 100644
index 0000000000..90a964db99
--- /dev/null
+++ b/changelog/26073.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+identity: alias metadata is now returned when listing entity aliases
+```
diff --git a/changelog/26570.txt b/changelog/26570.txt
new file mode 100644
index 0000000000..79efe31414
--- /dev/null
+++ b/changelog/26570.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+agent: Add metric (vault.agent.authenticated) that is set to 1 when vault agent has a valid token and zero if it does not.
+```
\ No newline at end of file
diff --git a/changelog/26660.txt b/changelog/26660.txt
new file mode 100644
index 0000000000..9490cd0b6e
--- /dev/null
+++ b/changelog/26660.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+storage/etcd: Update etcd3 client to v3.5.13 to allow use of TLSv1.3.
+```
diff --git a/changelog/26828.txt b/changelog/26828.txt
new file mode 100644
index 0000000000..4c9a004c46
--- /dev/null
+++ b/changelog/26828.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+secrets/database: Add support for GCP CloudSQL private IP's.
+```
diff --git a/changelog/26868.txt b/changelog/26868.txt
new file mode 100644
index 0000000000..3a25d05efd
--- /dev/null
+++ b/changelog/26868.txt
@@ -0,0 +1,3 @@
+```release-note:change
+api: Update backoff/v3 to backoff/v4.3.0
+```
\ No newline at end of file
diff --git a/changelog/27093.txt b/changelog/27093.txt
new file mode 100644
index 0000000000..a24becec3e
--- /dev/null
+++ b/changelog/27093.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+pki: Fix error in cross-signing using ed25519 keys
+```
diff --git a/changelog/27120.txt b/changelog/27120.txt
new file mode 100644
index 0000000000..3a9630b986
--- /dev/null
+++ b/changelog/27120.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Fix KVv2 cursor jumping inside json editor after initial input.
+```
\ No newline at end of file
diff --git a/changelog/27123.txt b/changelog/27123.txt
new file mode 100644
index 0000000000..f23dd835c5
--- /dev/null
+++ b/changelog/27123.txt
@@ -0,0 +1,6 @@
+```release-note:improvement
+agent/sink: Allow configuration of the user and group ID of the file sink.
+```
+```release-note:improvement
+proxy/sink: Allow configuration of the user and group ID of the file sink.
+```
diff --git a/changelog/27130.txt b/changelog/27130.txt
new file mode 100644
index 0000000000..ba3352c412
--- /dev/null
+++ b/changelog/27130.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/centrify: Remove the deprecated Centrify auth method plugin
+```
diff --git a/changelog/27131.txt b/changelog/27131.txt
new file mode 100644
index 0000000000..465da55fe9
--- /dev/null
+++ b/changelog/27131.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Fix configuration link from Secret Engine list view for Ember engines.
+```
\ No newline at end of file
diff --git a/changelog/27132.txt b/changelog/27132.txt
new file mode 100644
index 0000000000..2c51945045
--- /dev/null
+++ b/changelog/27132.txt
@@ -0,0 +1,3 @@
+```release-note:change
+database/snowflake: Update plugin to v0.11.0
+```
diff --git a/changelog/27133.txt b/changelog/27133.txt
new file mode 100644
index 0000000000..d19c4b849b
--- /dev/null
+++ b/changelog/27133.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/alicloud: Update plugin to v0.18.0
+```
diff --git a/changelog/27134.txt b/changelog/27134.txt
new file mode 100644
index 0000000000..e477acb87d
--- /dev/null
+++ b/changelog/27134.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/alicloud: Update plugin to v0.17.0
+```
diff --git a/changelog/27136.txt b/changelog/27136.txt
new file mode 100644
index 0000000000..24be2b0e0a
--- /dev/null
+++ b/changelog/27136.txt
@@ -0,0 +1,3 @@
+```release-note:change
+database/elasticsearch: Update plugin to v0.15.0
+```
diff --git a/changelog/27137.txt b/changelog/27137.txt
new file mode 100644
index 0000000000..e977dd4298
--- /dev/null
+++ b/changelog/27137.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/openldap: Update plugin to v0.13.0
+```
diff --git a/changelog/27139.txt b/changelog/27139.txt
new file mode 100644
index 0000000000..1b7915fc6d
--- /dev/null
+++ b/changelog/27139.txt
@@ -0,0 +1,3 @@
+```release-note:change
+database/redis-elasticache: Update plugin to v0.4.0
+```
diff --git a/changelog/27140.txt b/changelog/27140.txt
new file mode 100644
index 0000000000..4910718fb8
--- /dev/null
+++ b/changelog/27140.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/gcp: Update plugin to v0.18.0
+```
diff --git a/changelog/27141.txt b/changelog/27141.txt
new file mode 100644
index 0000000000..b34464a809
--- /dev/null
+++ b/changelog/27141.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/azure: Update plugin to v0.19.0
+```
diff --git a/changelog/27142.txt b/changelog/27142.txt
new file mode 100644
index 0000000000..9a36667fc3
--- /dev/null
+++ b/changelog/27142.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/oci: Update plugin to v0.16.0
+```
diff --git a/changelog/27143.txt b/changelog/27143.txt
new file mode 100644
index 0000000000..9e0f838355
--- /dev/null
+++ b/changelog/27143.txt
@@ -0,0 +1,3 @@
+```release-note:change
+database/mongodbatlas: Update plugin to v0.12.0
+```
diff --git a/changelog/27145.txt b/changelog/27145.txt
new file mode 100644
index 0000000000..45bca4ba1e
--- /dev/null
+++ b/changelog/27145.txt
@@ -0,0 +1,3 @@
+```release-note:change
+database/couchbase: Update plugin to v0.11.0
+```
diff --git a/changelog/27146.txt b/changelog/27146.txt
new file mode 100644
index 0000000000..0e106b92f6
--- /dev/null
+++ b/changelog/27146.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/azure: Update plugin to v0.18.0
+```
diff --git a/changelog/27147.txt b/changelog/27147.txt
new file mode 100644
index 0000000000..30d13d3661
--- /dev/null
+++ b/changelog/27147.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/terraform: Update plugin to v0.8.0
+```
diff --git a/changelog/27149.txt b/changelog/27149.txt
new file mode 100644
index 0000000000..653851c940
--- /dev/null
+++ b/changelog/27149.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/mongodbatlas: Update plugin to v0.12.0
+```
diff --git a/changelog/27159.txt b/changelog/27159.txt
new file mode 100644
index 0000000000..a21f894d05
--- /dev/null
+++ b/changelog/27159.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/kv: Update plugin to v0.19.0
+```
diff --git a/changelog/27161.txt b/changelog/27161.txt
new file mode 100644
index 0000000000..5764f028bd
--- /dev/null
+++ b/changelog/27161.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/cf: Update plugin to v0.17.0
+```
diff --git a/changelog/27163.txt b/changelog/27163.txt
new file mode 100644
index 0000000000..307cb66bf9
--- /dev/null
+++ b/changelog/27163.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/gcpkms: Update plugin to v0.17.0
+```
diff --git a/changelog/27164.txt b/changelog/27164.txt
new file mode 100644
index 0000000000..4c942e1b99
--- /dev/null
+++ b/changelog/27164.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/gcp: Update plugin to v0.19.0
+```
diff --git a/changelog/27172.txt b/changelog/27172.txt
new file mode 100644
index 0000000000..60e88ec479
--- /dev/null
+++ b/changelog/27172.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/ad: Update plugin to v0.18.0
+```
diff --git a/changelog/27177.txt b/changelog/27177.txt
new file mode 100644
index 0000000000..c01050b6fa
--- /dev/null
+++ b/changelog/27177.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/kerberos: Update plugin to v0.12.0
+```
diff --git a/changelog/27178.txt b/changelog/27178.txt
new file mode 100644
index 0000000000..c84c67f34e
--- /dev/null
+++ b/changelog/27178.txt
@@ -0,0 +1,3 @@
+```release-note:change
+ui/kubernetes: Update the roles filter-input to use explicit search.
+```
diff --git a/changelog/27184.txt b/changelog/27184.txt
new file mode 100644
index 0000000000..500045efb5
--- /dev/null
+++ b/changelog/27184.txt
@@ -0,0 +1,3 @@
+```release-note:change
+core/identity: improve performance for secondary nodes receiving identity related updates through replication
+```
diff --git a/changelog/27186.txt b/changelog/27186.txt
new file mode 100644
index 0000000000..b8d6adaf25
--- /dev/null
+++ b/changelog/27186.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/kubernetes: Update plugin to v0.19.0
+```
diff --git a/changelog/27187.txt b/changelog/27187.txt
new file mode 100644
index 0000000000..a723b1b4c5
--- /dev/null
+++ b/changelog/27187.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/kubernetes: Update plugin to v0.8.0
+```
diff --git a/changelog/27202.txt b/changelog/27202.txt
new file mode 100644
index 0000000000..224f976bba
--- /dev/null
+++ b/changelog/27202.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+auth/cert: Merge error messages returned in login failures and include error when present
+```
diff --git a/changelog/27203.txt b/changelog/27203.txt
new file mode 100644
index 0000000000..b0dee9ee38
--- /dev/null
+++ b/changelog/27203.txt
@@ -0,0 +1,3 @@
+```release-note:feature
+**LDAP Secrets engine hierarchical path support**: Hierarchical path handling is now supported for role and set APIs.
+```
diff --git a/changelog/27211.txt b/changelog/27211.txt
new file mode 100644
index 0000000000..26bf725ebf
--- /dev/null
+++ b/changelog/27211.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter.
+```
diff --git a/changelog/27262.txt b/changelog/27262.txt
new file mode 100644
index 0000000000..93c2fbe3f0
--- /dev/null
+++ b/changelog/27262.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui/secrets-sync: Hide Secrets Sync from the sidebar nav if user does not have access to the feature.
+```
diff --git a/changelog/27263.txt b/changelog/27263.txt
new file mode 100644
index 0000000000..cb008c59fa
--- /dev/null
+++ b/changelog/27263.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Do not show resultant-ACL banner when ancestor namespace grants wildcard access.
+```
diff --git a/changelog/27265.txt b/changelog/27265.txt
new file mode 100644
index 0000000000..926b2c7a07
--- /dev/null
+++ b/changelog/27265.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+cli: Fixed an erroneous warning appearing about `-address` not being set when it is.
+```
diff --git a/changelog/27277.txt b/changelog/27277.txt
new file mode 100644
index 0000000000..1a7abc5a6f
--- /dev/null
+++ b/changelog/27277.txt
@@ -0,0 +1,4 @@
+```release-note:bug
+storage/raft (enterprise): Fix a regression introduced in 1.15.8 that causes
+autopilot to fail to discover new server versions and so not trigger an upgrade.
+```
\ No newline at end of file
diff --git a/changelog/27289.txt b/changelog/27289.txt
new file mode 100644
index 0000000000..3e10cf0a02
--- /dev/null
+++ b/changelog/27289.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Allow users to wrap inputted data again instead of resetting form
+```
diff --git a/changelog/27346.txt b/changelog/27346.txt
new file mode 100644
index 0000000000..17f50216cb
--- /dev/null
+++ b/changelog/27346.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Update language in Transit secret engine to reflect that not all keys are for encyryption
+```
diff --git a/changelog/27348.txt b/changelog/27348.txt
new file mode 100644
index 0000000000..ec7ece0b85
--- /dev/null
+++ b/changelog/27348.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Mask obfuscated fields when creating/editing a Secrets sync destination.
+```
diff --git a/changelog/27350.txt b/changelog/27350.txt
new file mode 100644
index 0000000000..ddf95bc005
--- /dev/null
+++ b/changelog/27350.txt
@@ -0,0 +1,4 @@
+```release-note:change
+activity log: Deprecated the field "default_report_months". Instead, the billing start time will be used to determine the start time
+when querying the activity log endpoints.
+```
\ No newline at end of file
diff --git a/changelog/27352.txt b/changelog/27352.txt
new file mode 100644
index 0000000000..70a7fa3661
--- /dev/null
+++ b/changelog/27352.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: fix issue where a month without new clients breaks the client count dashboard
+```
diff --git a/changelog/27366.txt b/changelog/27366.txt
new file mode 100644
index 0000000000..16b936e5df
--- /dev/null
+++ b/changelog/27366.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Fix a bug where disabling TTL on the AWS credential form would still send TTL value
+```
\ No newline at end of file
diff --git a/changelog/27379.txt b/changelog/27379.txt
new file mode 100644
index 0000000000..1744873c28
--- /dev/null
+++ b/changelog/27379.txt
@@ -0,0 +1,5 @@
+```release-note:change
+activity: The startTime will be set to the start of the current billing period by default.
+The endTime will be set to the end of the current month. This applies to /sys/internal/counters/activity,
+/sys/internal/counters/activity/export, and the vault operator usage command that utilizes /sys/internal/counters/activity.
+```
diff --git a/changelog/27394.txt b/changelog/27394.txt
new file mode 100644
index 0000000000..81a04305f4
--- /dev/null
+++ b/changelog/27394.txt
@@ -0,0 +1,4 @@
+```release-note:feature
+**Vault Minimal Version**: Add the ability to build a minimal version of Vault
+with only core features using the BUILD_MINIMAL environment variable.
+```
diff --git a/changelog/27405.txt b/changelog/27405.txt
new file mode 100644
index 0000000000..ac5162e801
--- /dev/null
+++ b/changelog/27405.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: AWS credentials form sets credential_type from backing role
+```
diff --git a/changelog/27424.txt b/changelog/27424.txt
new file mode 100644
index 0000000000..fcfb93ea4b
--- /dev/null
+++ b/changelog/27424.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Allow creation of session_token type roles for AWS secret backend
+```
\ No newline at end of file
diff --git a/changelog/27426.txt b/changelog/27426.txt
new file mode 100644
index 0000000000..ac18d43862
--- /dev/null
+++ b/changelog/27426.txt
@@ -0,0 +1,4 @@
+```release-note:change
+activity log: Deprecates the current_billing_period field for /sys/internal/counters/activity. The default start time
+will automatically be set the billing period start date.
+```
\ No newline at end of file
diff --git a/changelog/27435.txt b/changelog/27435.txt
new file mode 100644
index 0000000000..916a81c901
--- /dev/null
+++ b/changelog/27435.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+helper/pkcs7: Fix parsing certain messages containing only certificates
+```
diff --git a/changelog/27455.txt b/changelog/27455.txt
new file mode 100644
index 0000000000..38b7c92ae6
--- /dev/null
+++ b/changelog/27455.txt
@@ -0,0 +1,3 @@
+```release-note:change
+ui: Uses the internal/counters/activity/export endpoint for client count export data.
+```
\ No newline at end of file
diff --git a/changelog/27459.txt b/changelog/27459.txt
new file mode 100644
index 0000000000..d46570f5a4
--- /dev/null
+++ b/changelog/27459.txt
@@ -0,0 +1,4 @@
+```release-note:bug
+config: Vault TCP listener config now correctly supports the documented proxy_protocol_behavior
+setting of 'deny_unauthorized'
+```
diff --git a/changelog/27464.txt b/changelog/27464.txt
new file mode 100644
index 0000000000..ff9d9f508b
--- /dev/null
+++ b/changelog/27464.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+storage/raft: Improve autopilot logging on startup to show config values clearly and avoid spurious logs
+```
diff --git a/changelog/27474.txt b/changelog/27474.txt
new file mode 100644
index 0000000000..86c773517a
--- /dev/null
+++ b/changelog/27474.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses.
+```
diff --git a/changelog/27479.txt b/changelog/27479.txt
new file mode 100644
index 0000000000..355fbbafbe
--- /dev/null
+++ b/changelog/27479.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Ensure token expired banner displays when batch token expires
+```
\ No newline at end of file
diff --git a/changelog/27498.txt b/changelog/27498.txt
new file mode 100644
index 0000000000..ac19156073
--- /dev/null
+++ b/changelog/27498.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/jwt: Update plugin to v0.21.0
+```
diff --git a/changelog/27510.txt b/changelog/27510.txt
new file mode 100644
index 0000000000..af574898b6
--- /dev/null
+++ b/changelog/27510.txt
@@ -0,0 +1,6 @@
+```release-note:improvement
+agent: Add the ability to dump pprof to the filesystem using SIGUSR2
+```
+```release-note:improvement
+proxy: Add the ability to dump pprof to the filesystem using SIGUSR2
+```
diff --git a/changelog/27518.txt b/changelog/27518.txt
new file mode 100644
index 0000000000..c8412c62b0
--- /dev/null
+++ b/changelog/27518.txt
@@ -0,0 +1,7 @@
+```release-note:bug
+agent: Fixed an issue causing excessive CPU usage during normal operation
+```
+
+```release-note:bug
+proxy: Fixed an issue causing excessive CPU usage during normal operation
+```
\ No newline at end of file
diff --git a/changelog/27531.txt b/changelog/27531.txt
new file mode 100644
index 0000000000..3dda984d1d
--- /dev/null
+++ b/changelog/27531.txt
@@ -0,0 +1,5 @@
+```release-note:bug
+core/audit: Audit logging a Vault request/response checks if the existing context
+is cancelled and will now use a new context with a 5 second timeout.
+If the existing context is cancelled a new context, will be used.
+```
\ No newline at end of file
diff --git a/changelog/27538.txt b/changelog/27538.txt
new file mode 100644
index 0000000000..e1d1448150
--- /dev/null
+++ b/changelog/27538.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Creates separate section for updating sensitive creds for Secrets sync create/edit view.
+```
diff --git a/changelog/27547.txt b/changelog/27547.txt
new file mode 100644
index 0000000000..ca18d264a4
--- /dev/null
+++ b/changelog/27547.txt
@@ -0,0 +1,4 @@
+```release-note:improvement
+activity log: Changes how new client counts in the current month are estimated, in order to return more
+visibly sensible totals.
+```
\ No newline at end of file
diff --git a/changelog/27559.txt b/changelog/27559.txt
new file mode 100644
index 0000000000..a9afccdc98
--- /dev/null
+++ b/changelog/27559.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Remove deprecated `current_billing_period` from dashboard activity log request
+```
diff --git a/changelog/27563.txt b/changelog/27563.txt
new file mode 100644
index 0000000000..294b5e7cf6
--- /dev/null
+++ b/changelog/27563.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+storage/azure: Fix invalid account name initialization bug
+```
\ No newline at end of file
diff --git a/changelog/27569.txt b/changelog/27569.txt
new file mode 100644
index 0000000000..cb81aa23df
--- /dev/null
+++ b/changelog/27569.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER.
+```
diff --git a/changelog/27574.txt b/changelog/27574.txt
new file mode 100644
index 0000000000..8c1f888242
--- /dev/null
+++ b/changelog/27574.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Display an error and force a timeout when TOTP passcode is incorrect
+```
\ No newline at end of file
diff --git a/changelog/27578.txt b/changelog/27578.txt
new file mode 100644
index 0000000000..3a1b62a2a5
--- /dev/null
+++ b/changelog/27578.txt
@@ -0,0 +1,3 @@
+```release-note:change
+cli: The undocumented `-dev-three-node` and `-dev-four-cluster` CLI options have been removed.
+```
diff --git a/changelog/27589.txt b/changelog/27589.txt
new file mode 100644
index 0000000000..844857ff1e
--- /dev/null
+++ b/changelog/27589.txt
@@ -0,0 +1,4 @@
+```release-note:bug
+core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`,
+which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection.
+```
\ No newline at end of file
diff --git a/changelog/27605.txt b/changelog/27605.txt
new file mode 100644
index 0000000000..b449daf789
--- /dev/null
+++ b/changelog/27605.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+storage/raft: Bump raft to v1.7.0 which includes pre-vote. This should make clusters more stable during network partitions.
+```
diff --git a/changelog/27620.txt b/changelog/27620.txt
new file mode 100644
index 0000000000..e808a0b4e0
--- /dev/null
+++ b/changelog/27620.txt
@@ -0,0 +1,5 @@
+```release-note:feature
+**AWS secrets engine STS session tags support**: Adds support for setting STS
+session tags when generating temporary credentials using the AWS secrets
+engine.
+```
diff --git a/changelog/27631.txt b/changelog/27631.txt
new file mode 100644
index 0000000000..d71fbb5508
--- /dev/null
+++ b/changelog/27631.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+core: Fixed an issue with performance standbys not being able to handle rotate root requests.
+```
\ No newline at end of file
diff --git a/changelog/27633.txt b/changelog/27633.txt
new file mode 100644
index 0000000000..1f5156b3bd
--- /dev/null
+++ b/changelog/27633.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+core: make authLock and mountsLock in Core configurable via the detect_deadlocks configuration parameter.
+```
\ No newline at end of file
diff --git a/changelog/27652.txt b/changelog/27652.txt
new file mode 100644
index 0000000000..7c9d257fd9
--- /dev/null
+++ b/changelog/27652.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/azure: Update plugin to v0.19.2
+```
diff --git a/changelog/27656.txt b/changelog/27656.txt
new file mode 100644
index 0000000000..e4445f826a
--- /dev/null
+++ b/changelog/27656.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+license utilization reporting (enterprise): Auto-roll billing start date.
+```
\ No newline at end of file
diff --git a/changelog/27660.txt b/changelog/27660.txt
new file mode 100644
index 0000000000..e754dbbfa3
--- /dev/null
+++ b/changelog/27660.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme.
+```
\ No newline at end of file
diff --git a/changelog/27681.txt b/changelog/27681.txt
new file mode 100644
index 0000000000..13f5f829d5
--- /dev/null
+++ b/changelog/27681.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+secrets/pki: fix lack of serial number to a certificate read resulting in a server side error.
+```
\ No newline at end of file
diff --git a/changelog/27694.txt b/changelog/27694.txt
new file mode 100644
index 0000000000..6f5d03e916
--- /dev/null
+++ b/changelog/27694.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+cli: Fixed issue with `vault hcp connect` where HCP resources with uppercase letters were inaccessible when entering the correct project name.
+```
\ No newline at end of file
diff --git a/changelog/27696.txt b/changelog/27696.txt
new file mode 100644
index 0000000000..42956c3360
--- /dev/null
+++ b/changelog/27696.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors
+```
diff --git a/changelog/27724.txt b/changelog/27724.txt
new file mode 100644
index 0000000000..0e58502bbc
--- /dev/null
+++ b/changelog/27724.txt
@@ -0,0 +1,3 @@
+```release-note:change
+auth/cf: Update plugin to v0.18.0
+```
diff --git a/changelog/27726.txt b/changelog/27726.txt
new file mode 100644
index 0000000000..80f2cc850f
--- /dev/null
+++ b/changelog/27726.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+raft/autopilot: Fixed panic that may occur during shutdown
+```
diff --git a/changelog/27728.txt b/changelog/27728.txt
new file mode 100644
index 0000000000..6c1c18ef50
--- /dev/null
+++ b/changelog/27728.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default.
+```
\ No newline at end of file
diff --git a/changelog/27730.txt b/changelog/27730.txt
new file mode 100644
index 0000000000..d265306293
--- /dev/null
+++ b/changelog/27730.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+proxy/cache (enterprise): Fixed an issue where cached static secrets could fail to update if the secrets belonged to a non-root namespace.
+```
diff --git a/changelog/27742.txt b/changelog/27742.txt
new file mode 100644
index 0000000000..6f958a02a7
--- /dev/null
+++ b/changelog/27742.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call.
+```
\ No newline at end of file
diff --git a/changelog/27750.txt b/changelog/27750.txt
new file mode 100644
index 0000000000..04c24fe59e
--- /dev/null
+++ b/changelog/27750.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+core/identity: Fixed an issue where deleted/reassigned entity-aliases were not removed from in-memory database.
+```
diff --git a/changelog/27790.txt b/changelog/27790.txt
new file mode 100644
index 0000000000..1475d0831a
--- /dev/null
+++ b/changelog/27790.txt
@@ -0,0 +1,3 @@
+```release-note:change
+activity (enterprise): filter all fields in client count responses by the request namespace
+```
\ No newline at end of file
diff --git a/changelog/27796.txt b/changelog/27796.txt
new file mode 100644
index 0000000000..7a1e7ebac3
--- /dev/null
+++ b/changelog/27796.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: simplify the date range editing experience in the client counts dashboard.
+```
\ No newline at end of file
diff --git a/changelog/27799.txt b/changelog/27799.txt
new file mode 100644
index 0000000000..217f6d78d9
--- /dev/null
+++ b/changelog/27799.txt
@@ -0,0 +1,3 @@
+```release-note:change
+consul-template: updated to version 0.39.1
+```
\ No newline at end of file
diff --git a/changelog/27809.txt b/changelog/27809.txt
new file mode 100644
index 0000000000..332c9155d9
--- /dev/null
+++ b/changelog/27809.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success.
+```
\ No newline at end of file
diff --git a/changelog/27816.txt b/changelog/27816.txt
new file mode 100644
index 0000000000..92dd2d7bb9
--- /dev/null
+++ b/changelog/27816.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: remove initial start/end parameters on the activity call for client counts dashboard.
+```
\ No newline at end of file
diff --git a/changelog/27830.txt b/changelog/27830.txt
new file mode 100644
index 0000000000..6a3d7e3041
--- /dev/null
+++ b/changelog/27830.txt
@@ -0,0 +1,3 @@
+```release-note:change
+activity (enterprise): remove deprecated fields distinct_entities and non_entity_tokens
+```
\ No newline at end of file
diff --git a/changelog/27831.txt b/changelog/27831.txt
new file mode 100644
index 0000000000..27224ef7db
--- /dev/null
+++ b/changelog/27831.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: For AWS and SSH secret engines hide mount configuration details in toggle and display configuration details or cta.
+```
\ No newline at end of file
diff --git a/changelog/27846.txt b/changelog/27846.txt
new file mode 100644
index 0000000000..50cba99062
--- /dev/null
+++ b/changelog/27846.txt
@@ -0,0 +1,7 @@
+```release-note:change
+activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now requires the `sudo` ACL capability.
+```
+
+```release-note:improvement
+activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) can now be called in non-root namespaces. Resulting records will be filtered to include the requested namespace (via `X-Vault-Namespace` header or within the path) and all child namespaces.
+```
diff --git a/changelog/27858.txt b/changelog/27858.txt
new file mode 100644
index 0000000000..398d94ac43
--- /dev/null
+++ b/changelog/27858.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+auth/aws: fixes an issue where not supplying an external id was interpreted as an empty external id
+```
diff --git a/changelog/27859.txt b/changelog/27859.txt
new file mode 100644
index 0000000000..d6836641fa
--- /dev/null
+++ b/changelog/27859.txt
@@ -0,0 +1,4 @@
+```release-note:improvement
+audit: sinks (file, socket, syslog) will attempt to log errors to the server operational
+log before returning (if there are errors to log, and the context is done).
+```
diff --git a/changelog/27881.txt b/changelog/27881.txt
new file mode 100644
index 0000000000..0b3f9aa7fd
--- /dev/null
+++ b/changelog/27881.txt
@@ -0,0 +1,4 @@
+```release-note:bug
+sys: Fix a bug where mounts of external plugins that were registered before Vault v1.0.0 could not be tuned to
+use versioned plugins.
+```
\ No newline at end of file
diff --git a/changelog/27883.txt b/changelog/27883.txt
new file mode 100644
index 0000000000..63752f78f1
--- /dev/null
+++ b/changelog/27883.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+website/docs: Added API documentation for Azure Secrets Engine delete role
+```
\ No newline at end of file
diff --git a/changelog/27891.txt b/changelog/27891.txt
new file mode 100644
index 0000000000..c5962285e7
--- /dev/null
+++ b/changelog/27891.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+proxy/cache (enterprise): Fixed an issue where Proxy would not correctly update KV secrets when talking to a perf standby. Proxy will now attempt to forward requests to update secrets triggered by events to the active node. Note that this requires `allow_forwarding_via_header` to be configured on the cluster.
+```
diff --git a/changelog/27902.txt b/changelog/27902.txt
new file mode 100644
index 0000000000..e058e8d962
--- /dev/null
+++ b/changelog/27902.txt
@@ -0,0 +1,5 @@
+```release-note:improvement
+auth/cert: Cache full list of role trust information separately to avoid
+eviction, and avoid duplicate loading during multiple simultaneous logins on
+the same role.
+```
\ No newline at end of file
diff --git a/changelog/27918.txt b/changelog/27918.txt
new file mode 100644
index 0000000000..bdf34609ef
--- /dev/null
+++ b/changelog/27918.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Move secret-engine configuration create/edit from routing `vault/settings/secrets/configure/` to `vault/secrets//configuration/edit`
+```
\ No newline at end of file
diff --git a/changelog/27939.txt b/changelog/27939.txt
new file mode 100644
index 0000000000..093b742b90
--- /dev/null
+++ b/changelog/27939.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured.
+```
\ No newline at end of file
diff --git a/changelog/27950.txt b/changelog/27950.txt
new file mode 100644
index 0000000000..27a1e53b17
--- /dev/null
+++ b/changelog/27950.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+secrets/database/hana: Update HANA db client to v1.10.1
+```
diff --git a/changelog/27952.txt b/changelog/27952.txt
new file mode 100644
index 0000000000..aa7d2ba84f
--- /dev/null
+++ b/changelog/27952.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+audit: Internal implementation changes to the audit subsystem which improve performance.
+```
diff --git a/changelog/28016.txt b/changelog/28016.txt
new file mode 100644
index 0000000000..ef8f06b873
--- /dev/null
+++ b/changelog/28016.txt
@@ -0,0 +1,3 @@
+```release-note:change
+secrets/terraform: Update plugin to v0.9.0
+```
diff --git a/changelog/28024.txt b/changelog/28024.txt
new file mode 100644
index 0000000000..8d1fbaa0e2
--- /dev/null
+++ b/changelog/28024.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+database/postgres: Add new fields to the plugin's config endpoint for client certificate authentication.
+```
diff --git a/changelog/28042.txt b/changelog/28042.txt
new file mode 100644
index 0000000000..f49cad8ac5
--- /dev/null
+++ b/changelog/28042.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+activity: The sys/internal/counters/activity endpoint will return current month data when the end_date parameter is set to a future date.
+```
diff --git a/changelog/28056.txt b/changelog/28056.txt
new file mode 100644
index 0000000000..f39fbe2921
--- /dev/null
+++ b/changelog/28056.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+audit: Adds TRACE logging to log request/response under certain circumstances, and further improvements to the audit subsystem.
+```
\ No newline at end of file
diff --git a/changelog/28062.txt b/changelog/28062.txt
new file mode 100644
index 0000000000..c6a1fbef19
--- /dev/null
+++ b/changelog/28062.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+core/activity: Ensure client count queries that include the current month return consistent results by sorting the clients before performing estimation
+```
\ No newline at end of file
diff --git a/changelog/28064.txt b/changelog/28064.txt
new file mode 100644
index 0000000000..6f18843cad
--- /dev/null
+++ b/changelog/28064.txt
@@ -0,0 +1,7 @@
+```release-note:improvement
+activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now includes identity metadata about entity clients.
+```
+
+```release-note:change
+activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now responds with a status of 204 instead 400 when no data exists within the time range specified by `start_time` and `end_time`.
+```
diff --git a/changelog/28068.txt b/changelog/28068.txt
new file mode 100644
index 0000000000..ec608a67a1
--- /dev/null
+++ b/changelog/28068.txt
@@ -0,0 +1,7 @@
+```release-note:improvement
+cli: `vault operator usage` will now include a warning if the specified usage period contains estimated client counts.
+```
+
+```release-note:improvement
+activity: `/sys/internal/counters/activity` will now include a warning if the specified usage period contains estimated client counts.
+```
\ No newline at end of file
diff --git a/changelog/28076.txt b/changelog/28076.txt
new file mode 100644
index 0000000000..bb9adb9429
--- /dev/null
+++ b/changelog/28076.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+website/docs: corrected invalid json in sample payload for azure secrets engine create/update role
+```
\ No newline at end of file
diff --git a/changelog/28093.txt b/changelog/28093.txt
new file mode 100644
index 0000000000..830f53baa6
--- /dev/null
+++ b/changelog/28093.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: fixes toast (flash) alert message saying "created" when deleting a kv v2 secret
+```
\ No newline at end of file
diff --git a/changelog/9733.txt b/changelog/9733.txt
new file mode 100644
index 0000000000..f345cbd527
--- /dev/null
+++ b/changelog/9733.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+db/cassandra: Add `disable_host_initial_lookup` option to backend, allowing the disabling of initial host lookup.
+```
diff --git a/changelog/_go-ver-1180.txt b/changelog/_go-ver-1180.txt
new file mode 100644
index 0000000000..43ae0c2449
--- /dev/null
+++ b/changelog/_go-ver-1180.txt
@@ -0,0 +1,3 @@
+```release-note:change
+core: Bump Go version to 1.22.5
+```
diff --git a/command/agent.go b/command/agent.go
index 7bab660ce3..2e5f550a55 100644
--- a/command/agent.go
+++ b/command/agent.go
@@ -13,6 +13,7 @@ import (
"net"
"net/http"
"os"
+ "path/filepath"
"sort"
"strings"
"sync"
@@ -74,6 +75,7 @@ type AgentCommand struct {
ShutdownCh chan struct{}
SighupCh chan struct{}
+ SigUSR2Ch chan struct{}
tlsReloadFuncsLock sync.RWMutex
tlsReloadFuncs []reloadutil.ReloadFunc
@@ -758,6 +760,16 @@ func (c *AgentCommand) Run(args []string) int {
case c.reloadedCh <- struct{}{}:
default:
}
+ case <-c.SigUSR2Ch:
+ pprofPath := filepath.Join(os.TempDir(), "vault-agent-pprof")
+ cpuProfileDuration := time.Second * 1
+ err := WritePprofToFile(pprofPath, cpuProfileDuration)
+ if err != nil {
+ c.logger.Error(err.Error())
+ continue
+ }
+
+ c.logger.Info(fmt.Sprintf("Wrote pprof files to: %s", pprofPath))
case <-ctx.Done():
return nil
}
diff --git a/command/agent/template/template.go b/command/agent/template/template.go
index 402b5f50fc..f0619694a5 100644
--- a/command/agent/template/template.go
+++ b/command/agent/template/template.go
@@ -246,31 +246,24 @@ func (ts *Server) Run(ctx context.Context, incoming chan string, templates []*ct
ts.runner.Stop()
return nil
}
- default:
- // We are using default instead of a new case block to prioritize the case where <-incoming has a new value over
- // receiving an error message from the consul-template server
- select {
- case err := <-ts.runner.ServerErrCh:
- var responseError *api.ResponseError
- ok := errors.As(err, &responseError)
- if !ok {
- ts.logger.Error("template server: could not extract error response")
- continue
- }
- if responseError.StatusCode == 403 && strings.Contains(responseError.Error(), logical.ErrInvalidToken.Error()) && !tokenRenewalInProgress.Load() {
- ts.logger.Info("template server: received invalid token error")
-
- // Drain the error channel before sending a new error
- select {
- case <-invalidTokenCh:
- default:
- }
- invalidTokenCh <- err
- }
- default:
+ case err := <-ts.runner.ServerErrCh:
+ var responseError *api.ResponseError
+ ok := errors.As(err, &responseError)
+ if !ok {
+ ts.logger.Error("template server: could not extract error response")
continue
}
+ if responseError.StatusCode == 403 && strings.Contains(responseError.Error(), logical.ErrInvalidToken.Error()) && !tokenRenewalInProgress.Load() {
+ ts.logger.Info("template server: received invalid token error")
+ // Drain the error channel and incoming channel before sending a new error
+ select {
+ case <-invalidTokenCh:
+ case <-incoming:
+ default:
+ }
+ invalidTokenCh <- err
+ }
}
}
}
diff --git a/command/agent_test.go b/command/agent_test.go
index 235a8ede1a..17c74fc316 100644
--- a/command/agent_test.go
+++ b/command/agent_test.go
@@ -91,6 +91,7 @@ func testAgentCommand(tb testing.TB, logger hclog.Logger) (*cli.MockUi, *AgentCo
},
ShutdownCh: MakeShutdownCh(),
SighupCh: MakeSighupCh(),
+ SigUSR2Ch: MakeSigUSR2Ch(),
logger: logger,
startedCh: make(chan struct{}, 5),
reloadedCh: make(chan struct{}, 5),
diff --git a/command/agentproxyshared/auth/auth.go b/command/agentproxyshared/auth/auth.go
index 12c998da5a..91e189ed26 100644
--- a/command/agentproxyshared/auth/auth.go
+++ b/command/agentproxyshared/auth/auth.go
@@ -145,12 +145,18 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
backoffCfg := newAutoAuthBackoff(ah.minBackoff, ah.maxBackoff, ah.exitOnError)
ah.logger.Info("starting auth handler")
+
+ // Set unauthenticated when starting up
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
+
defer func() {
am.Shutdown()
close(ah.OutputCh)
close(ah.TemplateTokenCh)
close(ah.ExecTokenCh)
ah.logger.Info("auth handler stopped")
+ // Set unauthenticated when shutting down
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
}()
credCh := am.NewCreds()
@@ -217,6 +223,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("error creating client for authentication call", "error", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -244,6 +252,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("could not look up token", "err", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -264,6 +274,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("error getting path or data from method", "error", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -277,6 +289,7 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("error creating client for wrapped call", "error", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -300,10 +313,11 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
isTokenFileMethod = path == "auth/token/lookup-self"
if isTokenFileMethod {
token, _ := data["token"].(string)
- lookupSelfClient, err := clientToUse.CloneWithHeaders()
- if err != nil {
+ // The error is called clientErr as to not shadow the other err above it.
+ lookupSelfClient, clientErr := clientToUse.CloneWithHeaders()
+ if clientErr != nil {
ah.logger.Error("failed to clone client to perform token lookup")
- return err
+ return clientErr
}
lookupSelfClient.SetToken(token)
secret, err = lookupSelfClient.Auth().Token().LookupSelf()
@@ -315,6 +329,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("error authenticating", "error", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -330,6 +346,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if secret.WrapInfo == nil {
ah.logger.Error("authentication returned nil wrap info", "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -339,6 +357,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if secret.WrapInfo.Token == "" {
ah.logger.Error("authentication returned empty wrapped client token", "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -349,6 +369,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("failed to encode wrapinfo", "error", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -388,6 +410,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if secret == nil || secret.Data == nil {
ah.logger.Error("token file validation failed, token may be invalid", "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -398,6 +422,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if !ok || token == "" {
ah.logger.Error("token file validation returned empty client token", "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -414,6 +440,7 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
Renewable: renewable,
}
ah.logger.Info("authentication successful, sending token to sinks")
+
ah.OutputCh <- token
if ah.enableTemplateTokenCh {
ah.TemplateTokenCh <- token
@@ -430,6 +457,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if secret == nil || secret.Auth == nil {
ah.logger.Error("authentication returned nil auth info", "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -439,6 +468,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if secret.Auth.ClientToken == "" {
ah.logger.Error("authentication returned empty client token", "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -471,6 +502,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("error creating lifetime watcher", "error", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
if backoffSleep(ctx, backoffCfg) {
continue
@@ -479,6 +512,7 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
}
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "success"}, 1)
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 1)
// We don't want to trigger the renewal process for the root token
if isRootToken(leaseDuration, isTokenFileMethod, secret) {
ah.logger.Info("not starting token renewal process, as token is root token")
@@ -500,6 +534,8 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
if err != nil {
ah.logger.Error("error renewing token", "error", err, "backoff", backoffCfg)
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1)
+ // Set unauthenticated when authentication fails
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0)
// Add some exponential backoff so that if auth is successful
// but the watcher errors, we won't go into an immediate
@@ -525,19 +561,15 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error {
case <-watcher.RenewCh():
metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "success"}, 1)
+ // Set authenticated when authentication succeeds
+ metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 1)
ah.logger.Info("renewed auth token")
-
case <-credCh:
ah.logger.Info("auth method found new credentials, re-authenticating")
break LifetimeWatcherLoop
- default:
- select {
- case <-ah.InvalidToken:
- ah.logger.Info("invalid token found, re-authenticating")
- break LifetimeWatcherLoop
- default:
- continue
- }
+ case <-ah.InvalidToken:
+ ah.logger.Info("invalid token found, re-authenticating")
+ break LifetimeWatcherLoop
}
}
}
diff --git a/command/agentproxyshared/auth/gcp/gcp.go b/command/agentproxyshared/auth/gcp/gcp.go
index 5d913581bc..aaaf21d16a 100644
--- a/command/agentproxyshared/auth/gcp/gcp.go
+++ b/command/agentproxyshared/auth/gcp/gcp.go
@@ -8,7 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"time"
@@ -151,7 +151,7 @@ func (g *gcpMethod) Authenticate(ctx context.Context, client *api.Client) (retPa
return
}
defer resp.Body.Close()
- jwtBytes, err := ioutil.ReadAll(resp.Body)
+ jwtBytes, err := io.ReadAll(resp.Body)
if err != nil {
retErr = fmt.Errorf("error reading instance token response body: %w", err)
return
diff --git a/command/agentproxyshared/auth/kubernetes/kubernetes.go b/command/agentproxyshared/auth/kubernetes/kubernetes.go
index 639226505f..6f16a2b9b4 100644
--- a/command/agentproxyshared/auth/kubernetes/kubernetes.go
+++ b/command/agentproxyshared/auth/kubernetes/kubernetes.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"strings"
@@ -123,7 +122,7 @@ func (k *kubernetesMethod) readJWT() (string, error) {
}
defer data.Close()
- contentBytes, err := ioutil.ReadAll(data)
+ contentBytes, err := io.ReadAll(data)
if err != nil {
return "", err
}
diff --git a/command/agentproxyshared/cache/handler.go b/command/agentproxyshared/cache/handler.go
index 5801c8ebde..d136983178 100644
--- a/command/agentproxyshared/cache/handler.go
+++ b/command/agentproxyshared/cache/handler.go
@@ -11,7 +11,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"strings"
"sync/atomic"
@@ -86,6 +85,10 @@ func ProxyHandler(ctx context.Context, logger hclog.Logger, proxier Proxier, inm
logical.RespondError(w, http.StatusInternalServerError, fmt.Errorf("failed to get the response: %w", err))
}
return
+ } else if resp == nil {
+ metrics.IncrCounter([]string{"agent", "proxy", "error"}, 1)
+ logical.RespondError(w, http.StatusInternalServerError, fmt.Errorf("failed to get the response: %w", err))
+ return
}
err = sanitizeAutoAuthTokenResponse(ctx, logger, inmemSink, req, resp)
@@ -218,7 +221,7 @@ func sanitizeAutoAuthTokenResponse(ctx context.Context, logger hclog.Logger, inm
if resp.Response.Body != nil {
resp.Response.Body.Close()
}
- resp.Response.Body = ioutil.NopCloser(bytes.NewReader(bodyBytes))
+ resp.Response.Body = io.NopCloser(bytes.NewReader(bodyBytes))
resp.Response.ContentLength = int64(len(bodyBytes))
// Serialize and re-read the response
diff --git a/command/agentproxyshared/cache/lease_cache.go b/command/agentproxyshared/cache/lease_cache.go
index 6e8b564a62..a9ea65806d 100644
--- a/command/agentproxyshared/cache/lease_cache.go
+++ b/command/agentproxyshared/cache/lease_cache.go
@@ -411,7 +411,7 @@ func (c *LeaseCache) Send(ctx context.Context, req *SendRequest) (*SendResponse,
return nil, err
}
if cachedResp != nil {
- c.logger.Debug("returning cached static secret response", "id", staticSecretCacheId, "path", req.Request.URL.Path)
+ c.logger.Debug("returning cached static secret response", "id", staticSecretCacheId, "path", getStaticSecretPathFromRequest(req))
return cachedResp, nil
}
}
@@ -482,6 +482,7 @@ func (c *LeaseCache) Send(ctx context.Context, req *SendRequest) (*SendResponse,
// included in the request path.
index.RequestPath = getStaticSecretPathFromRequest(req)
+ c.logger.Trace("attempting to cache static secret with following request path", "request path", index.RequestPath)
err := c.cacheStaticSecret(ctx, req, resp, index)
if err != nil {
return nil, err
@@ -665,7 +666,7 @@ func (c *LeaseCache) cacheStaticSecret(ctx context.Context, req *SendRequest, re
func (c *LeaseCache) storeStaticSecretIndex(ctx context.Context, req *SendRequest, index *cachememdb.Index) error {
// Store the index in the cache
- c.logger.Debug("storing static secret response into the cache", "method", req.Request.Method, "path", req.Request.URL.Path, "id", index.ID)
+ c.logger.Debug("storing static secret response into the cache", "method", req.Request.Method, "path", index.RequestPath, "id", index.ID)
err := c.Set(ctx, index)
if err != nil {
c.logger.Error("failed to cache the proxied response", "error", err)
diff --git a/command/agentproxyshared/cache/proxy.go b/command/agentproxyshared/cache/proxy.go
index 503d981d60..231c5d9d20 100644
--- a/command/agentproxyshared/cache/proxy.go
+++ b/command/agentproxyshared/cache/proxy.go
@@ -57,7 +57,7 @@ func NewSendResponse(apiResponse *api.Response, responseBody []byte) (*SendRespo
}
// If a response body is separately provided we set that as the SendResponse.ResponseBody,
- // otherwise we will do an ioutil.ReadAll to extract the response body from apiResponse.
+ // otherwise we will do an io.ReadAll to extract the response body from apiResponse.
switch {
case len(responseBody) > 0:
resp.ResponseBody = responseBody
diff --git a/command/agentproxyshared/cache/static_secret_cache_updater.go b/command/agentproxyshared/cache/static_secret_cache_updater.go
index 9499569cff..3d79f9eff4 100644
--- a/command/agentproxyshared/cache/static_secret_cache_updater.go
+++ b/command/agentproxyshared/cache/static_secret_cache_updater.go
@@ -65,6 +65,12 @@ type StaticSecretCacheUpdater struct {
leaseCache *LeaseCache
logger hclog.Logger
tokenSink sink.Sink
+
+ // allowForwardingViaHeaderDisabled is a bool that tracks if
+ // allow_forwarding_via_header is disabled on the cluster we're talking to.
+ // If we get an error back saying that it's disabled, we'll set this to true
+ // and never try to forward again.
+ allowForwardingViaHeaderDisabled bool
}
// StaticSecretCacheUpdaterConfig is the configuration for initializing a new
@@ -163,6 +169,10 @@ func (updater *StaticSecretCacheUpdater) streamStaticSecretEvents(ctx context.Co
if !ok {
return fmt.Errorf("unexpected event format when decoding 'path' element, message: %s\nerror: %w", string(message), err)
}
+ namespace, ok := data["namespace"].(string)
+ if ok {
+ path = namespace + path
+ }
err := updater.updateStaticSecret(ctx, path)
if err != nil {
// While we are kind of 'missing' an event this way, re-calling this function will
@@ -218,6 +228,10 @@ func (updater *StaticSecretCacheUpdater) updateStaticSecret(ctx context.Context,
return err
}
+ // Clear the client's header namespace since we'll be including the
+ // namespace as part of the path.
+ client.ClearNamespace()
+
indexId := hashStaticSecretIndex(path)
updater.logger.Debug("received update static secret request", "path", path, "indexId", indexId)
@@ -246,9 +260,34 @@ func (updater *StaticSecretCacheUpdater) updateStaticSecret(ctx context.Context,
for _, token := range maps.Keys(index.Tokens) {
client.SetToken(token)
request.Headers.Set(api.AuthHeaderName, token)
+
+ if !updater.allowForwardingViaHeaderDisabled {
+ // Set this to always forward to active, since events could come before
+ // replication, and if we're connected to the standby, then we will be
+ // receiving events from the primary but otherwise getting old values from
+ // the standby here. This makes sure that Proxy functions properly
+ // even when its Vault address is set to a standby, since we cannot
+ // currently receive events from a standby.
+ // We only try this if updater.allowForwardingViaHeaderDisabled is false
+ // and if we receive an error indicating that the config is set to false,
+ // we will never set this header again.
+ request.Headers.Set(api.HeaderForward, "active-node")
+ }
+
resp, err = client.RawRequestWithContext(ctx, request)
if err != nil {
- updater.logger.Trace("received error when trying to update cache", "path", path, "err", err, "token", token)
+ if strings.Contains(err.Error(), "forwarding via header X-Vault-Forward disabled") {
+ updater.logger.Info("allow_forwarding_via_header disabled, re-attempting update and no longer attempting to forward")
+ updater.allowForwardingViaHeaderDisabled = true
+
+ // Try again without the header
+ request.Headers.Del(api.HeaderForward)
+ resp, err = client.RawRequestWithContext(ctx, request)
+ }
+ }
+
+ if err != nil {
+ updater.logger.Trace("received error when trying to update cache", "path", path, "err", err, "token", token, "namespace", index.Namespace)
// We cannot access this secret with this token for whatever reason,
// so token for removal.
tokensToRemove = append(tokensToRemove, token)
@@ -329,6 +368,7 @@ func (updater *StaticSecretCacheUpdater) openWebSocketConnection(ctx context.Con
}
query := webSocketURL.Query()
query.Set("json", "true")
+ query.Set("namespaces", "*")
webSocketURL.RawQuery = query.Encode()
updater.client.AddHeader(api.AuthHeaderName, updater.client.Token())
diff --git a/command/agentproxyshared/cache/static_secret_cache_updater_test.go b/command/agentproxyshared/cache/static_secret_cache_updater_test.go
index 51c53b2fc3..91158d954c 100644
--- a/command/agentproxyshared/cache/static_secret_cache_updater_test.go
+++ b/command/agentproxyshared/cache/static_secret_cache_updater_test.go
@@ -407,7 +407,7 @@ func TestOpenWebSocketConnectionReceivesEventsKVV1(t *testing.T) {
}
}
-// TestOpenWebSocketConnectionReceivesEvents tests that the openWebSocketConnection function
+// TestOpenWebSocketConnectionReceivesEventsKVV2 tests that the openWebSocketConnection function
// works as expected with KVV2, and then the connection can be used to receive an event.
// This acts as more of an event system sanity check than a test of the updater
// logic. It's still important coverage, though.
diff --git a/command/agentproxyshared/sink/file/file_sink.go b/command/agentproxyshared/sink/file/file_sink.go
index bf26a86b3c..6e1b71aa2e 100644
--- a/command/agentproxyshared/sink/file/file_sink.go
+++ b/command/agentproxyshared/sink/file/file_sink.go
@@ -19,6 +19,8 @@ import (
type fileSink struct {
path string
mode os.FileMode
+ owner int
+ group int
logger hclog.Logger
}
@@ -33,6 +35,8 @@ func NewFileSink(conf *sink.SinkConfig) (sink.Sink, error) {
f := &fileSink{
logger: conf.Logger,
mode: 0o640,
+ owner: os.Getuid(),
+ group: os.Getgid(),
}
pathRaw, ok := conf.Config["path"]
@@ -61,11 +65,31 @@ func NewFileSink(conf *sink.SinkConfig) (sink.Sink, error) {
f.mode = os.FileMode(mode)
}
+ if modeRaw, ok := conf.Config["owner"]; ok {
+ owner, typeOK := modeRaw.(int)
+ if !typeOK {
+ return nil, errors.New("could not parse 'owner' as integer")
+ }
+
+ f.logger.Debug("overriding default file sink", "owner", owner)
+ f.owner = owner
+ }
+
+ if modeRaw, ok := conf.Config["group"]; ok {
+ group, typeOK := modeRaw.(int)
+ if !typeOK {
+ return nil, errors.New("could not parse 'group' as integer")
+ }
+
+ f.logger.Debug("overriding default file sink", "group", group)
+ f.group = group
+ }
+
if err := f.WriteToken(""); err != nil {
return nil, fmt.Errorf("error during write check: %w", err)
}
- f.logger.Info("file sink configured", "path", f.path, "mode", f.mode)
+ f.logger.Info("file sink configured", "path", f.path, "mode", f.mode, "owner", f.owner, "group", f.group)
return f, nil
}
@@ -93,6 +117,10 @@ func (f *fileSink) WriteToken(token string) error {
return fmt.Errorf("error opening temp file in dir %s for writing: %w", targetDir, err)
}
+ if err := tmpFile.Chown(f.owner, f.group); err != nil {
+ return fmt.Errorf("error changing ownership of %s: %w", tmpFile.Name(), err)
+ }
+
valToWrite := token
if token == "" {
valToWrite = u
diff --git a/command/agentproxyshared/sink/file/file_sink_test.go b/command/agentproxyshared/sink/file/file_sink_test.go
index e603c6a32d..de7840748d 100644
--- a/command/agentproxyshared/sink/file/file_sink_test.go
+++ b/command/agentproxyshared/sink/file/file_sink_test.go
@@ -4,10 +4,9 @@
package file
import (
- "fmt"
- "io/ioutil"
"os"
"path/filepath"
+ "syscall"
"testing"
hclog "github.com/hashicorp/go-hclog"
@@ -16,15 +15,8 @@ import (
"github.com/hashicorp/vault/sdk/helper/logging"
)
-const (
- fileServerTestDir = "vault-agent-file-test"
-)
-
func testFileSink(t *testing.T, log hclog.Logger) (*sink.SinkConfig, string) {
- tmpDir, err := ioutil.TempDir("", fmt.Sprintf("%s.", fileServerTestDir))
- if err != nil {
- t.Fatal(err)
- }
+ tmpDir := t.TempDir()
path := filepath.Join(tmpDir, "token")
@@ -74,7 +66,7 @@ func TestFileSink(t *testing.T) {
t.Fatal(err)
}
- fileBytes, err := ioutil.ReadFile(path)
+ fileBytes, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
@@ -84,19 +76,17 @@ func TestFileSink(t *testing.T) {
}
}
-func testFileSinkMode(t *testing.T, log hclog.Logger) (*sink.SinkConfig, string) {
- tmpDir, err := ioutil.TempDir("", fmt.Sprintf("%s.", fileServerTestDir))
- if err != nil {
- t.Fatal(err)
- }
+func testFileSinkMode(t *testing.T, log hclog.Logger, gid int) (*sink.SinkConfig, string) {
+ tmpDir := t.TempDir()
path := filepath.Join(tmpDir, "token")
config := &sink.SinkConfig{
Logger: log.Named("sink.file"),
Config: map[string]interface{}{
- "path": path,
- "mode": 0o644,
+ "path": path,
+ "mode": 0o644,
+ "group": gid,
},
}
@@ -112,7 +102,7 @@ func testFileSinkMode(t *testing.T, log hclog.Logger) (*sink.SinkConfig, string)
func TestFileSinkMode(t *testing.T) {
log := logging.NewVaultLogger(hclog.Trace)
- fs, tmpDir := testFileSinkMode(t, log)
+ fs, tmpDir := testFileSinkMode(t, log, os.Getegid())
defer os.RemoveAll(tmpDir)
path := filepath.Join(tmpDir, "token")
@@ -136,7 +126,69 @@ func TestFileSinkMode(t *testing.T) {
t.Fatalf("wrong file mode was detected at %s", path)
}
- fileBytes, err := ioutil.ReadFile(path)
+ fileBytes, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if string(fileBytes) != uuidStr {
+ t.Fatalf("expected %s, got %s", uuidStr, string(fileBytes))
+ }
+}
+
+// TestFileSinkMode_Ownership tests that the file is owned by the group specified
+// in the configuration. This test requires the current user to be in at least two
+// groups. If the user is not in two groups, the test will be skipped.
+func TestFileSinkMode_Ownership(t *testing.T) {
+ groups, err := os.Getgroups()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(groups) < 2 {
+ t.Skip("not enough groups to test file ownership")
+ }
+
+ // find a group that is not the current group
+ var gid int
+ for _, g := range groups {
+ if g != os.Getegid() {
+ gid = g
+ break
+ }
+ }
+
+ log := logging.NewVaultLogger(hclog.Trace)
+
+ fs, tmpDir := testFileSinkMode(t, log, gid)
+ defer os.RemoveAll(tmpDir)
+
+ path := filepath.Join(tmpDir, "token")
+
+ uuidStr, _ := uuid.GenerateUUID()
+ if err := fs.WriteToken(uuidStr); err != nil {
+ t.Fatal(err)
+ }
+
+ file, err := os.Open(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer file.Close()
+
+ fi, err := file.Stat()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if fi.Mode() != os.FileMode(0o644) {
+ t.Fatalf("wrong file mode was detected at %s", path)
+ }
+ // check if file is owned by the group
+ if fi.Sys().(*syscall.Stat_t).Gid != uint32(gid) {
+ t.Fatalf("file is not owned by the group %d", gid)
+ }
+
+ fileBytes, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
diff --git a/command/base.go b/command/base.go
index 1c16618414..47f7be04a8 100644
--- a/command/base.go
+++ b/command/base.go
@@ -8,7 +8,6 @@ import (
"flag"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"regexp"
@@ -212,7 +211,7 @@ func (c *BaseCommand) Client() (*api.Client, error) {
}
if c.addrWarning != "" && c.UI != nil {
- if os.Getenv("VAULT_ADDR") == "" {
+ if os.Getenv("VAULT_ADDR") == "" && !c.flags.hadAddressFlag {
if !c.flagNonInteractive && isatty.IsTerminal(os.Stdin.Fd()) {
c.UI.Warn(wrapAtLength(c.addrWarning))
}
@@ -627,6 +626,10 @@ type FlagSets struct {
hiddens map[string]struct{}
completions complete.Flags
ui cli.Ui
+ // hadAddressFlag signals if the FlagSet had an -address
+ // flag set, for the purposes of warning (see also:
+ // BaseCommand::addrWarning).
+ hadAddressFlag bool
}
// NewFlagSets creates a new flag sets.
@@ -635,7 +638,7 @@ func NewFlagSets(ui cli.Ui) *FlagSets {
// Errors and usage are controlled by the CLI.
mainSet.Usage = func() {}
- mainSet.SetOutput(ioutil.Discard)
+ mainSet.SetOutput(io.Discard)
return &FlagSets{
flagSets: make([]*FlagSet, 0, 6),
@@ -669,6 +672,15 @@ type (
// Parse parses the given flags, returning any errors.
// Warnings, if any, regarding the arguments format are sent to stdout
func (f *FlagSets) Parse(args []string, opts ...ParseOptions) error {
+ // Before parsing, check to see if we have an address flag, for the
+ // purposes of warning later. This must be done now, as the argument
+ // will be removed during parsing.
+ for _, arg := range args {
+ if strings.HasPrefix(arg, "-address") {
+ f.hadAddressFlag = true
+ }
+ }
+
err := f.mainSet.Parse(args)
displayFlagWarningsDisabled := false
diff --git a/command/base_predict_test.go b/command/base_predict_test.go
index 4c17651ecd..387b8f0b84 100644
--- a/command/base_predict_test.go
+++ b/command/base_predict_test.go
@@ -351,7 +351,6 @@ func TestPredict_Plugins(t *testing.T) {
"aws",
"azure",
"cassandra-database-plugin",
- "centrify",
"cert",
"cf",
"consul",
diff --git a/command/command_stubs_oss.go b/command/command_stubs_oss.go
index bb199f373c..6e55082f30 100644
--- a/command/command_stubs_oss.go
+++ b/command/command_stubs_oss.go
@@ -16,11 +16,6 @@ import (
func entInitCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions, commands map[string]cli.CommandFactory) {
}
-func entEnableFourClusterDev(c *ServerCommand, base *vault.CoreConfig, info map[string]string, infoKeys []string, tempDir string) int {
- c.logger.Error("-dev-four-cluster only supported in enterprise Vault")
- return 1
-}
-
func entAdjustCoreConfig(config *server.Config, coreConfig *vault.CoreConfig) {
}
@@ -35,3 +30,5 @@ func entGetFIPSInfoKey() string {
func entGetRequestLimiterStatus(coreConfig vault.CoreConfig) string {
return ""
}
+
+func entExtendAddonHandlers(handlers *vaultHandlers) {}
diff --git a/command/command_test.go b/command/command_test.go
index d4fb934ab4..def68c4fbc 100644
--- a/command/command_test.go
+++ b/command/command_test.go
@@ -21,7 +21,6 @@ import (
"github.com/hashicorp/vault/builtin/logical/pki"
"github.com/hashicorp/vault/builtin/logical/ssh"
"github.com/hashicorp/vault/builtin/logical/transit"
- "github.com/hashicorp/vault/helper/benchhelpers"
"github.com/hashicorp/vault/helper/builtinplugins"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/sdk/logical"
@@ -122,10 +121,11 @@ func testVaultServerWithKVVersion(tb testing.TB, kvVersion string) (*api.Client,
func testVaultServerAllBackends(tb testing.TB) (*api.Client, func()) {
tb.Helper()
+ handlers := newVaultHandlers()
client, _, closer := testVaultServerCoreConfig(tb, &vault.CoreConfig{
- CredentialBackends: credentialBackends,
- AuditBackends: auditBackends,
- LogicalBackends: logicalBackends,
+ CredentialBackends: handlers.credentialBackends,
+ AuditBackends: handlers.auditBackends,
+ LogicalBackends: handlers.logicalBackends,
BuiltinRegistry: builtinplugins.Registry,
})
return client, closer
@@ -189,12 +189,12 @@ func testVaultServerCoreConfig(tb testing.TB, coreConfig *vault.CoreConfig) (*ap
func testVaultServerCoreConfigWithOpts(tb testing.TB, coreConfig *vault.CoreConfig, opts *vault.TestClusterOptions) (*api.Client, []string, func()) {
tb.Helper()
- cluster := vault.NewTestCluster(benchhelpers.TBtoT(tb), coreConfig, opts)
+ cluster := vault.NewTestCluster(tb, coreConfig, opts)
cluster.Start()
// Make it easy to get access to the active
core := cluster.Cores[0].Core
- vault.TestWaitActive(benchhelpers.TBtoT(tb), core)
+ vault.TestWaitActive(tb, core)
// Get the client already setup for us!
client := cluster.Cores[0].Client
diff --git a/command/commands.go b/command/commands.go
index af2e5dc42d..a4253dd192 100644
--- a/command/commands.go
+++ b/command/commands.go
@@ -10,49 +10,18 @@ import (
"github.com/hashicorp/cli"
hcpvlib "github.com/hashicorp/vault-hcp-lib"
- credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
- credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
- credCF "github.com/hashicorp/vault-plugin-auth-cf"
- credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
credOIDC "github.com/hashicorp/vault-plugin-auth-jwt"
- credKerb "github.com/hashicorp/vault-plugin-auth-kerberos"
- credOCI "github.com/hashicorp/vault-plugin-auth-oci"
logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
"github.com/hashicorp/vault/audit"
- credAws "github.com/hashicorp/vault/builtin/credential/aws"
credCert "github.com/hashicorp/vault/builtin/credential/cert"
- credGitHub "github.com/hashicorp/vault/builtin/credential/github"
- credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
- credOkta "github.com/hashicorp/vault/builtin/credential/okta"
credToken "github.com/hashicorp/vault/builtin/credential/token"
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
logicalDb "github.com/hashicorp/vault/builtin/logical/database"
"github.com/hashicorp/vault/builtin/plugin"
_ "github.com/hashicorp/vault/helper/builtinplugins"
- physAerospike "github.com/hashicorp/vault/physical/aerospike"
- physAliCloudOSS "github.com/hashicorp/vault/physical/alicloudoss"
- physAzure "github.com/hashicorp/vault/physical/azure"
- physCassandra "github.com/hashicorp/vault/physical/cassandra"
- physCockroachDB "github.com/hashicorp/vault/physical/cockroachdb"
- physConsul "github.com/hashicorp/vault/physical/consul"
- physCouchDB "github.com/hashicorp/vault/physical/couchdb"
- physDynamoDB "github.com/hashicorp/vault/physical/dynamodb"
- physEtcd "github.com/hashicorp/vault/physical/etcd"
- physFoundationDB "github.com/hashicorp/vault/physical/foundationdb"
- physGCS "github.com/hashicorp/vault/physical/gcs"
- physManta "github.com/hashicorp/vault/physical/manta"
- physMSSQL "github.com/hashicorp/vault/physical/mssql"
- physMySQL "github.com/hashicorp/vault/physical/mysql"
- physOCI "github.com/hashicorp/vault/physical/oci"
- physPostgreSQL "github.com/hashicorp/vault/physical/postgresql"
physRaft "github.com/hashicorp/vault/physical/raft"
- physS3 "github.com/hashicorp/vault/physical/s3"
- physSpanner "github.com/hashicorp/vault/physical/spanner"
- physSwift "github.com/hashicorp/vault/physical/swift"
- physZooKeeper "github.com/hashicorp/vault/physical/zookeeper"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/physical"
- physFile "github.com/hashicorp/vault/sdk/physical/file"
physInmem "github.com/hashicorp/vault/sdk/physical/inmem"
sr "github.com/hashicorp/vault/serviceregistration"
csr "github.com/hashicorp/vault/serviceregistration/consul"
@@ -160,86 +129,69 @@ const (
flagNameDelegatedAuthAccessors = "delegated-auth-accessors"
)
-var (
- auditBackends = map[string]audit.Factory{
- "file": audit.NewFileBackend,
- "socket": audit.NewSocketBackend,
- "syslog": audit.NewSyslogBackend,
- }
+// vaultHandlers contains the handlers for creating the various Vault backends.
+type vaultHandlers struct {
+ physicalBackends map[string]physical.Factory
+ loginHandlers map[string]LoginHandler
+ auditBackends map[string]audit.Factory
+ credentialBackends map[string]logical.Factory
+ logicalBackends map[string]logical.Factory
+ serviceRegistrations map[string]sr.Factory
+}
- credentialBackends = map[string]logical.Factory{
- "plugin": plugin.Factory,
- }
-
- logicalBackends = map[string]logical.Factory{
- "plugin": plugin.Factory,
- "database": logicalDb.Factory,
- // This is also available in the plugin catalog, but is here due to the need to
- // automatically mount it.
- "kv": logicalKv.Factory,
- }
-
- physicalBackends = map[string]physical.Factory{
- "aerospike": physAerospike.NewAerospikeBackend,
- "alicloudoss": physAliCloudOSS.NewAliCloudOSSBackend,
- "azure": physAzure.NewAzureBackend,
- "cassandra": physCassandra.NewCassandraBackend,
- "cockroachdb": physCockroachDB.NewCockroachDBBackend,
- "consul": physConsul.NewConsulBackend,
- "couchdb_transactional": physCouchDB.NewTransactionalCouchDBBackend,
- "couchdb": physCouchDB.NewCouchDBBackend,
- "dynamodb": physDynamoDB.NewDynamoDBBackend,
- "etcd": physEtcd.NewEtcdBackend,
- "file_transactional": physFile.NewTransactionalFileBackend,
- "file": physFile.NewFileBackend,
- "foundationdb": physFoundationDB.NewFDBBackend,
- "gcs": physGCS.NewBackend,
- "inmem_ha": physInmem.NewInmemHA,
- "inmem_transactional_ha": physInmem.NewTransactionalInmemHA,
- "inmem_transactional": physInmem.NewTransactionalInmem,
- "inmem": physInmem.NewInmem,
- "manta": physManta.NewMantaBackend,
- "mssql": physMSSQL.NewMSSQLBackend,
- "mysql": physMySQL.NewMySQLBackend,
- "oci": physOCI.NewBackend,
- "postgresql": physPostgreSQL.NewPostgreSQLBackend,
- "s3": physS3.NewS3Backend,
- "spanner": physSpanner.NewBackend,
- "swift": physSwift.NewSwiftBackend,
- "raft": physRaft.NewRaftBackend,
- "zookeeper": physZooKeeper.NewZooKeeperBackend,
- }
-
- serviceRegistrations = map[string]sr.Factory{
- "consul": csr.NewServiceRegistration,
- "kubernetes": ksr.NewServiceRegistration,
- }
-
- loginHandlers = map[string]LoginHandler{
- "alicloud": &credAliCloud.CLIHandler{},
- "aws": &credAws.CLIHandler{},
- "centrify": &credCentrify.CLIHandler{},
- "cert": &credCert.CLIHandler{},
- "cf": &credCF.CLIHandler{},
- "gcp": &credGcp.CLIHandler{},
- "github": &credGitHub.CLIHandler{},
- "kerberos": &credKerb.CLIHandler{},
- "ldap": &credLdap.CLIHandler{},
- "oci": &credOCI.CLIHandler{},
- "oidc": &credOIDC.CLIHandler{},
- "okta": &credOkta.CLIHandler{},
- "pcf": &credCF.CLIHandler{}, // Deprecated.
- "radius": &credUserpass.CLIHandler{
- DefaultMount: "radius",
+// newMinimalVaultHandlers returns a new vaultHandlers that a minimal Vault would use.
+func newMinimalVaultHandlers() *vaultHandlers {
+ return &vaultHandlers{
+ physicalBackends: map[string]physical.Factory{
+ "inmem_ha": physInmem.NewInmemHA,
+ "inmem_transactional_ha": physInmem.NewTransactionalInmemHA,
+ "inmem_transactional": physInmem.NewTransactionalInmem,
+ "inmem": physInmem.NewInmem,
+ "raft": physRaft.NewRaftBackend,
},
- "token": &credToken.CLIHandler{},
- "userpass": &credUserpass.CLIHandler{
- DefaultMount: "userpass",
+ loginHandlers: map[string]LoginHandler{
+ "cert": &credCert.CLIHandler{},
+ "oidc": &credOIDC.CLIHandler{},
+ "token": &credToken.CLIHandler{},
+ "userpass": &credUserpass.CLIHandler{
+ DefaultMount: "userpass",
+ },
+ },
+ auditBackends: map[string]audit.Factory{
+ "file": audit.NewFileBackend,
+ "socket": audit.NewSocketBackend,
+ "syslog": audit.NewSyslogBackend,
+ },
+ credentialBackends: map[string]logical.Factory{
+ "plugin": plugin.Factory,
+ },
+ logicalBackends: map[string]logical.Factory{
+ "plugin": plugin.Factory,
+ "database": logicalDb.Factory,
+ // This is also available in the plugin catalog, but is here due to the need to
+ // automatically mount it.
+ "kv": logicalKv.Factory,
+ },
+ serviceRegistrations: map[string]sr.Factory{
+ "consul": csr.NewServiceRegistration,
+ "kubernetes": ksr.NewServiceRegistration,
},
}
-)
+}
+
+// newVaultHandlers returns a new vaultHandlers composed of newMinimalVaultHandlers()
+// and any addon handlers from Vault CE and Vault Enterprise selected by Go build tags.
+func newVaultHandlers() *vaultHandlers {
+ handlers := newMinimalVaultHandlers()
+ extendAddonHandlers(handlers)
+ entExtendAddonHandlers(handlers)
+
+ return handlers
+}
func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.CommandFactory {
+ handlers := newVaultHandlers()
+
getBaseCommand := func() *BaseCommand {
return &BaseCommand{
UI: ui,
@@ -258,6 +210,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co
},
ShutdownCh: MakeShutdownCh(),
SighupCh: MakeSighupCh(),
+ SigUSR2Ch: MakeSigUSR2Ch(),
}, nil
},
"agent generate-config": func() (cli.Command, error) {
@@ -308,7 +261,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co
"auth help": func() (cli.Command, error) {
return &AuthHelpCommand{
BaseCommand: getBaseCommand(),
- Handlers: loginHandlers,
+ Handlers: handlers.loginHandlers,
}, nil
},
"auth list": func() (cli.Command, error) {
@@ -365,7 +318,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co
"login": func() (cli.Command, error) {
return &LoginCommand{
BaseCommand: getBaseCommand(),
- Handlers: loginHandlers,
+ Handlers: handlers.loginHandlers,
}, nil
},
"namespace": func() (cli.Command, error) {
@@ -436,7 +389,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co
"operator migrate": func() (cli.Command, error) {
return &OperatorMigrateCommand{
BaseCommand: getBaseCommand(),
- PhysicalBackends: physicalBackends,
+ PhysicalBackends: handlers.physicalBackends,
ShutdownCh: MakeShutdownCh(),
}, nil
},
@@ -642,6 +595,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co
},
ShutdownCh: MakeShutdownCh(),
SighupCh: MakeSighupCh(),
+ SigUSR2Ch: MakeSigUSR2Ch(),
}, nil
},
"policy": func() (cli.Command, error) {
@@ -726,12 +680,11 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co
tokenHelper: runOpts.TokenHelper,
flagAddress: runOpts.Address,
},
- AuditBackends: auditBackends,
- CredentialBackends: credentialBackends,
- LogicalBackends: logicalBackends,
- PhysicalBackends: physicalBackends,
-
- ServiceRegistrations: serviceRegistrations,
+ AuditBackends: handlers.auditBackends,
+ CredentialBackends: handlers.credentialBackends,
+ LogicalBackends: handlers.logicalBackends,
+ PhysicalBackends: handlers.physicalBackends,
+ ServiceRegistrations: handlers.serviceRegistrations,
ShutdownCh: MakeShutdownCh(),
SighupCh: MakeSighupCh(),
diff --git a/command/commands_full.go b/command/commands_full.go
new file mode 100644
index 0000000000..8db22350cf
--- /dev/null
+++ b/command/commands_full.go
@@ -0,0 +1,96 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build !minimal
+
+package command
+
+import (
+ "maps"
+
+ credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
+ credCF "github.com/hashicorp/vault-plugin-auth-cf"
+ credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
+ credKerb "github.com/hashicorp/vault-plugin-auth-kerberos"
+ credOCI "github.com/hashicorp/vault-plugin-auth-oci"
+ credAws "github.com/hashicorp/vault/builtin/credential/aws"
+ credGitHub "github.com/hashicorp/vault/builtin/credential/github"
+ credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
+ credOkta "github.com/hashicorp/vault/builtin/credential/okta"
+ credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
+ _ "github.com/hashicorp/vault/helper/builtinplugins"
+ physAerospike "github.com/hashicorp/vault/physical/aerospike"
+ physAliCloudOSS "github.com/hashicorp/vault/physical/alicloudoss"
+ physAzure "github.com/hashicorp/vault/physical/azure"
+ physCassandra "github.com/hashicorp/vault/physical/cassandra"
+ physCockroachDB "github.com/hashicorp/vault/physical/cockroachdb"
+ physConsul "github.com/hashicorp/vault/physical/consul"
+ physCouchDB "github.com/hashicorp/vault/physical/couchdb"
+ physDynamoDB "github.com/hashicorp/vault/physical/dynamodb"
+ physEtcd "github.com/hashicorp/vault/physical/etcd"
+ physFoundationDB "github.com/hashicorp/vault/physical/foundationdb"
+ physGCS "github.com/hashicorp/vault/physical/gcs"
+ physManta "github.com/hashicorp/vault/physical/manta"
+ physMSSQL "github.com/hashicorp/vault/physical/mssql"
+ physMySQL "github.com/hashicorp/vault/physical/mysql"
+ physOCI "github.com/hashicorp/vault/physical/oci"
+ physPostgreSQL "github.com/hashicorp/vault/physical/postgresql"
+ physS3 "github.com/hashicorp/vault/physical/s3"
+ physSpanner "github.com/hashicorp/vault/physical/spanner"
+ physSwift "github.com/hashicorp/vault/physical/swift"
+ physZooKeeper "github.com/hashicorp/vault/physical/zookeeper"
+ "github.com/hashicorp/vault/sdk/physical"
+ physFile "github.com/hashicorp/vault/sdk/physical/file"
+)
+
+func newFullAddonHandlers() (map[string]physical.Factory, map[string]LoginHandler) {
+ addonPhysicalBackends := map[string]physical.Factory{
+ "aerospike": physAerospike.NewAerospikeBackend,
+ "alicloudoss": physAliCloudOSS.NewAliCloudOSSBackend,
+ "azure": physAzure.NewAzureBackend,
+ "cassandra": physCassandra.NewCassandraBackend,
+ "cockroachdb": physCockroachDB.NewCockroachDBBackend,
+ "consul": physConsul.NewConsulBackend,
+ "couchdb_transactional": physCouchDB.NewTransactionalCouchDBBackend,
+ "couchdb": physCouchDB.NewCouchDBBackend,
+ "dynamodb": physDynamoDB.NewDynamoDBBackend,
+ "etcd": physEtcd.NewEtcdBackend,
+ "file_transactional": physFile.NewTransactionalFileBackend,
+ "file": physFile.NewFileBackend,
+ "foundationdb": physFoundationDB.NewFDBBackend,
+ "gcs": physGCS.NewBackend,
+ "manta": physManta.NewMantaBackend,
+ "mssql": physMSSQL.NewMSSQLBackend,
+ "mysql": physMySQL.NewMySQLBackend,
+ "oci": physOCI.NewBackend,
+ "postgresql": physPostgreSQL.NewPostgreSQLBackend,
+ "s3": physS3.NewS3Backend,
+ "spanner": physSpanner.NewBackend,
+ "swift": physSwift.NewSwiftBackend,
+ "zookeeper": physZooKeeper.NewZooKeeperBackend,
+ }
+ addonLoginHandlers := map[string]LoginHandler{
+ "alicloud": &credAliCloud.CLIHandler{},
+ "aws": &credAws.CLIHandler{},
+ "cf": &credCF.CLIHandler{},
+ "gcp": &credGcp.CLIHandler{},
+ "github": &credGitHub.CLIHandler{},
+ "kerberos": &credKerb.CLIHandler{},
+ "ldap": &credLdap.CLIHandler{},
+ "oci": &credOCI.CLIHandler{},
+ "okta": &credOkta.CLIHandler{},
+ "pcf": &credCF.CLIHandler{}, // Deprecated.
+ "radius": &credUserpass.CLIHandler{
+ DefaultMount: "radius",
+ },
+ }
+
+ return addonPhysicalBackends, addonLoginHandlers
+}
+
+func extendAddonHandlers(handlers *vaultHandlers) {
+ addonPhysicalBackends, addonLoginHandlers := newFullAddonHandlers()
+
+ maps.Copy(handlers.physicalBackends, addonPhysicalBackends)
+ maps.Copy(handlers.loginHandlers, addonLoginHandlers)
+}
diff --git a/command/commands_full_test.go b/command/commands_full_test.go
new file mode 100644
index 0000000000..e22c0fc5f1
--- /dev/null
+++ b/command/commands_full_test.go
@@ -0,0 +1,46 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build !enterprise && !minimal
+
+package command
+
+import (
+ "maps"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+// Test_extendAddonHandlers tests extendAddonHandlers() extends the minimal Vault handlers with handlers
+// generated by newFullAddonHandlers()
+func Test_extendAddonHandlers(t *testing.T) {
+ handlers := newMinimalVaultHandlers()
+ expMinPhysicalBackends := maps.Clone(handlers.physicalBackends)
+ expMinLoginHandlers := maps.Clone(handlers.loginHandlers)
+
+ expAddonPhysicalBackends, expAddonLoginHandlers := newFullAddonHandlers()
+
+ extendAddonHandlers(handlers)
+
+ require.Equal(t, len(expMinPhysicalBackends)+len(expAddonPhysicalBackends), len(handlers.physicalBackends),
+ "extended total physical backends mismatch total of minimal and full addon physical backends")
+ require.Equal(t, len(expMinLoginHandlers)+len(expAddonLoginHandlers), len(handlers.loginHandlers),
+ "extended total login handlers mismatch total of minimal and full addon login handlers")
+
+ for k := range expMinPhysicalBackends {
+ require.Contains(t, handlers.physicalBackends, k, "expected to contain minimal physical backend")
+ }
+
+ for k := range expAddonPhysicalBackends {
+ require.Contains(t, handlers.physicalBackends, k, "expected to contain full addon physical backend")
+ }
+
+ for k := range expMinLoginHandlers {
+ require.Contains(t, handlers.loginHandlers, k, "expected to contain minimal login handler")
+ }
+
+ for k := range expAddonLoginHandlers {
+ require.Contains(t, handlers.loginHandlers, k, "expected to contain full addon login handler")
+ }
+}
diff --git a/command/commands_min.go b/command/commands_min.go
new file mode 100644
index 0000000000..812c37a40c
--- /dev/null
+++ b/command/commands_min.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build minimal
+
+package command
+
+import (
+ _ "github.com/hashicorp/vault/helper/builtinplugins"
+)
+
+func extendAddonHandlers(*vaultHandlers) {
+ // No-op
+}
diff --git a/command/commands_test.go b/command/commands_test.go
index ac057f737c..681e627125 100644
--- a/command/commands_test.go
+++ b/command/commands_test.go
@@ -25,6 +25,9 @@ func Test_Commands_HCPInit(t *testing.T) {
}
for n, tst := range tests {
+ n := n
+ tst := tst
+
t.Run(n, func(t *testing.T) {
t.Parallel()
diff --git a/command/debug.go b/command/debug.go
index 8ad7466e5c..7355372b5e 100644
--- a/command/debug.go
+++ b/command/debug.go
@@ -4,10 +4,12 @@
package command
import (
+ "archive/tar"
+ "compress/gzip"
"context"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/url"
"os"
"path/filepath"
@@ -26,7 +28,6 @@ import (
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/version"
- "github.com/mholt/archiver/v3"
"github.com/oklog/run"
"github.com/posener/complete"
)
@@ -374,7 +375,7 @@ func (c *DebugCommand) generateIndex() error {
}
// Write out file
- if err := ioutil.WriteFile(filepath.Join(c.flagOutput, "index.json"), bytes, 0o600); err != nil {
+ if err := os.WriteFile(filepath.Join(c.flagOutput, "index.json"), bytes, 0o600); err != nil {
return fmt.Errorf("error generating index file; %s", err)
}
@@ -778,7 +779,7 @@ func (c *DebugCommand) collectPprof(ctx context.Context) {
return
}
- err = ioutil.WriteFile(filepath.Join(dirName, target+".prof"), data, 0o600)
+ err = os.WriteFile(filepath.Join(dirName, target+".prof"), data, 0o600)
if err != nil {
c.captureError("pprof."+target, err)
}
@@ -796,13 +797,13 @@ func (c *DebugCommand) collectPprof(ctx context.Context) {
return
}
- err = ioutil.WriteFile(filepath.Join(dirName, "goroutines.txt"), data, 0o600)
+ err = os.WriteFile(filepath.Join(dirName, "goroutines.txt"), data, 0o600)
if err != nil {
c.captureError("pprof.goroutines-text", err)
}
}()
- // If the our remaining duration is less than the interval value
+ // If our remaining duration is less than the interval value
// skip profile and trace.
runDuration := currentTimestamp.Sub(startTime)
if (c.flagDuration+debugDurationGrace)-runDuration < c.flagInterval {
@@ -820,7 +821,7 @@ func (c *DebugCommand) collectPprof(ctx context.Context) {
return
}
- err = ioutil.WriteFile(filepath.Join(dirName, "profile.prof"), data, 0o600)
+ err = os.WriteFile(filepath.Join(dirName, "profile.prof"), data, 0o600)
if err != nil {
c.captureError("pprof.profile", err)
}
@@ -836,7 +837,7 @@ func (c *DebugCommand) collectPprof(ctx context.Context) {
return
}
- err = ioutil.WriteFile(filepath.Join(dirName, "trace.out"), data, 0o600)
+ err = os.WriteFile(filepath.Join(dirName, "trace.out"), data, 0o600)
if err != nil {
c.captureError("pprof.trace", err)
}
@@ -972,7 +973,7 @@ func (c *DebugCommand) persistCollection(collection []map[string]interface{}, ou
if err != nil {
return err
}
- if err := ioutil.WriteFile(filepath.Join(c.flagOutput, outFile), bytes, 0o600); err != nil {
+ if err := os.WriteFile(filepath.Join(c.flagOutput, outFile), bytes, 0o600); err != nil {
return err
}
@@ -984,14 +985,100 @@ func (c *DebugCommand) compress(dst string) error {
defer osutil.Umask(osutil.Umask(0o077))
}
- tgz := archiver.NewTarGz()
- if err := tgz.Archive([]string{c.flagOutput}, dst); err != nil {
- return fmt.Errorf("failed to compress data: %s", err)
+ if err := archiveToTgz(c.flagOutput, dst); err != nil {
+ return fmt.Errorf("failed to compress data: %w", err)
}
// If everything is fine up to this point, remove original directory
if err := os.RemoveAll(c.flagOutput); err != nil {
- return fmt.Errorf("failed to remove data directory: %s", err)
+ return fmt.Errorf("failed to remove data directory: %w", err)
+ }
+
+ return nil
+}
+
+// archiveToTgz compresses all the files in sourceDir to a
+// a tarball at destination.
+func archiveToTgz(sourceDir, destination string) error {
+ file, err := os.Create(destination)
+ if err != nil {
+ return fmt.Errorf("failed to create file: %w", err)
+ }
+ defer file.Close()
+
+ gzipWriter := gzip.NewWriter(file)
+ defer gzipWriter.Close()
+
+ tarWriter := tar.NewWriter(gzipWriter)
+ defer tarWriter.Close()
+
+ err = filepath.Walk(sourceDir,
+ func(filePath string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ return addFileToTar(sourceDir, filePath, tarWriter)
+ })
+
+ return err
+}
+
+// addFileToTar takes a file at filePath and adds it to the tar
+// being written to by tarWriter, alongside its header.
+// The tar header name will be relative. Example: If we're tarring
+// a file in ~/a/b/c/foo/bar.json, the header name will be foo/bar.json
+func addFileToTar(sourceDir, filePath string, tarWriter *tar.Writer) error {
+ file, err := os.Open(filePath)
+ if err != nil {
+ return fmt.Errorf("failed to open file %q: %w", filePath, err)
+ }
+ defer file.Close()
+
+ stat, err := file.Stat()
+ if err != nil {
+ return fmt.Errorf("failed to stat file %q: %w", filePath, err)
+ }
+
+ var link string
+ mode := stat.Mode()
+ if mode&os.ModeSymlink != 0 {
+ if link, err = os.Readlink(filePath); err != nil {
+ return fmt.Errorf("failed to read symlink for file %q: %w", filePath, err)
+ }
+ }
+ tarHeader, err := tar.FileInfoHeader(stat, link)
+ if err != nil {
+ return fmt.Errorf("failed to create tar header for file %q: %w", filePath, err)
+ }
+
+ // The tar header name should be relative, so remove the sourceDir from it,
+ // but preserve the last directory name.
+ // Example: If we're tarring a file in ~/a/b/c/foo/bar.json
+ // The name should be foo/bar.json
+ sourceDirExceptLastDir := filepath.Dir(sourceDir)
+ headerName := strings.TrimPrefix(filepath.Clean(filePath), filepath.Clean(sourceDirExceptLastDir)+"/")
+
+ // Directories should end with a slash.
+ if stat.IsDir() && !strings.HasSuffix(headerName, "/") {
+ headerName += "/"
+ }
+ tarHeader.Name = headerName
+
+ err = tarWriter.WriteHeader(tarHeader)
+ if err != nil {
+ return fmt.Errorf("failed to write tar header for file %q: %w", filePath, err)
+ }
+
+ // If it's not a regular file (e.g. link or directory) we shouldn't
+ // copy the file. The body of a tar entry (i.e. what's done by the
+ // below io.Copy call) is only required for tar files of TypeReg.
+ if tarHeader.Typeflag != tar.TypeReg {
+ return nil
+ }
+
+ _, err = io.Copy(tarWriter, file)
+ if err != nil {
+ return fmt.Errorf("failed to copy file %q into tarball: %w", filePath, err)
}
return nil
@@ -1008,7 +1095,7 @@ func pprofTarget(ctx context.Context, client *api.Client, target string, params
}
defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
+ data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -1028,7 +1115,7 @@ func pprofProfile(ctx context.Context, client *api.Client, duration time.Duratio
}
defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
+ data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -1048,7 +1135,7 @@ func pprofTrace(ctx context.Context, client *api.Client, duration time.Duration)
}
defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
+ data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
diff --git a/command/debug_test.go b/command/debug_test.go
index 279c48f0a5..16d297bf92 100644
--- a/command/debug_test.go
+++ b/command/debug_test.go
@@ -5,9 +5,10 @@ package command
import (
"archive/tar"
+ "compress/gzip"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"os"
"path/filepath"
"runtime"
@@ -18,7 +19,7 @@ import (
"github.com/hashicorp/cli"
"github.com/hashicorp/vault/api"
- "github.com/mholt/archiver/v3"
+ "github.com/stretchr/testify/require"
)
func testDebugCommand(tb testing.TB) (*cli.MockUi, *DebugCommand) {
@@ -35,11 +36,7 @@ func testDebugCommand(tb testing.TB) (*cli.MockUi, *DebugCommand) {
func TestDebugCommand_Run(t *testing.T) {
t.Parallel()
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
cases := []struct {
name string
@@ -104,6 +101,54 @@ func TestDebugCommand_Run(t *testing.T) {
}
}
+// expectHeaderNamesInTarGzFile asserts that the expectedHeaderNames
+// match exactly to the header names in the tar.gz file at tarballPath.
+// Will error if there are more or less than expected.
+// ignoreUnexpectedHeaders toggles ignoring the presence of headers not
+// in expectedHeaderNames.
+func expectHeaderNamesInTarGzFile(t *testing.T, tarballPath string, expectedHeaderNames []string, ignoreUnexpectedHeaders bool) {
+ t.Helper()
+
+ file, err := os.Open(tarballPath)
+ require.NoError(t, err)
+
+ uncompressedStream, err := gzip.NewReader(file)
+ require.NoError(t, err)
+
+ tarReader := tar.NewReader(uncompressedStream)
+ headersFoundMap := make(map[string]any)
+
+ for {
+ header, err := tarReader.Next()
+ if err == io.EOF {
+ // We're at the end of the tar.
+ break
+ }
+ require.NoError(t, err)
+
+ // Ignore directories.
+ if header.Typeflag == tar.TypeDir {
+ continue
+ }
+
+ for _, name := range expectedHeaderNames {
+ if header.Name == name {
+ headersFoundMap[header.Name] = struct{}{}
+ }
+ }
+ if _, ok := headersFoundMap[header.Name]; !ok && !ignoreUnexpectedHeaders {
+ t.Fatalf("unexpected file: %s", header.Name)
+ }
+ }
+
+ // Expect that every expectedHeader was found at some point
+ for _, name := range expectedHeaderNames {
+ if _, ok := headersFoundMap[name]; !ok {
+ t.Fatalf("missing header from tar: %s", name)
+ }
+ }
+}
+
func TestDebugCommand_Archive(t *testing.T) {
t.Parallel()
@@ -137,11 +182,7 @@ func TestDebugCommand_Archive(t *testing.T) {
// Create temp dirs for each test case since os.Stat and tgz.Walk
// (called down below) exhibits raciness otherwise.
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
client, closer := testVaultServer(t)
defer closer()
@@ -177,32 +218,14 @@ func TestDebugCommand_Archive(t *testing.T) {
}
bundlePath := filepath.Join(testDir, basePath+expectedExt)
- _, err = os.Stat(bundlePath)
+ _, err := os.Stat(bundlePath)
if os.IsNotExist(err) {
t.Log(ui.OutputWriter.String())
t.Fatal(err)
}
- tgz := archiver.NewTarGz()
- err = tgz.Walk(bundlePath, func(f archiver.File) error {
- fh, ok := f.Header.(*tar.Header)
- if !ok {
- return fmt.Errorf("invalid file header: %#v", f.Header)
- }
-
- // Ignore base directory and index file
- if fh.Name == basePath+"/" || fh.Name == filepath.Join(basePath, "index.json") {
- return nil
- }
-
- if fh.Name != filepath.Join(basePath, "server_status.json") {
- return fmt.Errorf("unexpected file: %s", fh.Name)
- }
- return nil
- })
- if err != nil {
- t.Fatal(err)
- }
+ expectedHeaders := []string{filepath.Join(basePath, "index.json"), filepath.Join(basePath, "server_status.json")}
+ expectHeaderNamesInTarGzFile(t, bundlePath, expectedHeaders, false)
})
}
}
@@ -258,11 +281,7 @@ func TestDebugCommand_CaptureTargets(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
client, closer := testVaultServer(t)
defer closer()
@@ -287,45 +306,22 @@ func TestDebugCommand_CaptureTargets(t *testing.T) {
}
bundlePath := filepath.Join(testDir, basePath+debugCompressionExt)
- _, err = os.Open(bundlePath)
+ _, err := os.Open(bundlePath)
if err != nil {
t.Fatalf("failed to open archive: %s", err)
}
- tgz := archiver.NewTarGz()
- err = tgz.Walk(bundlePath, func(f archiver.File) error {
- fh, ok := f.Header.(*tar.Header)
- if !ok {
- t.Fatalf("invalid file header: %#v", f.Header)
- }
-
- // Ignore base directory and index file
- if fh.Name == basePath+"/" || fh.Name == filepath.Join(basePath, "index.json") {
- return nil
- }
-
- for _, fileName := range tc.expectedFiles {
- if fh.Name == filepath.Join(basePath, fileName) {
- return nil
- }
- }
-
- // If we reach here, it means that this is an unexpected file
- return fmt.Errorf("unexpected file: %s", fh.Name)
- })
- if err != nil {
- t.Fatal(err)
+ expectedHeaders := []string{filepath.Join(basePath, "index.json")}
+ for _, fileName := range tc.expectedFiles {
+ expectedHeaders = append(expectedHeaders, filepath.Join(basePath, fileName))
}
+ expectHeaderNamesInTarGzFile(t, bundlePath, expectedHeaders, false)
})
}
}
func TestDebugCommand_Pprof(t *testing.T) {
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
client, closer := testVaultServer(t)
defer closer()
@@ -379,11 +375,7 @@ func TestDebugCommand_Pprof(t *testing.T) {
func TestDebugCommand_IndexFile(t *testing.T) {
t.Parallel()
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
client, closer := testVaultServer(t)
defer closer()
@@ -409,7 +401,7 @@ func TestDebugCommand_IndexFile(t *testing.T) {
t.Fatalf("expected %d to be %d", code, exp)
}
- content, err := ioutil.ReadFile(filepath.Join(outputPath, "index.json"))
+ content, err := os.ReadFile(filepath.Join(outputPath, "index.json"))
if err != nil {
t.Fatal(err)
}
@@ -426,11 +418,7 @@ func TestDebugCommand_IndexFile(t *testing.T) {
func TestDebugCommand_TimingChecks(t *testing.T) {
t.Parallel()
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
cases := []struct {
name string
@@ -585,11 +573,7 @@ func TestDebugCommand_OutputExists(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
client, closer := testVaultServer(t)
defer closer()
@@ -602,12 +586,12 @@ func TestDebugCommand_OutputExists(t *testing.T) {
// Create a conflicting file/directory
if tc.compress {
- _, err = os.Create(outputPath)
+ _, err := os.Create(outputPath)
if err != nil {
t.Fatal(err)
}
} else {
- err = os.Mkdir(outputPath, 0o700)
+ err := os.Mkdir(outputPath, 0o700)
if err != nil {
t.Fatal(err)
}
@@ -639,11 +623,7 @@ func TestDebugCommand_OutputExists(t *testing.T) {
func TestDebugCommand_PartialPermissions(t *testing.T) {
t.Parallel()
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
client, closer := testVaultServer(t)
defer closer()
@@ -680,38 +660,14 @@ func TestDebugCommand_PartialPermissions(t *testing.T) {
t.Fatalf("failed to open archive: %s", err)
}
- tgz := archiver.NewTarGz()
- err = tgz.Walk(bundlePath, func(f archiver.File) error {
- fh, ok := f.Header.(*tar.Header)
- if !ok {
- t.Fatalf("invalid file header: %#v", f.Header)
- }
-
- // Ignore base directory and index file
- if fh.Name == basePath+"/" {
- return nil
- }
-
- // Ignore directories, which still get created by pprof but should
- // otherwise be empty.
- if fh.FileInfo().IsDir() {
- return nil
- }
-
- switch {
- case fh.Name == filepath.Join(basePath, "index.json"):
- case fh.Name == filepath.Join(basePath, "replication_status.json"):
- case fh.Name == filepath.Join(basePath, "server_status.json"):
- case fh.Name == filepath.Join(basePath, "vault.log"):
- default:
- return fmt.Errorf("unexpected file: %s", fh.Name)
- }
-
- return nil
- })
- if err != nil {
- t.Fatal(err)
+ expectedHeaders := []string{
+ filepath.Join(basePath, "index.json"), filepath.Join(basePath, "server_status.json"),
+ filepath.Join(basePath, "vault.log"),
}
+
+ // We set ignoreUnexpectedHeaders to true as replication_status.json is only sometimes
+ // produced. Relying on it being or not being there would be racy.
+ expectHeaderNamesInTarGzFile(t, bundlePath, expectedHeaders, true)
}
// set insecure umask to see if the files and directories get created with right permissions
@@ -748,11 +704,7 @@ func TestDebugCommand_InsecureUmask(t *testing.T) {
// set insecure umask
defer syscall.Umask(syscall.Umask(0))
- testDir, err := ioutil.TempDir("", "vault-debug")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testDir)
+ testDir := t.TempDir()
client, closer := testVaultServer(t)
defer closer()
@@ -796,20 +748,22 @@ func TestDebugCommand_InsecureUmask(t *testing.T) {
// check permissions of the files within the parent directory
switch tc.compress {
case true:
- tgz := archiver.NewTarGz()
+ file, err := os.Open(bundlePath)
+ require.NoError(t, err)
- err = tgz.Walk(bundlePath, func(f archiver.File) error {
- fh, ok := f.Header.(*tar.Header)
- if !ok {
- return fmt.Errorf("invalid file header: %#v", f.Header)
- }
- err = isValidFilePermissions(fh.FileInfo())
- if err != nil {
- t.Fatalf(err.Error())
- }
- return nil
- })
+ uncompressedStream, err := gzip.NewReader(file)
+ require.NoError(t, err)
+ tarReader := tar.NewReader(uncompressedStream)
+
+ for {
+ header, err := tarReader.Next()
+ if err == io.EOF {
+ break
+ }
+ err = isValidFilePermissions(header.FileInfo())
+ require.NoError(t, err)
+ }
case false:
err = filepath.Walk(bundlePath, func(path string, info os.FileInfo, err error) error {
err = isValidFilePermissions(info)
@@ -820,9 +774,7 @@ func TestDebugCommand_InsecureUmask(t *testing.T) {
})
}
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
})
}
}
diff --git a/command/operator_diagnose.go b/command/operator_diagnose.go
index 47b6183cc5..b530ada5f0 100644
--- a/command/operator_diagnose.go
+++ b/command/operator_diagnose.go
@@ -203,17 +203,19 @@ func (c *OperatorDiagnoseCommand) RunWithParsedFlags() int {
func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error {
rloadFuncs := make(map[string][]reloadutil.ReloadFunc)
+ handlers := newVaultHandlers()
+
server := &ServerCommand{
// TODO: set up a different one?
// In particular, a UI instance that won't output?
BaseCommand: c.BaseCommand,
// TODO: refactor to a common place?
- AuditBackends: auditBackends,
- CredentialBackends: credentialBackends,
- LogicalBackends: logicalBackends,
- PhysicalBackends: physicalBackends,
- ServiceRegistrations: serviceRegistrations,
+ AuditBackends: handlers.auditBackends,
+ CredentialBackends: handlers.credentialBackends,
+ LogicalBackends: handlers.logicalBackends,
+ PhysicalBackends: handlers.physicalBackends,
+ ServiceRegistrations: handlers.serviceRegistrations,
// TODO: other ServerCommand options?
diff --git a/command/operator_migrate_test.go b/command/operator_migrate_test.go
index 9a6c27196e..15190b2640 100644
--- a/command/operator_migrate_test.go
+++ b/command/operator_migrate_test.go
@@ -32,10 +32,11 @@ func init() {
}
func TestMigration(t *testing.T) {
+ handlers := newVaultHandlers()
t.Run("Default", func(t *testing.T) {
data := generateData()
- fromFactory := physicalBackends["file"]
+ fromFactory := handlers.physicalBackends["file"]
folder := t.TempDir()
@@ -51,7 +52,7 @@ func TestMigration(t *testing.T) {
t.Fatal(err)
}
- toFactory := physicalBackends["inmem"]
+ toFactory := handlers.physicalBackends["inmem"]
confTo := map[string]string{}
to, err := toFactory(confTo, nil)
if err != nil {
@@ -72,7 +73,7 @@ func TestMigration(t *testing.T) {
t.Run("Concurrent migration", func(t *testing.T) {
data := generateData()
- fromFactory := physicalBackends["file"]
+ fromFactory := handlers.physicalBackends["file"]
folder := t.TempDir()
@@ -88,7 +89,7 @@ func TestMigration(t *testing.T) {
t.Fatal(err)
}
- toFactory := physicalBackends["inmem"]
+ toFactory := handlers.physicalBackends["inmem"]
confTo := map[string]string{}
to, err := toFactory(confTo, nil)
if err != nil {
@@ -110,7 +111,7 @@ func TestMigration(t *testing.T) {
t.Run("Start option", func(t *testing.T) {
data := generateData()
- fromFactory := physicalBackends["inmem"]
+ fromFactory := handlers.physicalBackends["inmem"]
confFrom := map[string]string{}
from, err := fromFactory(confFrom, nil)
if err != nil {
@@ -120,7 +121,7 @@ func TestMigration(t *testing.T) {
t.Fatal(err)
}
- toFactory := physicalBackends["file"]
+ toFactory := handlers.physicalBackends["file"]
folder := t.TempDir()
confTo := map[string]string{
"path": folder,
@@ -149,7 +150,7 @@ func TestMigration(t *testing.T) {
t.Run("Start option (parallel)", func(t *testing.T) {
data := generateData()
- fromFactory := physicalBackends["inmem"]
+ fromFactory := handlers.physicalBackends["inmem"]
confFrom := map[string]string{}
from, err := fromFactory(confFrom, nil)
if err != nil {
@@ -159,7 +160,7 @@ func TestMigration(t *testing.T) {
t.Fatal(err)
}
- toFactory := physicalBackends["file"]
+ toFactory := handlers.physicalBackends["file"]
folder := t.TempDir()
confTo := map[string]string{
"path": folder,
@@ -269,7 +270,7 @@ storage_destination "dest_type2" {
})
t.Run("DFS Scan", func(t *testing.T) {
- s, _ := physicalBackends["inmem"](map[string]string{}, nil)
+ s, _ := handlers.physicalBackends["inmem"](map[string]string{}, nil)
data := generateData()
data["cc"] = []byte{}
diff --git a/command/operator_usage.go b/command/operator_usage.go
index 079ddaba8f..e96b0ca33d 100644
--- a/command/operator_usage.go
+++ b/command/operator_usage.go
@@ -56,7 +56,7 @@ func (c *OperatorUsageCommand) Flags() *FlagSets {
f.TimeVar(&TimeVar{
Name: "start-time",
- Usage: "Start of report period. Defaults to 'default_reporting_period' before end time.",
+ Usage: "Start of report period. Defaults to billing start time",
Target: &c.flagStartTime,
Completion: complete.PredictNothing,
Default: time.Time{},
@@ -64,7 +64,7 @@ func (c *OperatorUsageCommand) Flags() *FlagSets {
})
f.TimeVar(&TimeVar{
Name: "end-time",
- Usage: "End of report period. Defaults to end of last month.",
+ Usage: "End of report period. Defaults to end of the current month.",
Target: &c.flagEndTime,
Completion: complete.PredictNothing,
Default: time.Time{},
@@ -132,7 +132,7 @@ func (c *OperatorUsageCommand) Run(args []string) int {
c.outputTimestamps(resp.Data)
out := []string{
- "Namespace path | Distinct entities | Non-Entity tokens | Secret syncs | ACME clients | Active clients",
+ "Namespace path | Entity Clients | Non-Entity clients | Secret syncs | ACME clients | Active clients",
}
out = append(out, c.namespacesOutput(resp.Data)...)
@@ -142,6 +142,12 @@ func (c *OperatorUsageCommand) Run(args []string) int {
colConfig.Empty = " " // Do not show n/a on intentional blank lines
colConfig.Glue = " "
c.UI.Output(tableOutput(out, colConfig))
+
+ // Also, output the warnings returned, if any:
+ for _, warning := range resp.Warnings {
+ c.UI.Warn(warning)
+ }
+
return 0
}
@@ -233,14 +239,14 @@ func (c *OperatorUsageCommand) parseNamespaceCount(rawVal interface{}) (UsageRes
return ret, errors.New("missing counts")
}
- ret.entityCount, ok = jsonNumberOK(counts, "distinct_entities")
+ ret.entityCount, ok = jsonNumberOK(counts, "entity_clients")
if !ok {
- return ret, errors.New("missing distinct_entities")
+ return ret, errors.New("missing entity_clients")
}
- ret.tokenCount, ok = jsonNumberOK(counts, "non_entity_tokens")
+ ret.tokenCount, ok = jsonNumberOK(counts, "non_entity_clients")
if !ok {
- return ret, errors.New("missing non_entity_tokens")
+ return ret, errors.New("missing non_entity_clients")
}
// don't error if the secret syncs key is missing
@@ -311,15 +317,15 @@ func (c *OperatorUsageCommand) totalOutput(data map[string]interface{}) []string
return out
}
- entityCount, ok := jsonNumberOK(total, "distinct_entities")
+ entityCount, ok := jsonNumberOK(total, "entity_clients")
if !ok {
- c.UI.Error("missing distinct_entities in total")
+ c.UI.Error("missing entity_clients in total")
return out
}
- tokenCount, ok := jsonNumberOK(total, "non_entity_tokens")
+ tokenCount, ok := jsonNumberOK(total, "non_entity_clients")
if !ok {
- c.UI.Error("missing non_entity_tokens in total")
+ c.UI.Error("missing non_entity_clients in total")
return out
}
// don't error if secret syncs key is missing
diff --git a/command/pki_reissue_intermediate.go b/command/pki_reissue_intermediate.go
index fa4dd38fbe..7501d4c862 100644
--- a/command/pki_reissue_intermediate.go
+++ b/command/pki_reissue_intermediate.go
@@ -113,6 +113,10 @@ func (c *PKIReIssueCACommand) Run(args []string) int {
}
templateData, err := parseTemplateCertificate(*certificate, useExistingKey, keyRef)
+ if err != nil {
+ c.UI.Error(fmt.Sprintf("Error fetching parsing template certificate: %v", err))
+ return 1
+ }
data := updateTemplateWithData(templateData, userData)
return pkiIssue(c.BaseCommand, parentIssuer, intermediateMount, c.flagNewIssuerName, c.flagKeyStorageSource, data)
diff --git a/command/proxy.go b/command/proxy.go
index 71559695e0..05a5239822 100644
--- a/command/proxy.go
+++ b/command/proxy.go
@@ -12,6 +12,7 @@ import (
"net"
"net/http"
"os"
+ "path/filepath"
"sort"
"strings"
"sync"
@@ -71,6 +72,7 @@ type ProxyCommand struct {
ShutdownCh chan struct{}
SighupCh chan struct{}
+ SigUSR2Ch chan struct{}
tlsReloadFuncsLock sync.RWMutex
tlsReloadFuncs []reloadutil.ReloadFunc
@@ -715,6 +717,16 @@ func (c *ProxyCommand) Run(args []string) int {
case c.reloadedCh <- struct{}{}:
default:
}
+ case <-c.SigUSR2Ch:
+ pprofPath := filepath.Join(os.TempDir(), "vault-proxy-pprof")
+ cpuProfileDuration := time.Second * 1
+ err := WritePprofToFile(pprofPath, cpuProfileDuration)
+ if err != nil {
+ c.logger.Error(err.Error())
+ continue
+ }
+
+ c.logger.Info(fmt.Sprintf("Wrote pprof files to: %s", pprofPath))
case <-ctx.Done():
return nil
}
diff --git a/command/proxy_test.go b/command/proxy_test.go
index 705224f2e8..3c2fdd0016 100644
--- a/command/proxy_test.go
+++ b/command/proxy_test.go
@@ -44,6 +44,7 @@ func testProxyCommand(tb testing.TB, logger hclog.Logger) (*cli.MockUi, *ProxyCo
},
ShutdownCh: MakeShutdownCh(),
SighupCh: MakeSighupCh(),
+ SigUSR2Ch: MakeSigUSR2Ch(),
logger: logger,
startedCh: make(chan struct{}, 5),
reloadedCh: make(chan struct{}, 5),
diff --git a/command/read.go b/command/read.go
index 742e036763..67ee2d6d7c 100644
--- a/command/read.go
+++ b/command/read.go
@@ -36,9 +36,17 @@ Usage: vault read [options] PATH
Reads data from Vault at the given path. This can be used to read secrets,
generate dynamic credentials, get configuration details, and more.
- Read a secret from the static secrets engine:
+ Read details of your own token:
- $ vault read secret/my-secret
+ $ vault read auth/token/lookup-self
+
+ Read entity details of a given ID:
+
+ $ vault read identity/entity/id/2f09126d-d161-abb8-2241-555886491d97
+
+ Generate credentials for my-role in an AWS secrets engine:
+
+ $ vault read aws/creds/my-role
For a full list of examples and paths, please see the documentation that
corresponds to the secrets engine in use.
diff --git a/command/server.go b/command/server.go
index c25f028543..54e921bbab 100644
--- a/command/server.go
+++ b/command/server.go
@@ -11,7 +11,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net"
"net/http"
"net/url"
@@ -47,7 +46,6 @@ import (
loghelper "github.com/hashicorp/vault/helper/logging"
"github.com/hashicorp/vault/helper/metricsutil"
"github.com/hashicorp/vault/helper/namespace"
- "github.com/hashicorp/vault/helper/testhelpers/teststorage"
"github.com/hashicorp/vault/helper/useragent"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/internalshared/configutil"
@@ -64,7 +62,6 @@ import (
"github.com/hashicorp/vault/vault/plugincatalog"
vaultseal "github.com/hashicorp/vault/vault/seal"
"github.com/hashicorp/vault/version"
- "github.com/mitchellh/go-testing-interface"
"github.com/posener/complete"
"github.com/sasha-s/go-deadlock"
"go.uber.org/atomic"
@@ -135,10 +132,9 @@ type ServerCommand struct {
flagDevLatency int
flagDevLatencyJitter int
flagDevLeasedKV bool
+ flagDevNoKV bool
flagDevKVV1 bool
flagDevSkipInit bool
- flagDevThreeNode bool
- flagDevFourCluster bool
flagDevTransactional bool
flagDevAutoSeal bool
flagDevClusterJson string
@@ -345,6 +341,13 @@ func (c *ServerCommand) Flags() *FlagSets {
Hidden: true,
})
+ f.BoolVar(&BoolVar{
+ Name: "dev-no-kv",
+ Target: &c.flagDevNoKV,
+ Default: false,
+ Hidden: true,
+ })
+
f.BoolVar(&BoolVar{
Name: "dev-kv-v1",
Target: &c.flagDevKVV1,
@@ -366,20 +369,6 @@ func (c *ServerCommand) Flags() *FlagSets {
Hidden: true,
})
- f.BoolVar(&BoolVar{
- Name: "dev-three-node",
- Target: &c.flagDevThreeNode,
- Default: false,
- Hidden: true,
- })
-
- f.BoolVar(&BoolVar{
- Name: "dev-four-cluster",
- Target: &c.flagDevFourCluster,
- Default: false,
- Hidden: true,
- })
-
f.BoolVar(&BoolVar{
Name: "dev-consul",
Target: &c.flagDevConsul,
@@ -1031,7 +1020,7 @@ func (c *ServerCommand) Run(args []string) int {
}
// Automatically enable dev mode if other dev flags are provided.
- if c.flagDevConsul || c.flagDevHA || c.flagDevTransactional || c.flagDevLeasedKV || c.flagDevThreeNode || c.flagDevFourCluster || c.flagDevAutoSeal || c.flagDevKVV1 || c.flagDevTLS {
+ if c.flagDevConsul || c.flagDevHA || c.flagDevTransactional || c.flagDevLeasedKV || c.flagDevAutoSeal || c.flagDevKVV1 || c.flagDevNoKV || c.flagDevTLS {
c.flagDev = true
}
@@ -1095,11 +1084,6 @@ func (c *ServerCommand) Run(args []string) int {
f.applyLogConfigOverrides(config.SharedConfig)
- // Set 'trace' log level for the following 'dev' clusters
- if c.flagDevThreeNode || c.flagDevFourCluster {
- config.LogLevel = "trace"
- }
-
l, err := c.configureLogging(config)
if err != nil {
c.UI.Error(err.Error())
@@ -1267,13 +1251,6 @@ func (c *ServerCommand) Run(args []string) int {
}()
coreConfig := createCoreConfig(c, config, backend, configSR, setSealResponse.barrierSeal, setSealResponse.unwrapSeal, metricsHelper, metricSink, secureRandomReader)
- if c.flagDevThreeNode {
- return c.enableThreeNodeDevCluster(&coreConfig, info, infoKeys, c.flagDevListenAddr, os.Getenv("VAULT_DEV_TEMP_DIR"))
- }
-
- if c.flagDevFourCluster {
- return entEnableFourClusterDev(c, &coreConfig, info, infoKeys, os.Getenv("VAULT_DEV_TEMP_DIR"))
- }
if allowPendingRemoval := os.Getenv(consts.EnvVaultAllowPendingRemovalMounts); allowPendingRemoval != "" {
var err error
@@ -1591,7 +1568,7 @@ func (c *ServerCommand) Run(args []string) int {
clusterJson.CACertPath = fmt.Sprintf("%s/%s", certDir, server.VaultDevCAFilename)
}
- if c.flagDevClusterJson != "" && !c.flagDevThreeNode {
+ if c.flagDevClusterJson != "" {
b, err := jsonutil.EncodeJSON(clusterJson)
if err != nil {
c.UI.Error(fmt.Sprintf("Error encoding cluster.json: %s", err))
@@ -1703,7 +1680,7 @@ func (c *ServerCommand) Run(args []string) int {
sr.NotifyConfigurationReload(srConfig)
}
- if err := core.ReloadCensus(); err != nil {
+ if err := core.ReloadCensusManager(false); err != nil {
c.UI.Error(err.Error())
}
@@ -1774,41 +1751,13 @@ func (c *ServerCommand) Run(args []string) int {
// into a state where it cannot process requests so we can get pprof outputs
// via SIGUSR2.
pprofPath := filepath.Join(os.TempDir(), "vault-pprof")
- err := os.MkdirAll(pprofPath, os.ModePerm)
+ cpuProfileDuration := time.Second * 1
+ err := WritePprofToFile(pprofPath, cpuProfileDuration)
if err != nil {
- c.logger.Error("Could not create temporary directory for pprof", "error", err)
+ c.logger.Error(err.Error())
continue
}
- dumps := []string{"goroutine", "heap", "allocs", "threadcreate", "profile"}
- for _, dump := range dumps {
- pFile, err := os.Create(filepath.Join(pprofPath, dump))
- if err != nil {
- c.logger.Error("error creating pprof file", "name", dump, "error", err)
- break
- }
-
- if dump != "profile" {
- err = pprof.Lookup(dump).WriteTo(pFile, 0)
- if err != nil {
- c.logger.Error("error generating pprof data", "name", dump, "error", err)
- pFile.Close()
- break
- }
- } else {
- // CPU profiles need to run for a duration so we're going to run it
- // just for one second to avoid blocking here.
- if err := pprof.StartCPUProfile(pFile); err != nil {
- c.logger.Error("could not start CPU profile: ", err)
- pFile.Close()
- break
- }
- time.Sleep(time.Second * 1)
- pprof.StopCPUProfile()
- }
- pFile.Close()
- }
-
c.logger.Info(fmt.Sprintf("Wrote pprof files to: %s", pprofPath))
}
}
@@ -2105,273 +2054,36 @@ func (c *ServerCommand) enableDev(core *vault.Core, coreConfig *vault.CoreConfig
}
}
- kvVer := "2"
- if c.flagDevKVV1 || c.flagDevLeasedKV {
- kvVer = "1"
- }
- req := &logical.Request{
- Operation: logical.UpdateOperation,
- ClientToken: init.RootToken,
- Path: "sys/mounts/secret",
- Data: map[string]interface{}{
- "type": "kv",
- "path": "secret/",
- "description": "key/value secret storage",
- "options": map[string]string{
- "version": kvVer,
+ if !c.flagDevNoKV {
+ kvVer := "2"
+ if c.flagDevKVV1 || c.flagDevLeasedKV {
+ kvVer = "1"
+ }
+ req := &logical.Request{
+ Operation: logical.UpdateOperation,
+ ClientToken: init.RootToken,
+ Path: "sys/mounts/secret",
+ Data: map[string]interface{}{
+ "type": "kv",
+ "path": "secret/",
+ "description": "key/value secret storage",
+ "options": map[string]string{
+ "version": kvVer,
+ },
},
- },
- }
- resp, err := core.HandleRequest(ctx, req)
- if err != nil {
- return nil, fmt.Errorf("error creating default KV store: %w", err)
- }
- if resp.IsError() {
- return nil, fmt.Errorf("failed to create default KV store: %w", resp.Error())
+ }
+ resp, err := core.HandleRequest(ctx, req)
+ if err != nil {
+ return nil, fmt.Errorf("error creating default KV store: %w", err)
+ }
+ if resp.IsError() {
+ return nil, fmt.Errorf("failed to create default KV store: %w", resp.Error())
+ }
}
return init, nil
}
-func (c *ServerCommand) enableThreeNodeDevCluster(base *vault.CoreConfig, info map[string]string, infoKeys []string, devListenAddress, tempDir string) int {
- conf, opts := teststorage.ClusterSetup(base, &vault.TestClusterOptions{
- HandlerFunc: vaulthttp.Handler,
- BaseListenAddress: c.flagDevListenAddr,
- Logger: c.logger,
- TempDir: tempDir,
- DefaultHandlerProperties: vault.HandlerProperties{
- ListenerConfig: &configutil.Listener{
- Profiling: configutil.ListenerProfiling{
- UnauthenticatedPProfAccess: true,
- },
- Telemetry: configutil.ListenerTelemetry{
- UnauthenticatedMetricsAccess: true,
- },
- },
- },
- }, nil)
- testCluster := vault.NewTestCluster(&testing.RuntimeT{}, conf, opts)
- defer c.cleanupGuard.Do(testCluster.Cleanup)
-
- if constants.IsEnterprise {
- err := testcluster.WaitForActiveNodeAndPerfStandbys(context.Background(), testCluster)
- if err != nil {
- c.UI.Error(fmt.Sprintf("perf standbys didn't become ready: %v", err))
- return 1
- }
- }
-
- info["cluster parameters path"] = testCluster.TempDir
- infoKeys = append(infoKeys, "cluster parameters path")
-
- for i, core := range testCluster.Cores {
- info[fmt.Sprintf("node %d api address", i)] = fmt.Sprintf("https://%s", core.Listeners[0].Address.String())
- infoKeys = append(infoKeys, fmt.Sprintf("node %d api address", i))
- }
-
- infoKeys = append(infoKeys, "version")
- verInfo := version.GetVersion()
- info["version"] = verInfo.FullVersionNumber(false)
- if verInfo.Revision != "" {
- info["version sha"] = strings.Trim(verInfo.Revision, "'")
- infoKeys = append(infoKeys, "version sha")
- }
-
- infoKeys = append(infoKeys, "cgo")
- info["cgo"] = "disabled"
- if version.CgoEnabled {
- info["cgo"] = "enabled"
- }
-
- infoKeys = append(infoKeys, "go version")
- info["go version"] = runtime.Version()
-
- fipsStatus := entGetFIPSInfoKey()
- if fipsStatus != "" {
- infoKeys = append(infoKeys, "fips")
- info["fips"] = fipsStatus
- }
-
- // Server configuration output
- padding := 24
-
- sort.Strings(infoKeys)
- c.UI.Output("==> Vault server configuration:\n")
-
- for _, k := range infoKeys {
- c.UI.Output(fmt.Sprintf(
- "%s%s: %s",
- strings.Repeat(" ", padding-len(k)),
- strings.Title(k),
- info[k]))
- }
-
- c.UI.Output("")
-
- for _, core := range testCluster.Cores {
- core.Server.Handler = vaulthttp.Handler.Handler(&vault.HandlerProperties{
- Core: core.Core,
- ListenerConfig: &configutil.Listener{},
- })
- core.SetClusterHandler(core.Server.Handler)
- }
-
- testCluster.Start()
-
- ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)
-
- if base.DevToken != "" {
- req := &logical.Request{
- ID: "dev-gen-root",
- Operation: logical.UpdateOperation,
- ClientToken: testCluster.RootToken,
- Path: "auth/token/create",
- Data: map[string]interface{}{
- "id": base.DevToken,
- "policies": []string{"root"},
- "no_parent": true,
- "no_default_policy": true,
- },
- }
- resp, err := testCluster.Cores[0].HandleRequest(ctx, req)
- if err != nil {
- c.UI.Error(fmt.Sprintf("failed to create root token with ID %s: %s", base.DevToken, err))
- return 1
- }
- if resp == nil {
- c.UI.Error(fmt.Sprintf("nil response when creating root token with ID %s", base.DevToken))
- return 1
- }
- if resp.Auth == nil {
- c.UI.Error(fmt.Sprintf("nil auth when creating root token with ID %s", base.DevToken))
- return 1
- }
-
- testCluster.RootToken = resp.Auth.ClientToken
-
- req.ID = "dev-revoke-init-root"
- req.Path = "auth/token/revoke-self"
- req.Data = nil
- _, err = testCluster.Cores[0].HandleRequest(ctx, req)
- if err != nil {
- c.UI.Output(fmt.Sprintf("failed to revoke initial root token: %s", err))
- return 1
- }
- }
-
- // Set the token
- tokenHelper, err := c.TokenHelper()
- if err != nil {
- c.UI.Error(fmt.Sprintf("Error getting token helper: %s", err))
- return 1
- }
- if err := tokenHelper.Store(testCluster.RootToken); err != nil {
- c.UI.Error(fmt.Sprintf("Error storing in token helper: %s", err))
- return 1
- }
-
- if err := ioutil.WriteFile(filepath.Join(testCluster.TempDir, "root_token"), []byte(testCluster.RootToken), 0o600); err != nil {
- c.UI.Error(fmt.Sprintf("Error writing token to tempfile: %s", err))
- return 1
- }
-
- c.UI.Output(fmt.Sprintf(
- "==> Three node dev mode is enabled\n\n" +
- "The unseal key and root token are reproduced below in case you\n" +
- "want to seal/unseal the Vault or play with authentication.\n",
- ))
-
- for i, key := range testCluster.BarrierKeys {
- c.UI.Output(fmt.Sprintf(
- "Unseal Key %d: %s",
- i+1, base64.StdEncoding.EncodeToString(key),
- ))
- }
-
- c.UI.Output(fmt.Sprintf(
- "\nRoot Token: %s\n", testCluster.RootToken,
- ))
-
- c.UI.Output(fmt.Sprintf(
- "\nUseful env vars:\n"+
- "VAULT_TOKEN=%s\n"+
- "VAULT_ADDR=%s\n"+
- "VAULT_CACERT=%s/ca_cert.pem\n",
- testCluster.RootToken,
- testCluster.Cores[0].Client.Address(),
- testCluster.TempDir,
- ))
-
- if c.flagDevClusterJson != "" {
- clusterJson := testcluster.ClusterJson{
- Nodes: []testcluster.ClusterNode{},
- CACertPath: filepath.Join(testCluster.TempDir, "ca_cert.pem"),
- RootToken: testCluster.RootToken,
- }
- for _, core := range testCluster.Cores {
- clusterJson.Nodes = append(clusterJson.Nodes, testcluster.ClusterNode{
- APIAddress: core.Client.Address(),
- })
- }
- b, err := jsonutil.EncodeJSON(clusterJson)
- if err != nil {
- c.UI.Error(fmt.Sprintf("Error encoding cluster.json: %s", err))
- return 1
- }
- err = os.WriteFile(c.flagDevClusterJson, b, 0o600)
- if err != nil {
- c.UI.Error(fmt.Sprintf("Error writing cluster.json %q: %s", c.flagDevClusterJson, err))
- return 1
- }
- }
-
- // Output the header that the server has started
- c.UI.Output("==> Vault server started! Log data will stream in below:\n")
-
- // Inform any tests that the server is ready
- select {
- case c.startedCh <- struct{}{}:
- default:
- }
-
- // Release the log gate.
- c.flushLog()
-
- // Wait for shutdown
- shutdownTriggered := false
-
- for !shutdownTriggered {
- select {
- case <-c.ShutdownCh:
- c.UI.Output("==> Vault shutdown triggered")
-
- // Stop the listeners so that we don't process further client requests.
- c.cleanupGuard.Do(testCluster.Cleanup)
-
- // Finalize will wait until after Vault is sealed, which means the
- // request forwarding listeners will also be closed (and also
- // waited for).
- for _, core := range testCluster.Cores {
- if err := core.Shutdown(); err != nil {
- c.UI.Error(fmt.Sprintf("Error with core shutdown: %s", err))
- }
- }
-
- shutdownTriggered = true
-
- case <-c.SighupCh:
- c.UI.Output("==> Vault reload triggered")
- for _, core := range testCluster.Cores {
- if err := c.Reload(core.ReloadFuncsLock, core.ReloadFuncs, nil, core.Core); err != nil {
- c.UI.Error(fmt.Sprintf("Error(s) were encountered during reload: %s", err))
- }
- }
- }
- }
-
- return 0
-}
-
// addPlugin adds any plugins to the catalog
func (c *ServerCommand) addPlugin(path, token string, core *vault.Core) error {
// Get the sha256 of the file at the given path.
@@ -3331,7 +3043,7 @@ func initDevCore(c *ServerCommand, coreConfig *vault.CoreConfig, config *server.
func startHttpServers(c *ServerCommand, core *vault.Core, config *server.Config, lns []listenerutil.Listener) error {
for _, ln := range lns {
if ln.Config == nil {
- return fmt.Errorf("Found nil listener config after parsing")
+ return fmt.Errorf("found nil listener config after parsing")
}
if err := config2.IsValidListener(ln.Config); err != nil {
diff --git a/command/server/listener_tcp_test.go b/command/server/listener_tcp_test.go
index 42da6c0d21..6508e7a8af 100644
--- a/command/server/listener_tcp_test.go
+++ b/command/server/listener_tcp_test.go
@@ -6,9 +6,7 @@ package server
import (
"crypto/tls"
"crypto/x509"
- "fmt"
"io/ioutil"
- "math/rand"
"net"
"os"
"testing"
@@ -18,6 +16,7 @@ import (
"github.com/hashicorp/go-sockaddr"
"github.com/hashicorp/vault/internalshared/configutil"
"github.com/pires/go-proxyproto"
+ "github.com/stretchr/testify/require"
)
func TestTCPListener(t *testing.T) {
@@ -25,9 +24,7 @@ func TestTCPListener(t *testing.T) {
Address: "127.0.0.1:0",
TLSDisable: true,
}, nil, cli.NewMockUi())
- if err != nil {
- t.Fatalf("err: %s", err)
- }
+ require.NoError(t, err)
connFn := func(lnReal net.Listener) (net.Conn, error) {
return net.Dial("tcp", ln.Addr().String())
@@ -41,19 +38,13 @@ func TestTCPListener_tls(t *testing.T) {
wd, _ := os.Getwd()
wd += "/test-fixtures/reload/"
- td, err := ioutil.TempDir("", fmt.Sprintf("vault-test-%d", rand.New(rand.NewSource(time.Now().Unix())).Int63()))
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(td)
-
// Setup initial certs
- inBytes, _ := ioutil.ReadFile(wd + "reload_ca.pem")
+ inBytes, err := os.ReadFile(wd + "reload_ca.pem")
+ require.NoError(t, err)
+
certPool := x509.NewCertPool()
ok := certPool.AppendCertsFromPEM(inBytes)
- if !ok {
- t.Fatal("not ok when appending CA cert")
- }
+ require.True(t, ok, "not ok when appending CA cert")
ln, _, _, err := tcpListenerFactory(&configutil.Listener{
Address: "127.0.0.1:0",
@@ -62,9 +53,8 @@ func TestTCPListener_tls(t *testing.T) {
TLSRequireAndVerifyClientCert: true,
TLSClientCAFile: wd + "reload_ca.pem",
}, nil, cli.NewMockUi())
- if err != nil {
- t.Fatalf("err: %s", err)
- }
+ require.NoError(t, err)
+
cwd, _ := os.Getwd()
clientCert, _ := tls.LoadX509KeyPair(
@@ -100,9 +90,7 @@ func TestTCPListener_tls(t *testing.T) {
TLSDisableClientCerts: true,
TLSClientCAFile: wd + "reload_ca.pem",
}, nil, cli.NewMockUi())
- if err == nil {
- t.Fatal("expected error due to mutually exclusive client cert options")
- }
+ require.Error(t, err, "expected error due to mutually exclusive client cert options")
ln, _, _, err = tcpListenerFactory(&configutil.Listener{
Address: "127.0.0.1:0",
@@ -111,9 +99,7 @@ func TestTCPListener_tls(t *testing.T) {
TLSDisableClientCerts: true,
TLSClientCAFile: wd + "reload_ca.pem",
}, nil, cli.NewMockUi())
- if err != nil {
- t.Fatalf("err: %s", err)
- }
+ require.NoError(t, err)
testListenerImpl(t, ln, connFn(false), "foo.example.com", 0, "127.0.0.1", false)
}
@@ -122,19 +108,11 @@ func TestTCPListener_tls13(t *testing.T) {
wd, _ := os.Getwd()
wd += "/test-fixtures/reload/"
- td, err := ioutil.TempDir("", fmt.Sprintf("vault-test-%d", rand.New(rand.NewSource(time.Now().Unix())).Int63()))
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(td)
-
// Setup initial certs
inBytes, _ := ioutil.ReadFile(wd + "reload_ca.pem")
certPool := x509.NewCertPool()
ok := certPool.AppendCertsFromPEM(inBytes)
- if !ok {
- t.Fatal("not ok when appending CA cert")
- }
+ require.True(t, ok, "not ok when appending CA cert")
ln, _, _, err := tcpListenerFactory(&configutil.Listener{
Address: "127.0.0.1:0",
@@ -144,9 +122,8 @@ func TestTCPListener_tls13(t *testing.T) {
TLSClientCAFile: wd + "reload_ca.pem",
TLSMinVersion: "tls13",
}, nil, cli.NewMockUi())
- if err != nil {
- t.Fatalf("err: %s", err)
- }
+ require.NoError(t, err)
+
cwd, _ := os.Getwd()
clientCert, _ := tls.LoadX509KeyPair(
@@ -183,9 +160,7 @@ func TestTCPListener_tls13(t *testing.T) {
TLSClientCAFile: wd + "reload_ca.pem",
TLSMinVersion: "tls13",
}, nil, cli.NewMockUi())
- if err == nil {
- t.Fatal("expected error due to mutually exclusive client cert options")
- }
+ require.Error(t, err, "expected error due to mutually exclusive client cert options")
ln, _, _, err = tcpListenerFactory(&configutil.Listener{
Address: "127.0.0.1:0",
@@ -195,9 +170,7 @@ func TestTCPListener_tls13(t *testing.T) {
TLSClientCAFile: wd + "reload_ca.pem",
TLSMinVersion: "tls13",
}, nil, cli.NewMockUi())
- if err != nil {
- t.Fatalf("err: %s", err)
- }
+ require.NoError(t, err)
testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS13, "127.0.0.1", false)
@@ -209,9 +182,7 @@ func TestTCPListener_tls13(t *testing.T) {
TLSClientCAFile: wd + "reload_ca.pem",
TLSMaxVersion: "tls12",
}, nil, cli.NewMockUi())
- if err != nil {
- t.Fatalf("err: %s", err)
- }
+ require.NoError(t, err)
testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS12, "127.0.0.1", false)
}
@@ -429,9 +400,7 @@ func TestTCPListener_proxyProtocol(t *testing.T) {
proxyProtocolAuthorizedAddrs := []*sockaddr.SockAddrMarshaler{}
if tc.AuthorizedAddr != "" {
sockAddr, err := sockaddr.NewSockAddr(tc.AuthorizedAddr)
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
proxyProtocolAuthorizedAddrs = append(
proxyProtocolAuthorizedAddrs,
&sockaddr.SockAddrMarshaler{SockAddr: sockAddr},
@@ -444,12 +413,11 @@ func TestTCPListener_proxyProtocol(t *testing.T) {
ProxyProtocolBehavior: tc.Behavior,
ProxyProtocolAuthorizedAddrs: proxyProtocolAuthorizedAddrs,
}, nil, cli.NewMockUi())
- if err != nil {
- t.Fatalf("err: %s", err)
- }
+ require.NoError(t, err)
connFn := func(lnReal net.Listener) (net.Conn, error) {
- conn, err := net.Dial("tcp", ln.Addr().String())
+ d := net.Dialer{Timeout: 3 * time.Second}
+ conn, err := d.Dial("tcp", lnReal.Addr().String())
if err != nil {
return nil, err
}
@@ -464,3 +432,73 @@ func TestTCPListener_proxyProtocol(t *testing.T) {
})
}
}
+
+// TestTCPListener_proxyProtocol_keepAcceptingOnInvalidUpstream ensures that the server side listener
+// never returns an error from the listener.Accept method if the error is that the
+// upstream proxy isn't trusted. If an error is returned, underlying Go HTTP native
+// libraries may close down a server and stop listening.
+func TestTCPListener_proxyProtocol_keepAcceptingOnInvalidUpstream(t *testing.T) {
+ timeout := 3 * time.Second
+
+ // Configure proxy so we hit the deny unauthorized behavior.
+ header := &proxyproto.Header{
+ Version: 1,
+ Command: proxyproto.PROXY,
+ TransportProtocol: proxyproto.TCPv4,
+ SourceAddr: &net.TCPAddr{
+ IP: net.ParseIP("10.1.1.1"),
+ Port: 1000,
+ },
+ DestinationAddr: &net.TCPAddr{
+ IP: net.ParseIP("20.2.2.2"),
+ Port: 2000,
+ },
+ }
+
+ var authAddrs []*sockaddr.SockAddrMarshaler
+ sockAddr, err := sockaddr.NewSockAddr("10.0.0.1/32")
+ require.NoError(t, err)
+ authAddrs = append(authAddrs, &sockaddr.SockAddrMarshaler{SockAddr: sockAddr})
+
+ ln, _, _, err := tcpListenerFactory(&configutil.Listener{
+ Address: "127.0.0.1:0",
+ TLSDisable: true,
+ ProxyProtocolBehavior: "deny_unauthorized",
+ ProxyProtocolAuthorizedAddrs: authAddrs,
+ }, nil, cli.NewMockUi())
+ require.NoError(t, err)
+
+ // Kick off setting up server side, if we ever accept a connection send it out
+ // via a channel.
+ serverConnCh := make(chan net.Conn, 1)
+ go func() {
+ serverConn, err := ln.Accept()
+ // We shouldn't ever have an error if the problem was only that the upstream
+ // proxy wasn't trusted.
+ // An error would lead to the http.Serve closing the listener and giving up.
+ require.NoError(t, err, "server side listener errored")
+ serverConnCh <- serverConn
+ }()
+
+ // Now try to connect as the client.
+ d := net.Dialer{Timeout: timeout}
+ clientConn, err := d.Dial("tcp", ln.Addr().String())
+ require.NoError(t, err)
+ defer clientConn.Close()
+ _, err = header.WriteTo(clientConn)
+ require.NoError(t, err)
+
+ // Wait for the server to have accepted a connection, or we time out.
+ select {
+ case <-time.After(timeout):
+ // The server still hasn't accepted any valid client connection.
+ // Try to write another header using the same connection which should have
+ // been closed by the server, we expect that this client side connection was
+ // closed as it us untrusted,
+ _, err = header.WriteTo(clientConn)
+ require.Error(t, err, "reused a rejected connection without error")
+ case serverConn := <-serverConnCh:
+ require.NotNil(t, serverConn)
+ defer serverConn.Close()
+ }
+}
diff --git a/command/server/listener_test.go b/command/server/listener_test.go
index b1c6be73f7..cffba69eed 100644
--- a/command/server/listener_test.go
+++ b/command/server/listener_test.go
@@ -9,6 +9,7 @@ import (
"io"
"net"
"testing"
+ "time"
)
type testListenerConnFn func(net.Listener) (net.Conn, error)
@@ -60,7 +61,11 @@ func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn,
}
}
- server := <-serverCh
+ var server net.Conn
+ select {
+ case <-time.After(3 * time.Second):
+ case server = <-serverCh:
+ }
if server == nil {
if !expectError {
diff --git a/command/server_util.go b/command/server_util.go
index 4573ec14ec..c0227ea28b 100644
--- a/command/server_util.go
+++ b/command/server_util.go
@@ -24,6 +24,10 @@ func (c *ServerCommand) ReloadedCh() chan struct{} {
return c.reloadedCh
}
+func (c *ServerCommand) LicenseReloadedCh() chan error {
+ return c.licenseReloadedCh
+}
+
func testServerCommand(tb testing.TB) (*cli.MockUi, *ServerCommand) {
tb.Helper()
diff --git a/command/util.go b/command/util.go
index 26fd38000b..55aa7778c2 100644
--- a/command/util.go
+++ b/command/util.go
@@ -8,6 +8,8 @@ import (
"io"
"net/http"
"os"
+ "path/filepath"
+ "runtime/pprof"
"testing"
"time"
@@ -201,3 +203,40 @@ func (r *recordingRoundTripper) RoundTrip(req *http.Request) (*http.Response, er
StatusCode: 200,
}, nil
}
+
+// WritePprofToFile will create a temporary directory at the specified path
+// and generate pprof files at that location. CPU requires polling over a
+// duration. For most situations 1 second is enough.
+func WritePprofToFile(path string, cpuProfileDuration time.Duration) error {
+ err := os.MkdirAll(path, os.ModePerm)
+ if err != nil {
+ return fmt.Errorf("could not create temporary directory for pprof: %v", err)
+ }
+
+ dumps := []string{"goroutine", "heap", "allocs", "threadcreate", "profile"}
+ for _, dump := range dumps {
+ pFile, err := os.Create(filepath.Join(path, dump))
+ if err != nil {
+ return fmt.Errorf("error creating pprof file %s: %v", dump, err)
+ }
+
+ if dump != "profile" {
+ err = pprof.Lookup(dump).WriteTo(pFile, 0)
+ if err != nil {
+ pFile.Close()
+ return fmt.Errorf("error generating pprof data for %s: %v", dump, err)
+ }
+ } else {
+ // CPU profiles need to run for a duration so we're going to run it
+ // just for one second to avoid blocking here.
+ if err := pprof.StartCPUProfile(pFile); err != nil {
+ pFile.Close()
+ return fmt.Errorf("could not start CPU profile: %v", err)
+ }
+ time.Sleep(cpuProfileDuration)
+ pprof.StopCPUProfile()
+ }
+ pFile.Close()
+ }
+ return nil
+}
diff --git a/command/write.go b/command/write.go
index 33ee3be0f2..0b10ec4656 100644
--- a/command/write.go
+++ b/command/write.go
@@ -51,13 +51,15 @@ Usage: vault write [options] PATH [DATA K=V...]
it is loaded from a file. If the value is "-", Vault will read the value from
stdin.
- Persist data in the generic secrets engine:
+ Store an arbitrary secret in the token's cubbyhole.
- $ vault write secret/my-secret foo=bar
+ $ vault write cubbyhole/git-credentials username="student01" password="p@$$w0rd"
Create a new encryption key in the transit secrets engine:
- $ vault write -f transit/keys/my-key
+ $ vault write -force transit/keys/my-key
+
+ The -force / -f flag allows a write operation without any input data.
Upload an AWS IAM policy from a file on disk:
@@ -67,6 +69,10 @@ Usage: vault write [options] PATH [DATA K=V...]
$ echo $MY_TOKEN | vault write consul/config/access token=-
+ Create a token
+
+ $ vault write auth/token/create policies="admin" policies="secops" ttl=8h num_uses=3
+
For a full list of examples and paths, please see the documentation that
corresponds to the secret engines in use.
diff --git a/enos/ci/service-user-iam/main.tf b/enos/ci/service-user-iam/main.tf
index 0df9bcafca..24265052a4 100644
--- a/enos/ci/service-user-iam/main.tf
+++ b/enos/ci/service-user-iam/main.tf
@@ -97,6 +97,7 @@ data "aws_iam_policy_document" "enos_scenario" {
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CancelSpotFleetRequests",
"ec2:CancelSpotInstanceRequests",
+ "ec2:CreateEgressOnlyInternetGateway",
"ec2:CreateInternetGateway",
"ec2:CreateKeyPair",
"ec2:CreateFleet",
@@ -110,6 +111,7 @@ data "aws_iam_policy_document" "enos_scenario" {
"ec2:CreateTags",
"ec2:CreateVolume",
"ec2:CreateVPC",
+ "ec2:DeleteEgressOnlyInternetGateway",
"ec2:DeleteFleets",
"ec2:DeleteInternetGateway",
"ec2:DeleteLaunchTemplate",
@@ -125,6 +127,7 @@ data "aws_iam_policy_document" "enos_scenario" {
"ec2:DeleteVPC",
"ec2:DescribeAccountAttributes",
"ec2:DescribeAvailabilityZones",
+ "ec2:DescribeEgressOnlyInternetGateways",
"ec2:DescribeFleets",
"ec2:DescribeFleetHistory",
"ec2:DescribeFleetInstances",
diff --git a/enos/enos-descriptions.hcl b/enos/enos-descriptions.hcl
new file mode 100644
index 0000000000..c78dbeacf7
--- /dev/null
+++ b/enos/enos-descriptions.hcl
@@ -0,0 +1,196 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+globals {
+ description = {
+ build_vault = <<-EOF
+ Determine which Vault artifact we want to use for the scenario. Depending on the
+ 'artifact_source' variant we'll either build Vault from the local branch, fetch a candidate
+ build from Artifactory, or use a local artifact that was built in CI via CRT.
+ EOF
+
+ create_backend_cluster = <<-EOF
+ Create a storage backend cluster if necessary. When configured to use Consul it will
+ install, configure, and start the Consul cluster on the target hosts and wait for the Consul
+ cluster to become healthy. When using integrated raft storage this step is a no-op as the
+ Vault cluster nodes will provide their own integrated storage.
+ EOF
+
+ create_seal_key = <<-EOF
+ Create the necessary seal key infrastructure for Vaults auto-unseal functionality. Depending
+ on the 'seal' variant this step will perform different actions. When using 'shamir' the step
+ is a no-op as we won't require an external seal mechanism. When using 'pkcs11' this step will
+ create a SoftHSM slot and associated token which can be distributed to all target nodes. When
+ using 'awskms' a new AWSKMS key will be created. The necessary security groups and policies
+ for Vault target nodes to access it the AWSKMS key are handled in the target modules.
+ EOF
+
+ create_vault_cluster = <<-EOF
+ Create the the Vault cluster. In this module we'll install, configure, start, initialize and
+ unseal all the nodes in the Vault. After initialization it also enables various audit engines.
+ EOF
+
+ create_vault_cluster_backend_targets = <<-EOF
+ Create the target machines that we'll install Consul onto when using Consul for storage. We
+ also handle creating AWS instance profiles and security groups that allow for auto-discovery
+ via the retry_join functionality in Consul. The security group firewall rules will
+ automatically allow SSH access from the host external IP address of the machine executing
+ Enos, in addition to all of the required ports for Consul to function and be accessible in the
+ VPC.
+ EOF
+
+ create_vault_cluster_targets = <<-EOF
+ Create the target machines that we'll install Vault onto. We also handle creating AWS instance
+ profiles and security groups that allow for auto-discovery via the retry_join functionality in
+ Consul. The security group firewall rules will automatically allow SSH access from the host
+ external IP address of the machine executing Enos, in addition to all of the required ports
+ for Vault to function and be accessible in the VPC.
+ EOF
+
+ create_vpc = <<-EOF
+ Create an AWS VPC, internet gateway, default security group, and default subnet that allows
+ egress traffic via the internet gateway.
+ EOF
+
+ ec2_info = <<-EOF
+ Query various endpoints in AWS Ec2 to gather metadata we'll use later in our run when creating
+ infrastructure for the Vault cluster. This metadata includes:
+ - AMI IDs for different Linux distributions and platform architectures
+ - Available Ec2 Regions
+ - Availability Zones for our desired machine instance types
+ EOF
+
+ enable_multiseal = <<-EOF
+ Configure the Vault cluster with 'enable_multiseal' and up to three auto-unseal methods
+ via individual, prioritized 'seal' stanzas.
+ EOF
+
+ get_local_metadata = <<-EOF
+ Performs several Vault quality verification that are dynamically modified based on the Vault
+ binary version, commit SHA, build-date (commit SHA date), and edition metadata. When we're
+ testing existing artifacts this expected metadata is passed in via Enos variables. When we're
+ building a local by using the 'artifact_source:local' variant, this step executes and
+ populates the expected metadata with that of our branch so that we don't have to update the
+ Enos variables on each commit.
+ EOF
+
+ get_vault_cluster_ip_addresses = <<-EOF
+ Map the public and private IP addresses of the Vault cluster nodes and segregate them by
+ their leader status. This allows us to easily determine the public IP addresses of the leader
+ and follower nodes.
+ EOF
+
+ read_backend_license = <<-EOF
+ When using Consul Enterprise as a storage backend, ensure that a Consul Enterprise license is
+ present on disk and read its contents so that we can utilize it when configuring the storage
+ cluster. Must have the 'backend:consul' and 'consul_edition:ent' variants.
+ EOF
+
+ read_vault_license = <<-EOF
+ When deploying Vault Enterprise, ensure a Vault Enterprise license is present on disk and
+ read its contents so that we can utilize it when configuring the Vault Enterprise cluster.
+ Must have the 'edition' variant to be set to any Enterprise edition.
+ EOF
+
+ shutdown_nodes = <<-EOF
+ Shut down the nodes to ensure that they are no longer operating software as part of the
+ cluster.
+ EOF
+
+ start_vault_agent = <<-EOF
+ Create an agent approle in the auth engine, generate a Vault Agent configuration file, and
+ start the Vault agent.
+ EOF
+
+ stop_vault = <<-EOF
+ Stop the Vault cluster by stopping the vault service via systemctl.
+ EOF
+
+ vault_leader_step_down = <<-EOF
+ Force the Vault cluster leader to step down which forces the Vault cluster to perform a leader
+ election.
+ EOF
+
+ verify_agent_output = <<-EOF
+ Vault running in Agent mode uses templates to create log output.
+ EOF
+
+ verify_raft_cluster_all_nodes_are_voters = <<-EOF
+ When configured with a 'backend:raft' variant, verify that all nodes in the cluster are
+ healthy and are voters.
+ EOF
+
+ verify_autopilot_idle_state = <<-EOF
+ Wait for the Autopilot to upgrade the entire Vault cluster and ensure that the target version
+ matches the candidate version. Ensure that the cluster reaches an upgrade state of
+ 'await-server-removal'.
+ EOF
+
+ verify_read_test_data = <<-EOF
+ Verify that we are able to read test data we've written in prior steps. This includes:
+ - Auth user policies
+ - Kv data
+ EOF
+
+ verify_replication_status = <<-EOF
+ Verify that the default replication status is correct depending on the edition of Vault that
+ been deployed. When testing a Community Edition of Vault we'll ensure that replication is not
+ enabled. When testing any Enterprise edition of Vault we'll ensure that Performance and
+ Disaster Recovery replication are available.
+ EOF
+
+ verify_seal_rewrap_entries_processed_eq_entries_succeeded_post_rewrap = <<-EOF
+ Verify that the v1/sys/sealwrap/rewrap Vault API returns the rewrap data and
+ 'entries.processed' equals 'entries.succeeded' after the rewrap has completed.
+ EOF
+
+ verify_seal_rewrap_entries_processed_is_gt_zero_post_rewrap = <<-EOF
+ Verify that the /sys/sealwrap/rewrap Vault API returns the rewrap data and the 'entries.processed' has
+ processed at least one entry after the rewrap has completed.
+ EOF
+
+ verify_seal_rewrap_is_running_false_post_rewrap = <<-EOF
+ Verify that the v1/sys/sealwrap/rewrap Vault API returns the rewrap data and 'is_running' is set to
+ 'false' after a rewrap has completed.
+ EOF
+
+ verify_seal_rewrap_no_entries_fail_during_rewrap = <<-EOF
+ Verify that the v1/sys/sealwrap/rewrap Vault API returns the rewrap data and 'entries.failed' is '0'
+ after the rewrap has completed.
+ EOF
+
+ verify_seal_type = <<-EOF
+ Vault's reported seal type matches our configuration.
+ EOF
+
+ verify_write_test_data = <<-EOF
+ Verify that vault is capable mounting engines and writing data to them. These currently include:
+ - Mount the auth engine
+ - Mount the kv engine
+ - Write auth user policies
+ - Write kv data
+ EOF
+
+ verify_ui = <<-EOF
+ The Vault UI assets are embedded in the Vault binary and available when running.
+ EOF
+
+ verify_vault_unsealed = <<-EOF
+ Verify that the Vault cluster has successfully unsealed.
+ EOF
+
+ verify_vault_version = <<-EOF
+ Verify that the Vault CLI has the correct embedded version metadata and that the Vault Cluster
+ verision history includes our expected version. The CLI metadata that is validated includes
+ the Vault version, edition, build date, and any special prerelease metadata.
+ EOF
+
+ wait_for_cluster_to_have_leader = <<-EOF
+ Wait for a leader election to occur before we proceed with any further quality verification.
+ EOF
+
+ wait_for_seal_rewrap = <<-EOF
+ Wait for the Vault cluster seal rewrap process to complete.
+ EOF
+ }
+}
diff --git a/enos/enos-dev-scenario-pr-replication.hcl b/enos/enos-dev-scenario-pr-replication.hcl
index 54aaa6e6ba..3a81d175d3 100644
--- a/enos/enos-dev-scenario-pr-replication.hcl
+++ b/enos/enos-dev-scenario-pr-replication.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "dev_pr_replication" {
description = <<-EOF
@@ -14,11 +14,13 @@ scenario "dev_pr_replication" {
build and deploy the current branch!
In order to execute this scenario you'll need to install the enos CLI:
- brew tap hashicorp/tap && brew update && brew install hashicorp/tap/enos
+ - $ brew tap hashicorp/tap && brew update && brew install hashicorp/tap/enos
- You'll also need access to an AWS account with an SSH keypair.
- Perform the steps here to get AWS access with Doormat https://eng-handbook.hashicorp.services/internal-tools/enos/common-setup-steps/#authenticate-with-doormat
- Perform the steps here to get an AWS keypair set up: https://eng-handbook.hashicorp.services/internal-tools/enos/common-setup-steps/#set-your-aws-key-pair-name-and-private-key
+ You'll also need access to an AWS account via Doormat, follow the guide here:
+ https://eng-handbook.hashicorp.services/internal-tools/enos/common-setup-steps/#authenticate-with-doormat
+
+ Follow this guide to get an SSH keypair set up in the AWS account:
+ https://eng-handbook.hashicorp.services/internal-tools/enos/common-setup-steps/#set-your-aws-key-pair-name-and-private-key
Please note that this scenario requires several inputs variables to be set in order to function
properly. While not all variants will require all variables, it's suggested that you look over
@@ -69,13 +71,13 @@ scenario "dev_pr_replication" {
EOF
// The matrix is where we define all the baseline combinations that enos can utilize to customize
- // your scenario. By default enos attempts to perform your command an the entire product! Most
- // of the time you'll want to reduce that by passing in a filter.
+ // your scenario. By default enos attempts to perform your command on the entire product of these
+ // possible comginations! Most of the time you'll want to reduce that by passing in a filter.
// Run 'enos scenario list --help' to see more about how filtering scenarios works in enos.
matrix {
arch = ["amd64", "arm64"]
artifact = ["local", "deb", "rpm", "zip"]
- distro = ["ubuntu", "rhel"]
+ distro = ["amzn", "leap", "rhel", "sles", "ubuntu"]
edition = ["ent", "ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
primary_backend = ["consul", "raft"]
primary_seal = ["awskms", "pkcs11", "shamir"]
@@ -117,8 +119,8 @@ scenario "dev_pr_replication" {
// Here we declare all of the providers that we might need for our scenario.
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
// These are variable values that are local to our scenario. They are evaluated after external
@@ -127,19 +129,24 @@ scenario "dev_pr_replication" {
// The enos provider uses different ssh transport configs for different distros (as
// specified in enos-providers.hcl), and we need to be able to access both of those here.
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
// We install vault packages from artifactory. If you wish to use one of these variants you'll
// need to configure your artifactory credentials.
use_artifactory = matrix.artifact == "deb" || matrix.artifact == "rpm"
+ // The IP version to use for the Vault listener and associated things.
+ ip_version = 4
// Zip bundles and local builds don't come with systemd units or any associated configuration.
// When this is true we'll let enos handle this for us.
manage_service = matrix.artifact == "zip" || matrix.artifact == "local"
// If you are using an ent edition, you will need a Vault license. Common convention
// is to store it at ./support/vault.hclic, but you may change this path according
// to your own preference.
- vault_install_dir = matrix.artifact == "zip" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
+ vault_install_dir = matrix.artifact == "zip" || matrix.artifact == "local" ? global.vault_install_dir["bundle"] : global.vault_install_dir["package"]
}
// Begin scenario steps. These are the steps we'll perform to get your cluster up and running.
@@ -336,6 +343,7 @@ scenario "dev_pr_replication" {
ami_id = step.ec2_info.ami_ids[matrix.arch][matrix.distro][global.distro_version[matrix.distro]]
cluster_tag_key = global.vault_tag_key
common_tags = global.tags
+ instance_count = try(var.vault_instance_count, 3)
seal_key_names = step.create_primary_seal_key.resource_names
vpc_id = step.create_vpc.id
}
@@ -365,7 +373,7 @@ scenario "dev_pr_replication" {
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_primary_seal_key.resource_names
@@ -411,7 +419,7 @@ scenario "dev_pr_replication" {
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_secondary_seal_key.resource_names
@@ -445,12 +453,12 @@ scenario "dev_pr_replication" {
variables {
cluster_name = step.create_primary_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
+ hosts = step.create_primary_cluster_backend_targets.hosts
license = matrix.primary_backend == "consul" ? step.read_backend_license.license : null
release = {
edition = var.backend_edition
version = var.dev_consul_version
}
- target_hosts = step.create_primary_cluster_backend_targets.hosts
}
}
@@ -509,16 +517,17 @@ scenario "dev_pr_replication" {
version = var.dev_consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
+ hosts = step.create_primary_cluster_targets.hosts
install_dir = local.vault_install_dir
+ ip_version = local.ip_version
license = step.read_vault_license.license
local_artifact_path = matrix.artifact == "local" ? abspath(var.vault_artifact_path) : null
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
release = matrix.artifact == "zip" ? { version = var.vault_product_version, edition = matrix.edition } : null
seal_attributes = step.create_primary_seal_key.attributes
seal_type = matrix.primary_seal
storage_backend = matrix.primary_backend
- target_hosts = step.create_primary_cluster_targets.hosts
}
}
@@ -548,12 +557,12 @@ scenario "dev_pr_replication" {
variables {
cluster_name = step.create_secondary_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
+ hosts = step.create_secondary_cluster_backend_targets.hosts
license = matrix.secondary_backend == "consul" ? step.read_backend_license.license : null
release = {
edition = var.backend_edition
version = var.dev_consul_version
}
- target_hosts = step.create_secondary_cluster_backend_targets.hosts
}
}
@@ -611,16 +620,17 @@ scenario "dev_pr_replication" {
version = var.dev_consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
+ hosts = step.create_secondary_cluster_targets.hosts
install_dir = local.vault_install_dir
+ ip_version = local.ip_version
license = step.read_vault_license.license
local_artifact_path = matrix.artifact == "local" ? abspath(var.vault_artifact_path) : null
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
release = matrix.artifact == "zip" ? { version = var.vault_product_version, edition = matrix.edition } : null
seal_attributes = step.create_secondary_seal_key.attributes
seal_type = matrix.secondary_seal
storage_backend = matrix.secondary_backend
- target_hosts = step.create_secondary_cluster_targets.hosts
}
}
@@ -638,7 +648,8 @@ scenario "dev_pr_replication" {
}
variables {
- vault_instances = step.create_primary_cluster_targets.hosts
+ hosts = step.create_primary_cluster_targets.hosts
+ vault_addr = step.create_primary_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
}
}
@@ -657,7 +668,8 @@ scenario "dev_pr_replication" {
}
variables {
- vault_instances = step.create_secondary_cluster_targets.hosts
+ hosts = step.create_secondary_cluster_targets.hosts
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
}
}
@@ -676,7 +688,9 @@ scenario "dev_pr_replication" {
}
variables {
- vault_hosts = step.create_primary_cluster_targets.hosts
+ hosts = step.create_primary_cluster_targets.hosts
+ ip_version = local.ip_version
+ vault_addr = step.create_primary_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_primary_cluster.root_token
}
@@ -696,7 +710,9 @@ scenario "dev_pr_replication" {
}
variables {
- vault_hosts = step.create_secondary_cluster_targets.hosts
+ hosts = step.create_secondary_cluster_targets.hosts
+ ip_version = local.ip_version
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_secondary_cluster.root_token
}
@@ -715,9 +731,9 @@ scenario "dev_pr_replication" {
}
variables {
- leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
- leader_private_ip = step.get_primary_cluster_ips.leader_private_ip
- vault_instances = step.create_primary_cluster_targets.hosts
+ hosts = step.create_primary_cluster_targets.hosts
+ leader_host = step.get_primary_cluster_ips.leader_host
+ vault_addr = step.create_primary_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_primary_cluster.root_token
}
@@ -740,10 +756,10 @@ scenario "dev_pr_replication" {
}
variables {
- primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
- primary_leader_private_ip = step.get_primary_cluster_ips.leader_private_ip
- vault_install_dir = local.vault_install_dir
- vault_root_token = step.create_primary_cluster.root_token
+ primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
+ vault_root_token = step.create_primary_cluster.root_token
}
}
@@ -761,6 +777,7 @@ scenario "dev_pr_replication" {
variables {
primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
+ vault_addr = step.create_primary_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_primary_cluster.root_token
}
@@ -778,11 +795,11 @@ scenario "dev_pr_replication" {
}
variables {
- secondary_leader_public_ip = step.get_secondary_cluster_ips.leader_public_ip
- secondary_leader_private_ip = step.get_secondary_cluster_ips.leader_private_ip
- vault_install_dir = local.vault_install_dir
- vault_root_token = step.create_secondary_cluster.root_token
- wrapping_token = step.generate_secondary_token.secondary_token
+ secondary_leader_public_ip = step.get_secondary_cluster_ips.leader_public_ip
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
+ vault_root_token = step.create_secondary_cluster.root_token
+ wrapping_token = step.generate_secondary_token.secondary_token
}
}
@@ -805,10 +822,11 @@ scenario "dev_pr_replication" {
}
variables {
- follower_public_ips = step.get_secondary_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
- vault_unseal_keys = matrix.primary_seal == "shamir" ? step.create_primary_cluster.unseal_keys_hex : step.create_primary_cluster.recovery_keys_hex
- vault_seal_type = matrix.primary_seal == "shamir" ? matrix.primary_seal : matrix.secondary_seal
+ hosts = step.get_secondary_cluster_ips.follower_hosts
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
+ vault_unseal_keys = matrix.primary_seal == "shamir" ? step.create_primary_cluster.unseal_keys_hex : step.create_primary_cluster.recovery_keys_hex
+ vault_seal_type = matrix.primary_seal == "shamir" ? matrix.primary_seal : matrix.secondary_seal
}
}
@@ -826,7 +844,8 @@ scenario "dev_pr_replication" {
}
variables {
- vault_instances = step.create_secondary_cluster_targets.hosts
+ hosts = step.create_secondary_cluster_targets.hosts
+ vault_addr = step.create_primary_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
}
}
@@ -844,11 +863,11 @@ scenario "dev_pr_replication" {
}
variables {
- primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
- primary_leader_private_ip = step.get_primary_cluster_ips.leader_private_ip
- secondary_leader_public_ip = step.get_secondary_cluster_ips.leader_public_ip
- secondary_leader_private_ip = step.get_secondary_cluster_ips.leader_private_ip
- vault_install_dir = local.vault_install_dir
+ ip_version = local.ip_version
+ primary_leader_host = step.get_primary_cluster_ips.leader_host
+ secondary_leader_host = step.get_secondary_cluster_ips.leader_host
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
}
}
diff --git a/enos/enos-dev-scenario-single-cluster.hcl b/enos/enos-dev-scenario-single-cluster.hcl
index b3052584e5..1f413f05d1 100644
--- a/enos/enos-dev-scenario-single-cluster.hcl
+++ b/enos/enos-dev-scenario-single-cluster.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "dev_single_cluster" {
description = <<-EOF
@@ -68,14 +68,14 @@ scenario "dev_single_cluster" {
EOF
// The matrix is where we define all the baseline combinations that enos can utilize to customize
- // your scenario. By default enos attempts to perform your command an the entire product! Most
- // of the time you'll want to reduce that by passing in a filter.
+ // your scenario. By default enos attempts to perform your command on the entire product of these
+ // possible comginations! Most of the time you'll want to reduce that by passing in a filter.
// Run 'enos scenario list --help' to see more about how filtering scenarios works in enos.
matrix {
arch = ["amd64", "arm64"]
artifact = ["local", "deb", "rpm", "zip"]
backend = ["consul", "raft"]
- distro = ["ubuntu", "rhel"]
+ distro = ["amzn", "leap", "rhel", "sles", "ubuntu"]
edition = ["ce", "ent", "ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
seal = ["awskms", "pkcs11", "shamir"]
@@ -107,10 +107,12 @@ scenario "dev_single_cluster" {
terraform = terraform.default
// Here we declare all of the providers that we might need for our scenario.
+ // There are two different configurations for the Enos provider, each specifying
+ // SSH transport configs for different Linux distros.
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
// These are variable values that are local to our scenario. They are evaluated after external
@@ -119,19 +121,24 @@ scenario "dev_single_cluster" {
// The enos provider uses different ssh transport configs for different distros (as
// specified in enos-providers.hcl), and we need to be able to access both of those here.
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
// We install vault packages from artifactory. If you wish to use one of these variants you'll
// need to configure your artifactory credentials.
use_artifactory = matrix.artifact == "deb" || matrix.artifact == "rpm"
+ // The IP version to use for the Vault listener and associated things.
+ ip_version = 4
// Zip bundles and local builds don't come with systemd units or any associated configuration.
// When this is true we'll let enos handle this for us.
manage_service = matrix.artifact == "zip" || matrix.artifact == "local"
// If you are using an ent edition, you will need a Vault license. Common convention
// is to store it at ./support/vault.hclic, but you may change this path according
// to your own preference.
- vault_install_dir = matrix.artifact == "zip" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
+ vault_install_dir = matrix.artifact == "zip" || matrix.artifact == "local" ? global.vault_install_dir["bundle"] : global.vault_install_dir["package"]
}
// Begin scenario steps. These are the steps we'll perform to get your cluster up and running.
@@ -168,7 +175,6 @@ scenario "dev_single_cluster" {
variant.
EOF
module = matrix.artifact == "local" ? "build_local" : local.use_artifactory ? "build_artifactory_package" : "build_crt"
- skip_step = matrix.artifact == "zip"
variables {
// Used for all modules
@@ -335,7 +341,7 @@ scenario "dev_single_cluster" {
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_seal_key.resource_names
@@ -369,12 +375,12 @@ scenario "dev_single_cluster" {
variables {
cluster_name = step.create_vault_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
+ hosts = step.create_vault_cluster_backend_targets.hosts
license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
release = {
edition = var.backend_edition
version = var.dev_consul_version
}
- target_hosts = step.create_vault_cluster_backend_targets.hosts
}
}
@@ -433,16 +439,17 @@ scenario "dev_single_cluster" {
version = var.dev_consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
+ hosts = step.create_vault_cluster_targets.hosts
install_dir = local.vault_install_dir
+ ip_version = local.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
local_artifact_path = matrix.artifact == "local" ? abspath(var.vault_artifact_path) : null
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
release = matrix.artifact == "zip" ? { version = var.vault_product_version, edition = matrix.edition } : null
seal_attributes = step.create_seal_key.attributes
seal_type = matrix.seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
@@ -460,7 +467,7 @@ scenario "dev_single_cluster" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "private_ips" {
diff --git a/enos/enos-dev-variables.hcl b/enos/enos-dev-variables.hcl
index 1184748f04..ed7ab24076 100644
--- a/enos/enos-dev-variables.hcl
+++ b/enos/enos-dev-variables.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
variable "dev_build_local_ui" {
type = bool
diff --git a/enos/enos-globals.hcl b/enos/enos-globals.hcl
index 5ca6dd86f8..a17bc357f7 100644
--- a/enos/enos-globals.hcl
+++ b/enos/enos-globals.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
globals {
archs = ["amd64", "arm64"]
@@ -16,20 +16,143 @@ globals {
"ent.hsm.fips1402" = ["ui", "enterprise", "cgo", "hsm", "fips", "fips_140_2", "ent.hsm.fips1402"]
}
config_modes = ["env", "file"]
+ consul_editions = ["ce", "ent"]
consul_versions = ["1.14.11", "1.15.7", "1.16.3", "1.17.0"]
- distros = ["ubuntu", "rhel"]
- distro_version = {
- "rhel" = var.rhel_distro_version
- "ubuntu" = var.ubuntu_distro_version
- }
- editions = ["ce", "ent", "ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
- packages = ["jq"]
+ distros = ["amzn", "leap", "rhel", "sles", "ubuntu"]
+ // Different distros may require different packages, or use different aliases for the same package
distro_packages = {
- ubuntu = ["netcat"]
- rhel = ["nc"]
+ amzn = {
+ "2" = ["nc"]
+ "2023" = ["nc"]
+ }
+ leap = {
+ "15.6" = ["netcat", "openssl"]
+ }
+ rhel = {
+ "8.10" = ["nc"]
+ "9.4" = ["nc"]
+ }
+ sles = {
+ // When installing Vault RPM packages on a SLES AMI, the openssl package provided
+ // isn't named "openssl, which rpm doesn't know how to handle. Therefore we add the
+ // "correctly" named one in our package installation before installing Vault.
+ "15.6" = ["netcat-openbsd", "openssl"]
+ }
+ ubuntu = {
+ "20.04" = ["netcat"]
+ "22.04" = ["netcat"]
+ "24.04" = ["netcat-openbsd"]
+ }
+ }
+ distro_version = {
+ amzn = var.distro_version_amzn
+ leap = var.distro_version_leap
+ rhel = var.distro_version_rhel
+ sles = var.distro_version_sles
+ ubuntu = var.distro_version_ubuntu
+ }
+ editions = ["ce", "ent", "ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
+ enterprise_editions = [for e in global.editions : e if e != "ce"]
+ ip_versions = ["4", "6"]
+ package_manager = {
+ "amzn" = "yum"
+ "leap" = "zypper"
+ "rhel" = "yum"
+ "sles" = "zypper"
+ "ubuntu" = "apt"
+ }
+ packages = ["jq"]
+ // Ports that we'll open up for ingress in the security group for all target machines.
+ // Port protocol maps to the IpProtocol schema: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_IpPermission.html
+ ports = {
+ ssh : {
+ description = "SSH"
+ port = 22
+ protocol = "tcp"
+ },
+ vault_agent : {
+ description = "Vault Agent"
+ port = 8100
+ protocol = "tcp"
+ },
+ vault_proxy : {
+ description = "Vault Proxy"
+ port = 8101
+ protocol = "tcp"
+ },
+ vault_listener : {
+ description = "Vault Addr listener"
+ port = 8200
+ protocol = "tcp"
+ },
+ vault_cluster : {
+ description = "Vault Cluster listener"
+ port = 8201
+ protocol = "tcp"
+ },
+ consul_rpc : {
+ description = "Consul internal communication"
+ port = 8300
+ protocol = "tcp"
+ },
+ consul_serf_lan_tcp : {
+ description = "Consul Serf LAN TCP"
+ port = 8301
+ protocol = "tcp"
+ },
+ consul_serf_lan_udp : {
+ description = "Consul Serf LAN UDP"
+ port = 8301
+ protocol = "udp"
+ },
+ consul_serf_wan_tcp : {
+ description = "Consul Serf WAN TCP"
+ port = 8302
+ protocol = "tcp"
+ },
+ consul_serf_wan_udp : {
+ description = "Consul Serf WAN UDP"
+ port = 8302
+ protocol = "udp"
+ },
+ consul_http : {
+ description = "Consul HTTP API"
+ port = 8500
+ protocol = "tcp"
+ },
+ consul_https : {
+ description = "Consul HTTPS API"
+ port = 8501
+ protocol = "tcp"
+ },
+ consul_grpc : {
+ description = "Consul gRPC API"
+ port = 8502
+ protocol = "tcp"
+ },
+ consul_grpc_tls : {
+ description = "Consul gRPC TLS API"
+ port = 8503
+ protocol = "tcp"
+ },
+ consul_dns_tcp : {
+ description = "Consul TCP DNS Server"
+ port = 8600
+ protocol = "tcp"
+ },
+ consul_dns_udp : {
+ description = "Consul UDP DNS Server"
+ port = 8600
+ protocol = "udp"
+ },
}
sample_attributes = {
- aws_region = ["us-east-1", "us-west-2"]
+ aws_region = ["us-east-1", "us-west-2"]
+ distro_version_amzn = ["2023"]
+ distro_version_leap = ["15.6"]
+ distro_version_rhel = ["8.10", "9.4"]
+ distro_version_sles = ["15.6"]
+ distro_version_ubuntu = ["20.04", "24.04"]
}
seals = ["awskms", "pkcs11", "shamir"]
tags = merge({
@@ -37,15 +160,22 @@ globals {
"Project" : "Enos",
"Environment" : "ci"
}, var.tags)
+ // This reads the VERSION file, strips any pre-release metadata, and selects only initial
+ // versions that are less than our current version. E.g. A VERSION file containing 1.17.0-beta2
+ // would render: semverconstraint(v, "<1.17.0-0")
+ upgrade_version_stripped = join("-", [split("-", chomp(file("../version/VERSION")))[0], "0"])
// NOTE: when backporting, make sure that our initial versions are less than that
// release branch's version. Also beware if adding versions below 1.11.x. Some scenarios
// that use this global might not work as expected with earlier versions. Below 1.8.x is
// not supported in any way.
- upgrade_initial_versions = ["1.11.12", "1.12.11", "1.13.11", "1.14.7", "1.15.3"]
- vault_install_dir_packages = {
- rhel = "/bin"
- ubuntu = "/usr/bin"
+ upgrade_all_initial_versions_ce = ["1.8.12", "1.9.10", "1.10.11", "1.11.12", "1.12.11", "1.13.13", "1.14.10", "1.15.6", "1.16.3", "1.17.0"]
+ upgrade_all_initial_versions_ent = ["1.8.12", "1.9.10", "1.10.11", "1.11.12", "1.12.11", "1.13.13", "1.14.13", "1.15.10", "1.16.4", "1.17.0"]
+ upgrade_initial_versions_ce = [for v in global.upgrade_all_initial_versions_ce : v if semverconstraint(v, "<${global.upgrade_version_stripped}")]
+ upgrade_initial_versions_ent = [for v in global.upgrade_all_initial_versions_ent : v if semverconstraint(v, "<${global.upgrade_version_stripped}")]
+ vault_install_dir = {
+ bundle = "/opt/vault/bin"
+ package = "/usr/bin"
}
vault_license_path = abspath(var.vault_license_path != null ? var.vault_license_path : joinpath(path.root, "./support/vault.hclic"))
- vault_tag_key = "Type" // enos_vault_start expects Type as the tag key
+ vault_tag_key = "vault-cluster"
}
diff --git a/enos/enos-modules.hcl b/enos/enos-modules.hcl
index 396d54d909..973d87c332 100644
--- a/enos/enos-modules.hcl
+++ b/enos/enos-modules.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
module "autopilot_upgrade_storageconfig" {
source = "./modules/autopilot_upgrade_storageconfig"
@@ -114,7 +114,7 @@ module "stop_vault" {
source = "./modules/stop_vault"
}
-# create target instances using ec2:CreateFleet
+// create target instances using ec2:CreateFleet
module "target_ec2_fleet" {
source = "./modules/target_ec2_fleet"
@@ -123,25 +123,27 @@ module "target_ec2_fleet" {
ssh_keypair = var.aws_ssh_keypair_name
}
-# create target instances using ec2:RunInstances
+// create target instances using ec2:RunInstances
module "target_ec2_instances" {
source = "./modules/target_ec2_instances"
- common_tags = var.tags
- project_name = var.project_name
- ssh_keypair = var.aws_ssh_keypair_name
+ common_tags = var.tags
+ ports_ingress = values(global.ports)
+ project_name = var.project_name
+ ssh_keypair = var.aws_ssh_keypair_name
}
-# don't create instances but satisfy the module interface
+// don't create instances but satisfy the module interface
module "target_ec2_shim" {
source = "./modules/target_ec2_shim"
- common_tags = var.tags
- project_name = var.project_name
- ssh_keypair = var.aws_ssh_keypair_name
+ common_tags = var.tags
+ ports_ingress = values(global.ports)
+ project_name = var.project_name
+ ssh_keypair = var.aws_ssh_keypair_name
}
-# create target instances using ec2:RequestSpotFleet
+// create target instances using ec2:RequestSpotFleet
module "target_ec2_spot_fleet" {
source = "./modules/target_ec2_spot_fleet"
@@ -153,36 +155,34 @@ module "target_ec2_spot_fleet" {
module "vault_agent" {
source = "./modules/vault_agent"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
+ vault_agent_port = global.ports["vault_agent"]["port"]
}
module "vault_proxy" {
source = "./modules/vault_proxy"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
+ vault_proxy_port = global.ports["vault_proxy"]["port"]
}
module "vault_verify_agent_output" {
source = "./modules/vault_verify_agent_output"
-
- vault_instance_count = var.vault_instance_count
}
module "vault_cluster" {
source = "./modules/vault_cluster"
- install_dir = var.vault_install_dir
- consul_license = var.backend_license_path == null ? null : file(abspath(var.backend_license_path))
- log_level = var.vault_log_level
+ install_dir = var.vault_install_dir
+ consul_license = var.backend_license_path == null ? null : file(abspath(var.backend_license_path))
+ cluster_tag_key = global.vault_tag_key
+ log_level = var.vault_log_level
}
module "vault_get_cluster_ips" {
source = "./modules/vault_get_cluster_ips"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_raft_remove_peer" {
@@ -211,15 +211,13 @@ module "vault_test_ui" {
module "vault_unseal_nodes" {
source = "./modules/vault_unseal_nodes"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_upgrade" {
source = "./modules/vault_upgrade"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_verify_autopilot" {
@@ -227,48 +225,39 @@ module "vault_verify_autopilot" {
vault_autopilot_upgrade_status = "await-server-removal"
vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
}
module "vault_verify_raft_auto_join_voter" {
source = "./modules/vault_verify_raft_auto_join_voter"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
+ vault_cluster_addr_port = global.ports["vault_cluster"]["port"]
}
module "vault_verify_undo_logs" {
source = "./modules/vault_verify_undo_logs"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_verify_default_lcq" {
source = "./modules/vault_verify_default_lcq"
vault_autopilot_default_max_leases = "300000"
- vault_instance_count = var.vault_instance_count
}
module "vault_verify_replication" {
source = "./modules/vault_verify_replication"
-
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
}
module "vault_verify_ui" {
source = "./modules/vault_verify_ui"
-
- vault_instance_count = var.vault_instance_count
}
module "vault_verify_unsealed" {
source = "./modules/vault_verify_unsealed"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_setup_perf_primary" {
@@ -280,8 +269,7 @@ module "vault_setup_perf_primary" {
module "vault_verify_read_data" {
source = "./modules/vault_verify_read_data"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_verify_performance_replication" {
@@ -293,15 +281,13 @@ module "vault_verify_performance_replication" {
module "vault_verify_version" {
source = "./modules/vault_verify_version"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_verify_write_data" {
source = "./modules/vault_verify_write_data"
- vault_install_dir = var.vault_install_dir
- vault_instance_count = var.vault_instance_count
+ vault_install_dir = var.vault_install_dir
}
module "vault_wait_for_leader" {
diff --git a/enos/enos-providers.hcl b/enos/enos-providers.hcl
index 472589f4a1..89c79bd100 100644
--- a/enos/enos-providers.hcl
+++ b/enos/enos-providers.hcl
@@ -1,11 +1,12 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
provider "aws" "default" {
region = var.aws_region
}
-provider "enos" "rhel" {
+// This default SSH user is used in RHEL, Amazon Linux, SUSE, and Leap distros
+provider "enos" "ec2_user" {
transport = {
ssh = {
user = "ec2-user"
@@ -14,6 +15,7 @@ provider "enos" "rhel" {
}
}
+// This default SSH user is used in the Ubuntu distro
provider "enos" "ubuntu" {
transport = {
ssh = {
diff --git a/enos/enos-qualities.hcl b/enos/enos-qualities.hcl
new file mode 100644
index 0000000000..639cf027cd
--- /dev/null
+++ b/enos/enos-qualities.hcl
@@ -0,0 +1,501 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+quality "consul_api_agent_host_read" {
+ description = "The /v1/agent/host Consul API returns host info for each node in the cluster"
+}
+
+quality "consul_api_health_node_read" {
+ description = <<-EOF
+ The /v1/health/node/ Consul API returns health info for each node in the cluster
+ EOF
+}
+
+quality "consul_api_operator_raft_config_read" {
+ description = "The /v1/operator/raft/configuration Consul API returns raft info for the cluster"
+}
+
+quality "consul_autojoin_aws" {
+ description = "The Consul cluster auto-joins with AWS tag discovery"
+}
+
+quality "consul_cli_validate" {
+ description = "The 'consul validate' command validates the Consul configuration"
+}
+
+quality "consul_config_file" {
+ description = "Consul starts when configured with a configuration file"
+}
+
+quality "consul_ha_leader_election" {
+ description = "The Consul cluster elects a leader node on start up"
+}
+
+quality "consul_health_state_passing_read_nodes_minimum" {
+ description = <<-EOF
+ The Consul cluster meets the minimum of number of healthy nodes according to the
+ /v1/health/state/passing Consul API
+ EOF
+}
+
+quality "consul_operator_raft_configuration_read_voters_minimum" {
+ description = <<-EOF
+ The Consul cluster meets the minimum number of raft voters according to the
+ /v1/operator/raft/configuration Consul API
+ EOF
+}
+
+quality "consul_service_start_client" {
+ description = "The Consul service starts in client mode"
+}
+
+quality "consul_service_start_server" {
+ description = "The Consul service starts in server mode"
+}
+
+quality "consul_service_systemd_notified" {
+ description = "The Consul binary notifies systemd when the service is active"
+}
+
+quality "consul_service_systemd_unit" {
+ description = "The 'consul.service' systemd unit starts the service"
+}
+
+quality "vault_agent_auto_auth_approle" {
+ description = <<-EOF
+ Vault running in Agent mode utilizes the approle auth method to do auto-auth via a role and
+ read secrets from a file source
+ EOF
+}
+
+quality "vault_agent_log_template" {
+ description = global.description.verify_agent_output
+}
+
+quality "vault_api_sys_auth_userpass_user_write" {
+ description = "The v1/sys/auth/userpass/users/ Vault API associates a policy with a user"
+}
+
+quality "vault_api_sys_config_read" {
+ description = <<-EOF
+ The v1/sys/config/sanitized Vault API returns sanitized configuration which matches our given
+ configuration
+ EOF
+}
+
+quality "vault_api_sys_ha_status_read" {
+ description = "The v1/sys/ha-status Vault API returns the HA status of the cluster"
+}
+
+quality "vault_api_sys_health_read" {
+ description = <<-EOF
+ The v1/sys/health Vault API returns the correct codes depending on the replication and
+ 'seal-status' of the cluster
+ EOF
+}
+
+quality "vault_api_sys_host_info_read" {
+ description = "The v1/sys/host-info Vault API returns the host info for each node in the cluster"
+}
+
+quality "vault_api_sys_leader_read" {
+ description = "The v1/sys/leader Vault API returns the cluster leader info"
+}
+
+quality "vault_api_sys_metrics_vault_core_replication_write_undo_logs_enabled" {
+ description = <<-EOF
+ The v1/sys/metrics Vault API returns metrics and verifies that
+ 'Gauges[vault.core.replication.write_undo_logs]' is enabled
+ EOF
+}
+
+quality "vault_api_sys_policy_write" {
+ description = "The v1/sys/policy Vault API writes a superuser policy"
+}
+
+quality "vault_api_sys_quotas_lease_count_read_max_leases_default" {
+ description = <<-EOF
+ The v1/sys/quotas/lease-count/default Vault API returns the lease 'count' and 'max_leases' is
+ set to 300,000
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_primary_enable_write" {
+ description = <<-EOF
+ The v1/sys/replication/performance/primary/enable Vault API enables performance replication
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_primary_secondary_token_write" {
+ description = <<-EOF
+ The v1/sys/replication/performance/primary/secondary-token Vault API configures the replication
+ token
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_secondary_enable_write" {
+ description = <<-EOF
+ The v1/sys/replication/performance/secondary/enable Vault API enables performance replication
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_read_connection_status_connected" {
+ description = <<-EOF
+ The v1/sys/replication/performance/status Vault API returns status info and the
+ 'connection_status' is correct for the given node
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_status_known_primary_cluster_addrs" {
+ description = <<-EOF
+ The v1/sys/replication/performance/status Vault API returns the replication status and
+ 'known_primary_cluster_address' is the expected primary cluster leader
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_status_read" {
+ description = <<-EOF
+ The v1/sys/replication/performance/status Vault API returns the performance replication status
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_status_read_cluster_address" {
+ description = <<-EOF
+ The v1/sys/replication/performance/status Vault API returns the performance replication status
+ and the '{primaries,secondaries}[*].cluster_address' is correct for the given node
+ EOF
+}
+
+quality "vault_api_sys_replication_performance_status_read_state_not_idle" {
+ description = <<-EOF
+ The v1/sys/replication/performance/status Vault API returns the performance replication status
+ and the state is not idle
+ EOF
+}
+
+quality "vault_api_sys_replication_status_read" {
+ description = <<-EOF
+ The v1/sys/replication/status Vault API returns the performance replication status of the
+ cluster
+ EOF
+}
+
+quality "vault_api_sys_seal_status_api_read_matches_sys_health" {
+ description = <<-EOF
+ The v1/sys/seal-status Vault API and v1/sys/health Vault API agree on the health of each node
+ and the cluster
+ EOF
+}
+
+quality "vault_api_sys_sealwrap_rewrap_read_entries_processed_eq_entries_succeeded_post_rewrap" {
+ description = global.description.verify_seal_rewrap_entries_processed_eq_entries_succeeded_post_rewrap
+}
+
+quality "vault_api_sys_sealwrap_rewrap_read_entries_processed_gt_zero_post_rewrap" {
+ description = global.description.verify_seal_rewrap_entries_processed_is_gt_zero_post_rewrap
+}
+
+quality "vault_api_sys_sealwrap_rewrap_read_is_running_false_post_rewrap" {
+ description = global.description.verify_seal_rewrap_is_running_false_post_rewrap
+}
+
+quality "vault_api_sys_sealwrap_rewrap_read_no_entries_fail_during_rewrap" {
+ description = global.description.verify_seal_rewrap_no_entries_fail_during_rewrap
+}
+
+quality "vault_api_sys_step_down_steps_down" {
+ description = <<-EOF
+ The v1/sys/step-down Vault API forces the cluster leader to step down and intiates a new leader
+ election
+ EOF
+}
+
+quality "vault_api_sys_storage_raft_autopilot_configuration_read" {
+ description = <<-EOF
+ The /sys/storage/raft/autopilot/configuration Vault API returns the autopilot configuration of
+ the cluster
+ EOF
+}
+
+quality "vault_api_sys_storage_raft_autopilot_state_read" {
+ description = <<-EOF
+ The v1/sys/storage/raft/autopilot/state Vault API returns the raft autopilot state of the
+ cluster
+ EOF
+}
+
+quality "vault_api_sys_storage_raft_autopilot_upgrade_info_read_status_matches" {
+ description = <<-EOF
+ The v1/sys/storage/raft/autopilot/state Vault API returns the raft autopilot state and the
+ 'upgrade_info.status' matches our expected state
+ EOF
+}
+
+quality "vault_api_sys_storage_raft_autopilot_upgrade_info_target_version_read_matches_candidate" {
+ description = <<-EOF
+ The v1/sys/storage/raft/autopilot/state Vault API returns the raft autopilot state and the
+ 'upgrade_info.target_version' matches the the candidate version
+ EOF
+}
+
+quality "vault_api_sys_storage_raft_configuration_read" {
+ description = <<-EOF
+ The v1/sys/storage/raft/configuration Vault API returns the raft configuration of the cluster
+ EOF
+}
+
+quality "vault_api_sys_storage_raft_remove_peer_write_removes_peer" {
+ description = <<-EOF
+ The v1/sys/storage/raft/remove-peer Vault API removes the desired node from the raft sub-system
+ EOF
+}
+
+quality "vault_api_sys_version_history_keys" {
+ description = <<-EOF
+ The v1/sys/version-history Vault API returns the cluster version history and the 'keys' data
+ includes our target version
+ EOF
+}
+
+quality "vault_api_sys_version_history_key_info" {
+ description = <<-EOF
+ The v1/sys/version-history Vault API returns the cluster version history and the
+ 'key_info["$expected_version]' data is present for the expected version and the 'build_date'
+ matches the expected build_date.
+ EOF
+}
+
+quality "vault_artifact_bundle" {
+ description = "The candidate binary packaged as a zip bundle is used for testing"
+}
+
+quality "vault_artifact_deb" {
+ description = "The candidate binary packaged as a deb package is used for testing"
+}
+
+quality "vault_artifact_rpm" {
+ description = "The candidate binary packaged as an rpm package is used for testing"
+}
+
+quality "vault_audit_log" {
+ description = "The Vault audit sub-system is enabled with the log and writes to a log"
+}
+
+quality "vault_audit_socket" {
+ description = "The Vault audit sub-system is enabled with the socket and writes to a socket"
+}
+
+quality "vault_audit_syslog" {
+ description = "The Vault audit sub-system is enabled with the syslog and writes to syslog"
+}
+
+quality "vault_auto_unseals_after_autopilot_upgrade" {
+ description = "Vault auto-unseals after upgrading the cluster with autopilot"
+}
+
+quality "vault_autojoins_new_nodes_into_initialized_cluster" {
+ description = "Vault sucessfully auto-joins new nodes into an existing cluster"
+}
+
+quality "vault_autojoin_aws" {
+ description = "Vault auto-joins nodes using AWS tag discovery"
+}
+
+quality "vault_autopilot_upgrade_leader_election" {
+ description = <<-EOF
+ Vault elects a new leader after upgrading the cluster with autopilot
+ EOF
+}
+
+quality "vault_cli_audit_enable" {
+ description = "The 'vault audit enable' command enables audit devices"
+}
+
+quality "vault_cli_auth_enable_approle" {
+ description = "The 'vault auth enable approle' command enables the approle auth method"
+}
+
+quality "vault_cli_operator_members" {
+ description = "The 'vault operator members' command returns the expected list of members"
+}
+
+quality "vault_cli_operator_raft_remove_peer" {
+ description = "The 'vault operator remove-peer' command removes the desired node"
+}
+
+quality "vault_cli_operator_step_down" {
+ description = "The 'vault operator step-down' command forces the cluster leader to step down"
+}
+
+quality "vault_cli_policy_write" {
+ description = "The 'vault policy write' command writes a policy"
+}
+
+quality "vault_cli_status_exit_code" {
+ description = <<-EOF
+ The 'vault status' command exits with the correct code depending on expected seal status
+ EOF
+}
+
+quality "vault_cluster_upgrade_in_place" {
+ description = <<-EOF
+ Vault starts with existing data and configuration in-place migrates the data
+ EOF
+}
+
+quality "vault_config_env_variables" {
+ description = "Vault starts when configured primarily with environment variables"
+}
+
+quality "vault_config_file" {
+ description = "Vault starts when configured primarily with a configuration file"
+}
+
+quality "vault_config_log_level" {
+ description = "The 'log_level' config stanza modifies its log level"
+}
+
+quality "vault_config_multiseal_is_toggleable" {
+ description = <<-EOF
+ The Vault Cluster can be configured with a single unseal method regardless of the
+ 'enable_multiseal' config value
+ EOF
+}
+
+quality "vault_init" {
+ description = "Vault initializes the cluster with the given seal parameters"
+}
+
+quality "vault_license_required_ent" {
+ description = "Vault Enterprise requires a license in order to start"
+}
+
+quality "vault_listener_ipv4" {
+ description = "Vault operates on ipv4 TCP listeners"
+}
+
+quality "vault_listener_ipv6" {
+ description = "Vault operates on ipv6 TCP listeners"
+}
+
+quality "vault_mount_auth" {
+ description = "Vault mounts the auth engine"
+}
+
+quality "vault_mount_kv" {
+ description = "Vault mounts the kv engine"
+}
+
+quality "vault_multiseal_enable" {
+ description = <<-EOF
+ The Vault Cluster starts with 'enable_multiseal' and multiple auto-unseal methods.
+ EOF
+}
+
+quality "vault_proxy_auto_auth_approle" {
+ description = <<-EOF
+ Vault Proxy utilizes the approle auth method to to auto auth via a roles and secrets from file.
+ EOF
+}
+
+quality "vault_proxy_cli_access" {
+ description = <<-EOF
+ The Vault CLI accesses tokens through the Vault proxy without a VAULT_TOKEN available
+ EOF
+}
+
+quality "vault_raft_voters" {
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+}
+
+quality "vault_replication_ce_disabled" {
+ description = "Replication is not enabled for CE editions"
+}
+
+quality "vault_replication_ent_dr_available" {
+ description = "DR replication is available on Enterprise"
+}
+
+quality "vault_replication_ent_pr_available" {
+ description = "PR replication is available on Enterprise"
+}
+
+quality "vault_seal_awskms" {
+ description = "Vault auto-unseals with the awskms seal"
+}
+
+quality "vault_seal_shamir" {
+ description = <<-EOF
+ Vault manually unseals with the shamir seal when given the expected number of 'key_shares'
+ EOF
+}
+
+quality "vault_seal_pkcs11" {
+ description = "Vault auto-unseals with the pkcs11 seal"
+}
+
+quality "vault_secrets_auth_user_policy_write" {
+ description = "Vault creates auth user policies with the root token"
+}
+
+quality "vault_secrets_kv_read" {
+ description = "Vault kv secrets engine data is readable"
+}
+
+quality "vault_secrets_kv_write" {
+ description = "Vault kv secrets engine data is writable"
+}
+
+quality "vault_service_restart" {
+ description = "Vault restarts with existing configuration"
+}
+
+quality "vault_service_start" {
+ description = "Vault starts with the configuration"
+}
+
+quality "vault_service_systemd_notified" {
+ description = "The Vault binary notifies systemd when the service is active"
+}
+
+quality "vault_service_systemd_unit" {
+ description = "The 'vault.service' systemd unit starts the service"
+}
+
+quality "vault_status_seal_type" {
+ description = global.description.verify_seal_type
+}
+
+quality "vault_storage_backend_consul" {
+ description = "Vault operates using Consul for storage"
+}
+
+quality "vault_storage_backend_raft" {
+ description = "Vault operates using integrated Raft storage"
+}
+
+quality "vault_ui_assets" {
+ description = global.description.verify_ui
+}
+
+quality "vault_ui_test" {
+ description = <<-EOF
+ The Vault Web UI test suite runs against a live Vault server with the embedded static assets
+ EOF
+}
+
+quality "vault_unseal_ha_leader_election" {
+ description = "Vault performs a leader election after it is unsealed"
+}
+
+quality "vault_version_build_date" {
+ description = "Vault's reported build date matches our expectations"
+}
+
+quality "vault_version_edition" {
+ description = "Vault's reported edition matches our expectations"
+}
+
+quality "vault_version_release" {
+ description = "Vault's reported release version matches our expectations"
+}
diff --git a/enos/enos-samples-ce-build.hcl b/enos/enos-samples-ce-build.hcl
index 2c3cae0f77..981c248669 100644
--- a/enos/enos-samples-ce-build.hcl
+++ b/enos/enos-samples-ce-build.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
sample "build_ce_linux_amd64_deb" {
attributes = global.sample_attributes
@@ -97,7 +97,7 @@ sample "build_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -107,7 +107,7 @@ sample "build_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -117,7 +117,7 @@ sample "build_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -127,7 +127,7 @@ sample "build_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -141,7 +141,7 @@ sample "build_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -151,7 +151,7 @@ sample "build_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -161,7 +161,7 @@ sample "build_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -171,7 +171,7 @@ sample "build_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["crt"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
exclude {
@@ -191,6 +191,7 @@ sample "build_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["crt"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -200,6 +201,7 @@ sample "build_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["crt"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -209,6 +211,7 @@ sample "build_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["crt"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -218,6 +221,7 @@ sample "build_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["crt"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -231,6 +235,7 @@ sample "build_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -240,6 +245,7 @@ sample "build_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -249,6 +255,7 @@ sample "build_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -258,6 +265,7 @@ sample "build_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["crt"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
diff --git a/enos/enos-samples-ce-release.hcl b/enos/enos-samples-ce-release.hcl
index 4e3d9acdf2..634b4faeed 100644
--- a/enos/enos-samples-ce-release.hcl
+++ b/enos/enos-samples-ce-release.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
sample "release_ce_linux_amd64_deb" {
attributes = global.sample_attributes
@@ -97,7 +97,7 @@ sample "release_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -107,7 +107,7 @@ sample "release_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -117,7 +117,7 @@ sample "release_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -127,7 +127,7 @@ sample "release_ce_linux_arm64_rpm" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -141,7 +141,7 @@ sample "release_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -151,7 +151,7 @@ sample "release_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -161,7 +161,7 @@ sample "release_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -171,7 +171,7 @@ sample "release_ce_linux_amd64_rpm" {
arch = ["amd64"]
artifact_source = ["artifactory"]
artifact_type = ["package"]
- distro = ["rhel"]
+ distro = ["amzn", "leap", "rhel", "sles"]
edition = ["ce"]
}
}
@@ -185,6 +185,7 @@ sample "release_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["artifactory"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -194,6 +195,7 @@ sample "release_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["artifactory"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -203,6 +205,7 @@ sample "release_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["artifactory"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -212,6 +215,7 @@ sample "release_ce_linux_amd64_zip" {
arch = ["amd64"]
artifact_type = ["bundle"]
artifact_source = ["artifactory"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -225,6 +229,7 @@ sample "release_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -234,6 +239,7 @@ sample "release_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -243,6 +249,7 @@ sample "release_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
@@ -252,6 +259,7 @@ sample "release_ce_linux_arm64_zip" {
arch = ["arm64"]
artifact_source = ["artifactory"]
artifact_type = ["bundle"]
+ distro = ["amzn", "ubuntu"]
edition = ["ce"]
}
}
diff --git a/enos/enos-scenario-agent.hcl b/enos/enos-scenario-agent.hcl
index f87f29785d..d8c60ccdc2 100644
--- a/enos/enos-scenario-agent.hcl
+++ b/enos/enos-scenario-agent.hcl
@@ -1,34 +1,58 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "agent" {
+ description = <<-EOF
+ The agent scenario verifies Vault when running in Agent mode. The build can be a local branch,
+ any CRT built Vault artifact saved to the local machine, or any CRT built Vault artifact in the
+ stable channel in Artifactory.
+
+ The scenario creates a new Vault Cluster using the candidate build and then runs the same Vault
+ build in Agent mode and verifies behavior against the Vault cluster. The scenario also performs
+ standard baseline verification that is not specific to the Agent mode deployment.
+
+ If you want to use the 'distro:leap' variant you must first accept SUSE's terms for the AWS
+ account. To verify that your account has agreed, sign-in to your AWS through Doormat,
+ and visit the following links to verify your subscription or subscribe:
+ arm64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+ amd64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+ EOF
+
matrix {
arch = global.archs
artifact_source = global.artifact_sources
artifact_type = global.artifact_types
backend = global.backends
config_mode = global.config_modes
+ consul_edition = global.consul_editions
consul_version = global.consul_versions
distro = global.distros
edition = global.editions
+ ip_version = global.ip_versions
seal = global.seals
- # Our local builder always creates bundles
+ // Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}
- # HSM and FIPS 140-2 are only supported on amd64
- exclude {
- arch = ["arm64"]
- edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
- }
-
- # PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
+ // PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
exclude {
seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
+ }
+
+ // softhsm packages not available for leap/sles.
+ exclude {
+ seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ // Testing in IPV6 mode is currently implemented for integrated Raft storage only
+ exclude {
+ ip_version = ["6"]
+ backend = ["consul"]
}
}
@@ -36,27 +60,25 @@ scenario "agent" {
terraform = terraform.default
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
locals {
artifact_path = matrix.artifact_source != "artifactory" ? abspath(var.vault_artifact_path) : null
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
- manage_service = matrix.artifact_type == "bundle"
- vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
- }
-
- step "get_local_metadata" {
- skip_step = matrix.artifact_source != "local"
- module = module.get_local_metadata
+ manage_service = matrix.artifact_type == "bundle"
}
step "build_vault" {
- module = "build_${matrix.artifact_source}"
+ description = global.description.build_vault
+ module = "build_${matrix.artifact_source}"
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : global.build_tags[matrix.edition]
@@ -77,22 +99,26 @@ scenario "agent" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = global.tags
+ ip_version = matrix.ip_version
}
}
// This step reads the contents of the backend license if we're using a Consul backend and
- // the edition is "ent".
+ // an "ent" Consul edition.
step "read_backend_license" {
- skip_step = matrix.backend == "raft" || var.backend_edition == "ce"
- module = module.read_license
+ description = global.description.read_backend_license
+ skip_step = matrix.backend == "raft" || matrix.consul_edition == "ce"
+ module = module.read_license
variables {
file_name = global.backend_license_path
@@ -100,8 +126,9 @@ scenario "agent" {
}
step "read_vault_license" {
- skip_step = matrix.edition == "ce"
- module = module.read_license
+ description = global.description.read_vault_license
+ skip_step = matrix.edition == "ce"
+ module = module.read_license
variables {
file_name = global.vault_license_path
@@ -109,8 +136,9 @@ scenario "agent" {
}
step "create_seal_key" {
- module = "seal_${matrix.seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -123,8 +151,9 @@ scenario "agent" {
}
step "create_vault_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
@@ -140,15 +169,16 @@ scenario "agent" {
}
step "create_vault_cluster_backend_targets" {
- module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_seal_key.resource_names
@@ -157,7 +187,8 @@ scenario "agent" {
}
step "create_backend_cluster" {
- module = "backend_${matrix.backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.backend}"
depends_on = [
step.create_vault_cluster_backend_targets
]
@@ -166,20 +197,38 @@ scenario "agent" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_server,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_cli_validate,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_unit,
+ quality.consul_service_systemd_notified,
+ ]
+
variables {
cluster_name = step.create_vault_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
- license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_vault_cluster_backend_targets.hosts
+ license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
}
- target_hosts = step.create_vault_cluster_backend_targets.hosts
}
}
step "create_vault_cluster" {
- module = module.vault_cluster
+ description = global.description.create_vault_cluster
+ module = module.vault_cluster
depends_on = [
step.create_backend_cluster,
step.build_vault,
@@ -190,62 +239,120 @@ scenario "agent" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.consul_service_start_client,
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_syslog,
+ quality.vault_audit_socket,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_log_level,
+ quality.vault_config_file,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_init,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_cli_status_exit_code,
+ quality.vault_service_systemd_unit,
+ quality.vault_service_systemd_notified,
+ ]
+
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
backend_cluster_name = step.create_vault_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
cluster_name = step.create_vault_cluster_targets.cluster_name
config_mode = matrix.config_mode
- consul_license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
consul_release = matrix.backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
- install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
local_artifact_path = local.artifact_path
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
seal_attributes = step.create_seal_key.attributes
seal_type = matrix.seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
+ step "get_local_metadata" {
+ description = global.description.get_local_metadata
+ skip_step = matrix.artifact_source != "local"
+ module = module.get_local_metadata
+ }
+
// Wait for our cluster to elect a leader
step "wait_for_leader" {
- module = module.vault_wait_for_leader
- depends_on = [step.create_vault_cluster]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_vault_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "start_vault_agent" {
- module = "vault_agent"
+ description = global.description.start_vault_agent
+ module = module.vault_agent
depends_on = [
step.build_vault,
step.create_vault_cluster,
step.wait_for_leader,
]
+ verifies = [
+ quality.vault_agent_auto_auth_approle,
+ quality.vault_cli_auth_enable_approle,
+ ]
+
providers = {
enos = local.enos_provider[matrix.distro]
}
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
vault_agent_template_destination = "/tmp/agent_output.txt"
vault_agent_template_contents = "{{ with secret \\\"auth/token/lookup-self\\\" }}orphan={{ .Data.orphan }} display_name={{ .Data.display_name }}{{ end }}"
@@ -260,44 +367,87 @@ scenario "agent" {
step.wait_for_leader,
]
+ verifies = quality.vault_agent_log_template
+
providers = {
enos = local.enos_provider[matrix.distro]
}
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
vault_agent_template_destination = "/tmp/agent_output.txt"
vault_agent_expected_output = "orphan=true display_name=approle"
}
}
step "get_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_leader]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
- step "verify_vault_version" {
- module = module.vault_verify_version
- depends_on = [step.wait_for_leader]
+ step "verify_vault_unsealed" {
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
+ depends_on = [step.wait_for_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ }
+ }
+
+ step "verify_vault_version" {
+ description = global.description.verify_vault_version
+ module = module.vault_verify_version
+ depends_on = [step.verify_vault_unsealed]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_version_history_keys,
+ quality.vault_api_sys_version_history_key_info,
+ quality.vault_version_build_date,
+ quality.vault_version_edition,
+ quality.vault_version_release,
+ ]
+
+ variables {
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_revision = matrix.artifact_source == "local" ? step.get_local_metadata.revision : var.vault_revision
vault_build_date = matrix.artifact_source == "local" ? step.get_local_metadata.build_date : var.vault_build_date
@@ -305,79 +455,77 @@ scenario "agent" {
}
}
- step "verify_vault_unsealed" {
- module = module.vault_verify_unsealed
- depends_on = [step.wait_for_leader]
+ step "verify_write_test_data" {
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_write_data
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
- variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
- }
- }
-
- step "verify_write_test_data" {
- module = module.vault_verify_write_data
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
+ verifies = [
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
]
- providers = {
- enos = local.enos_provider[matrix.distro]
- }
-
variables {
- leader_public_ip = step.get_vault_cluster_ips.leader_public_ip
- leader_private_ip = step.get_vault_cluster_ips.leader_private_ip
- vault_instances = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ leader_host = step.get_vault_cluster_ips.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_raft_auto_join_voter" {
- skip_step = matrix.backend != "raft"
- module = module.vault_verify_raft_auto_join_voter
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
- ]
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+ skip_step = matrix.backend != "raft"
+ module = module.vault_verify_raft_auto_join_voter
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_raft_voters
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_replication" {
- module = module.vault_verify_replication
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
- ]
+ description = global.description.verify_replication_status
+ module = module.vault_verify_replication
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_replication_ce_disabled,
+ quality.vault_replication_ent_dr_available,
+ quality.vault_replication_ent_pr_available,
+ ]
+
variables {
- vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_edition = matrix.edition
}
}
step "verify_read_test_data" {
- module = module.vault_verify_read_data
+ description = global.description.verify_read_test_data
+ module = module.vault_verify_read_data
depends_on = [
step.verify_write_test_data,
step.verify_replication
@@ -387,22 +535,29 @@ scenario "agent" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_secrets_kv_read
+
variables {
- node_public_ips = step.get_vault_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_vault_cluster_ips.follower_hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_ui" {
- module = module.vault_verify_ui
- depends_on = [step.create_vault_cluster]
+ description = global.description.verify_ui
+ module = module.vault_verify_ui
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_ui_assets
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
}
}
@@ -418,7 +573,7 @@ scenario "agent" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "private_ips" {
diff --git a/enos/enos-scenario-autopilot.hcl b/enos/enos-scenario-autopilot.hcl
index a28500fe7c..b8ff550303 100644
--- a/enos/enos-scenario-autopilot.hcl
+++ b/enos/enos-scenario-autopilot.hcl
@@ -1,38 +1,70 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "autopilot" {
+ description = <<-EOF
+ The autopilot scenario verifies autopilot upgrades between previously released versions of
+ Vault Enterprise against another candidate build. The build can be a local branch, any CRT built
+ Vault Enterprise artifact saved to the local machine, or any CRT built Vault Enterprise artifact
+ in the stable channel in Artifactory.
+
+ The scenario creates a new Vault Cluster with a previously released version of Vault, mounts
+ various engines and creates data, then perform an Autopilot upgrade with any candidate build.
+ The scenario also performs standard baseline verification that is not specific to the autopilot
+ upgrade.
+
+ If you want to use the 'distro:leap' variant you must first accept SUSE's terms for the AWS
+ account. To verify that your account has agreed, sign-in to your AWS through Doormat,
+ and visit the following links to verify your subscription or subscribe:
+ arm64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+ amd64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+ EOF
+
matrix {
arch = global.archs
artifact_source = global.artifact_sources
artifact_type = global.artifact_types
config_mode = global.config_modes
distro = global.distros
- edition = global.editions
- initial_version = global.upgrade_initial_versions
+ edition = global.enterprise_editions
+ initial_version = global.upgrade_initial_versions_ent
+ ip_version = global.ip_versions
seal = global.seals
- # Autopilot wasn't available before 1.11.x
+ // Autopilot wasn't available before 1.11.x
exclude {
- initial_version = ["1.8.12", "1.9.10", "1.10.11"]
+ initial_version = [for e in matrix.initial_version : e if semverconstraint(e, "<1.11.0-0")]
}
- # Our local builder always creates bundles
+ // Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}
- # HSM and FIPS 140-2 are only supported on amd64
+ // There are no published versions of these artifacts yet. We'll update this to exclude older
+ // versions after our initial publication of these editions for arm64.
exclude {
arch = ["arm64"]
edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
}
- # PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
+ // PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
exclude {
seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
+ }
+
+ // softhsm packages not available for leap/sles.
+ exclude {
+ seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ // Testing in IPV6 mode is currently implemented for integrated Raft storage only
+ exclude {
+ ip_version = ["6"]
+ backend = ["consul"]
}
}
@@ -40,23 +72,27 @@ scenario "autopilot" {
terraform = terraform.default
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
locals {
artifact_path = matrix.artifact_source != "artifactory" ? abspath(var.vault_artifact_path) : null
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
manage_service = matrix.artifact_type == "bundle"
- vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_autopilot_default_max_leases = semverconstraint(matrix.initial_version, ">=1.16.0-0") ? "300000" : ""
}
step "build_vault" {
- module = "build_${matrix.artifact_source}"
+ description = global.description.build_vault
+ module = "build_${matrix.artifact_source}"
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : global.build_tags[matrix.edition]
@@ -77,19 +113,23 @@ scenario "autopilot" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = global.tags
+ ip_version = matrix.ip_version
}
}
step "read_license" {
- module = module.read_license
+ description = global.description.read_vault_license
+ module = module.read_license
variables {
file_name = global.vault_license_path
@@ -97,8 +137,9 @@ scenario "autopilot" {
}
step "create_seal_key" {
- module = "seal_${matrix.seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -111,8 +152,9 @@ scenario "autopilot" {
}
step "create_vault_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
@@ -122,29 +164,38 @@ scenario "autopilot" {
ami_id = step.ec2_info.ami_ids[matrix.arch][matrix.distro][global.distro_version[matrix.distro]]
cluster_tag_key = global.vault_tag_key
common_tags = global.tags
+ instance_count = 3
seal_key_names = step.create_seal_key.resource_names
vpc_id = step.create_vpc.id
}
}
step "create_vault_cluster_upgrade_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
}
variables {
- ami_id = step.ec2_info.ami_ids[matrix.arch][matrix.distro][global.distro_version[matrix.distro]]
- common_tags = global.tags
- cluster_name = step.create_vault_cluster_targets.cluster_name
- seal_key_names = step.create_seal_key.resource_names
- vpc_id = step.create_vpc.id
+ ami_id = step.ec2_info.ami_ids[matrix.arch][matrix.distro][global.distro_version[matrix.distro]]
+ common_tags = global.tags
+ cluster_name = step.create_vault_cluster_targets.cluster_name
+ cluster_tag_key = global.vault_tag_key
+ instance_count = 3
+ seal_key_names = step.create_seal_key.resource_names
+ vpc_id = step.create_vpc.id
}
}
step "create_vault_cluster" {
+ description = <<-EOF
+ ${global.description.create_vault_cluster} In this instance we'll create a Vault Cluster with
+ and older version and use Autopilot to upgrade to it.
+ EOF
+
module = module.vault_cluster
depends_on = [
step.build_vault,
@@ -155,13 +206,49 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_cli_status_exit_code,
+ quality.vault_service_systemd_notified,
+ quality.vault_service_systemd_unit,
+ ]
+
variables {
cluster_name = step.create_vault_cluster_targets.cluster_name
config_mode = matrix.config_mode
enable_audit_devices = var.vault_enable_audit_devices
+ hosts = step.create_vault_cluster_targets.hosts
install_dir = local.vault_install_dir
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_license.license : null
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
release = {
edition = matrix.edition
version = matrix.initial_version
@@ -172,32 +259,70 @@ scenario "autopilot" {
storage_backend_addl_config = {
autopilot_upgrade_version = matrix.initial_version
}
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
step "get_local_metadata" {
- skip_step = matrix.artifact_source != "local"
- module = module.get_local_metadata
+ description = global.description.get_local_metadata
+ skip_step = matrix.artifact_source != "local"
+ module = module.get_local_metadata
}
- step "get_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.create_vault_cluster]
+ // Wait for our cluster to elect a leader
+ step "wait_for_leader" {
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_vault_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster.target_hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
+ vault_root_token = step.create_vault_cluster.root_token
+ }
+ }
+
+ step "get_vault_cluster_ips" {
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [
+ step.create_vault_cluster,
+ step.wait_for_leader,
+ ]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
+ variables {
+ hosts = step.create_vault_cluster.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_write_test_data" {
- module = module.vault_verify_write_data
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_write_data
depends_on = [
step.create_vault_cluster,
step.get_vault_cluster_ips
@@ -207,17 +332,28 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
+ ]
+
variables {
- leader_public_ip = step.get_vault_cluster_ips.leader_public_ip
- leader_private_ip = step.get_vault_cluster_ips.leader_private_ip
- vault_instances = step.create_vault_cluster.target_hosts
+ hosts = step.create_vault_cluster.hosts
+ leader_host = step.get_vault_cluster_ips.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_vault_cluster.root_token
}
}
step "create_autopilot_upgrade_storageconfig" {
- module = module.autopilot_upgrade_storageconfig
+ description = <<-EOF
+ An arithmetic module used to dynamically create autopilot storage configuration depending on
+ whether or not we're testing a local build or a candidate build.
+ EOF
+ module = module.autopilot_upgrade_storageconfig
variables {
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
@@ -239,17 +375,19 @@ scenario "autopilot" {
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
- enable_audit_devices = var.vault_enable_audit_devices
cluster_name = step.create_vault_cluster_targets.cluster_name
config_mode = matrix.config_mode
- log_level = var.vault_log_level
+ enable_audit_devices = var.vault_enable_audit_devices
force_unseal = matrix.seal == "shamir"
+ hosts = step.create_vault_cluster_upgrade_targets.hosts
initialize_cluster = false
install_dir = local.vault_install_dir
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_license.license : null
local_artifact_path = local.artifact_path
+ log_level = var.vault_log_level
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
root_token = step.create_vault_cluster.root_token
seal_attributes = step.create_seal_key.attributes
seal_type = matrix.seal
@@ -257,12 +395,12 @@ scenario "autopilot" {
storage_backend = "raft"
storage_backend_addl_config = step.create_autopilot_upgrade_storageconfig.storage_addl_config
storage_node_prefix = "upgrade_node"
- target_hosts = step.create_vault_cluster_upgrade_targets.hosts
}
}
step "verify_vault_unsealed" {
- module = module.vault_verify_unsealed
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
depends_on = [
step.create_vault_cluster,
step.create_vault_cluster_upgrade_targets,
@@ -273,14 +411,23 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_auto_unseals_after_autopilot_upgrade,
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_install_dir = local.vault_install_dir
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
}
}
step "verify_raft_auto_join_voter" {
- module = module.vault_verify_raft_auto_join_voter
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+ module = module.vault_verify_raft_auto_join_voter
depends_on = [
step.upgrade_vault_cluster_with_autopilot,
step.verify_vault_unsealed
@@ -290,15 +437,20 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_raft_voters
+
variables {
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_install_dir = local.vault_install_dir
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
vault_root_token = step.upgrade_vault_cluster_with_autopilot.root_token
}
}
step "verify_autopilot_await_server_removal_state" {
- module = module.vault_verify_autopilot
+ description = global.description.verify_autopilot_idle_state
+ module = module.vault_verify_autopilot
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.upgrade_vault_cluster_with_autopilot,
@@ -309,17 +461,24 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_storage_raft_autopilot_upgrade_info_read_status_matches,
+ quality.vault_api_sys_storage_raft_autopilot_upgrade_info_target_version_read_matches_candidate,
+ ]
+
variables {
+ hosts = step.create_vault_cluster.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_autopilot_upgrade_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_autopilot_upgrade_status = "await-server-removal"
vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster.target_hosts
vault_root_token = step.upgrade_vault_cluster_with_autopilot.root_token
}
}
step "wait_for_leader_in_upgrade_targets" {
- module = module.vault_wait_for_leader
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
depends_on = [
step.create_vault_cluster,
step.create_vault_cluster_upgrade_targets,
@@ -331,15 +490,24 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_autopilot_upgrade_leader_election,
+ ]
+
variables {
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_vault_cluster.root_token
- vault_hosts = step.upgrade_vault_cluster_with_autopilot.target_hosts
}
}
step "get_updated_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
depends_on = [
step.create_vault_cluster,
step.create_vault_cluster_upgrade_targets,
@@ -352,15 +520,24 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.upgrade_vault_cluster_with_autopilot.target_hosts
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_read_test_data" {
- module = module.vault_verify_read_data
+ description = global.description.verify_read_test_data
+ module = module.vault_verify_read_data
depends_on = [
step.get_updated_vault_cluster_ips,
step.verify_write_test_data,
@@ -372,15 +549,20 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_secrets_kv_read
+
variables {
- node_public_ips = step.get_updated_vault_cluster_ips.follower_public_ips
- vault_instance_count = 6
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_updated_vault_cluster_ips.follower_hosts
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
}
}
step "raft_remove_peers" {
- module = module.vault_raft_remove_peer
+ description = <<-EOF
+ Remove the nodes that were running the prior version of Vault from the raft cluster
+ EOF
+ module = module.vault_raft_remove_peer
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.get_updated_vault_cluster_ips,
@@ -392,17 +574,25 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_storage_raft_remove_peer_write_removes_peer,
+ quality.vault_cli_operator_raft_remove_peer,
+ ]
+
variables {
- operator_instance = step.get_updated_vault_cluster_ips.leader_public_ip
- remove_vault_instances = step.create_vault_cluster.target_hosts
- vault_install_dir = local.vault_install_dir
- vault_instance_count = 3
- vault_root_token = step.create_vault_cluster.root_token
+ hosts = step.create_vault_cluster.hosts
+ ip_version = matrix.ip_version
+ operator_instance = step.get_updated_vault_cluster_ips.leader_public_ip
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
+ vault_cluster_addr_port = step.upgrade_vault_cluster_with_autopilot.cluster_port
+ vault_install_dir = local.vault_install_dir
+ vault_root_token = step.create_vault_cluster.root_token
}
}
step "remove_old_nodes" {
- module = module.shutdown_multiple_nodes
+ description = global.description.shutdown_nodes
+ module = module.shutdown_multiple_nodes
depends_on = [
step.create_vault_cluster,
step.raft_remove_peers
@@ -413,13 +603,13 @@ scenario "autopilot" {
}
variables {
- old_vault_instances = step.create_vault_cluster.target_hosts
- vault_instance_count = 3
+ old_hosts = step.create_vault_cluster.hosts
}
}
step "verify_autopilot_idle_state" {
- module = module.vault_verify_autopilot
+ description = global.description.verify_autopilot_idle_state
+ module = module.vault_verify_autopilot
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.upgrade_vault_cluster_with_autopilot,
@@ -431,17 +621,24 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_storage_raft_autopilot_upgrade_info_read_status_matches,
+ quality.vault_api_sys_storage_raft_autopilot_upgrade_info_target_version_read_matches_candidate,
+ ]
+
variables {
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_autopilot_upgrade_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_autopilot_upgrade_status = "idle"
vault_install_dir = local.vault_install_dir
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_replication" {
- module = module.vault_verify_replication
+ description = global.description.verify_replication_status
+ module = module.vault_verify_replication
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.upgrade_vault_cluster_with_autopilot,
@@ -453,15 +650,22 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_replication_ce_disabled,
+ quality.vault_replication_ent_dr_available,
+ quality.vault_replication_ent_pr_available,
+ ]
+
variables {
- vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
+ vault_edition = matrix.edition
}
}
step "verify_vault_version" {
- module = module.vault_verify_version
+ description = global.description.verify_vault_version
+ module = module.vault_verify_version
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.upgrade_vault_cluster_with_autopilot,
@@ -473,8 +677,17 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_version_history_keys,
+ quality.vault_api_sys_version_history_key_info,
+ quality.vault_version_build_date,
+ quality.vault_version_edition,
+ quality.vault_version_release,
+ ]
+
variables {
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = local.vault_install_dir
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
@@ -485,7 +698,8 @@ scenario "autopilot" {
}
step "verify_ui" {
- module = module.vault_verify_ui
+ description = global.description.verify_ui
+ module = module.vault_verify_ui
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.upgrade_vault_cluster_with_autopilot,
@@ -497,16 +711,22 @@ scenario "autopilot" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_ui_assets
+
variables {
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
}
}
- step "verify_undo_logs_status" {
- skip_step = true
- # NOTE: temporarily disable undo logs checking until it is fixed. See VAULT-20259
- # skip_step = semverconstraint(var.vault_product_version, "<1.13.0-0")
- module = module.vault_verify_undo_logs
+ step "verify_undo_logs_enabled_on_primary" {
+ skip_step = semverconstraint(var.vault_product_version, "<1.13.0-0")
+ module = module.vault_verify_undo_logs
+ description = <<-EOF
+ Verifies that undo logs is correctly enabled on newly upgraded target hosts. For this it will
+ query the metrics system backend for the vault.core.replication.write_undo_logs gauge.
+ EOF
+
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.remove_old_nodes,
@@ -514,20 +734,48 @@ scenario "autopilot" {
step.verify_autopilot_idle_state
]
+ verifies = quality.vault_api_sys_metrics_vault_core_replication_write_undo_logs_enabled
+
providers = {
enos = local.enos_provider[matrix.distro]
}
variables {
+ expected_state = 1 # Enabled
+ hosts = step.get_updated_vault_cluster_ips.leader_hosts
+ timeout = 180 # Seconds
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_install_dir = local.vault_install_dir
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
vault_root_token = step.create_vault_cluster.root_token
}
}
- # Verify that upgrading from a version <1.16.0 does not introduce Default LCQ
+ step "verify_undo_logs_disabled_on_followers" {
+ skip_step = semverconstraint(var.vault_product_version, "<1.13.0-0")
+ module = module.vault_verify_undo_logs
+ depends_on = [step.verify_undo_logs_enabled_on_primary]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ variables {
+ expected_state = 0 # Disabled
+ hosts = step.get_updated_vault_cluster_ips.follower_hosts
+ timeout = 10 # Seconds
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
+ vault_root_token = step.create_vault_cluster.root_token
+ }
+ }
+
+ // Verify that upgrading from a version <1.16.0 does not introduce Default LCQ
step "verify_default_lcq" {
- module = module.vault_verify_default_lcq
+ description = <<-EOF
+ Verify that the default max lease count is 300,000 when the upgraded nodes are running
+ Vault >= 1.16.0.
+ EOF
+ module = module.vault_verify_default_lcq
depends_on = [
step.create_vault_cluster_upgrade_targets,
step.remove_old_nodes,
@@ -535,12 +783,15 @@ scenario "autopilot" {
step.verify_autopilot_idle_state
]
+ verifies = quality.vault_api_sys_quotas_lease_count_read_max_leases_default
+
providers = {
enos = local.enos_provider[matrix.distro]
}
variables {
- vault_instances = step.upgrade_vault_cluster_with_autopilot.target_hosts
+ hosts = step.upgrade_vault_cluster_with_autopilot.hosts
+ vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_root_token = step.create_vault_cluster.root_token
vault_autopilot_default_max_leases = local.vault_autopilot_default_max_leases
}
@@ -558,7 +809,7 @@ scenario "autopilot" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "private_ips" {
@@ -608,7 +859,7 @@ scenario "autopilot" {
output "upgrade_hosts" {
description = "The Vault cluster target hosts"
- value = step.upgrade_vault_cluster_with_autopilot.target_hosts
+ value = step.upgrade_vault_cluster_with_autopilot.hosts
}
output "upgrade_private_ips" {
diff --git a/enos/enos-scenario-proxy.hcl b/enos/enos-scenario-proxy.hcl
index 356abb8b15..8b47fa4e16 100644
--- a/enos/enos-scenario-proxy.hcl
+++ b/enos/enos-scenario-proxy.hcl
@@ -1,34 +1,58 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "proxy" {
+ description = <<-EOF
+ The agent scenario verifies Vault when running in Proxy mode. The build can be a local branch,
+ any CRT built Vault artifact saved to the local machine, or any CRT built Vault artifact in the
+ stable channel in Artifactory.
+
+ The scenario creates a new Vault Cluster using the candidate build and then runs the same Vault
+ build in Proxy mode and verifies behavior against the Vault cluster. The scenario also performs
+ standard baseline verification that is not specific to the Proxy mode deployment.
+
+ If you want to use the 'distro:leap' variant you must first accept SUSE's terms for the AWS
+ account. To verify that your account has agreed, sign-in to your AWS through Doormat,
+ and visit the following links to verify your subscription or subscribe:
+ arm64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+ amd64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+ EOF
+
matrix {
arch = global.archs
artifact_source = global.artifact_sources
artifact_type = global.artifact_types
backend = global.backends
config_mode = global.config_modes
+ consul_edition = global.consul_editions
consul_version = global.consul_versions
distro = global.distros
edition = global.editions
+ ip_version = global.ip_versions
seal = global.seals
- # Our local builder always creates bundles
+ // Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}
- # HSM and FIPS 140-2 are only supported on amd64
- exclude {
- arch = ["arm64"]
- edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
- }
-
- # PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
+ // PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
exclude {
seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
+ }
+
+ // softhsm packages not available for leap/sles.
+ exclude {
+ seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ // Testing in IPV6 mode is currently implemented for integrated Raft storage only
+ exclude {
+ ip_version = ["6"]
+ backend = ["consul"]
}
}
@@ -36,27 +60,32 @@ scenario "proxy" {
terraform = terraform.default
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
locals {
artifact_path = matrix.artifact_source != "artifactory" ? abspath(var.vault_artifact_path) : null
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
manage_service = matrix.artifact_type == "bundle"
- vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
step "get_local_metadata" {
- skip_step = matrix.artifact_source != "local"
- module = module.get_local_metadata
+ description = global.description.get_local_metadata
+ skip_step = matrix.artifact_source != "local"
+ module = module.get_local_metadata
}
step "build_vault" {
- module = "build_${matrix.artifact_source}"
+ description = global.description.build_vault
+ module = "build_${matrix.artifact_source}"
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : global.build_tags[matrix.edition]
@@ -77,22 +106,26 @@ scenario "proxy" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = global.tags
+ ip_version = matrix.ip_version
}
}
// This step reads the contents of the backend license if we're using a Consul backend and
- // the edition is "ent".
+ // an "ent" Consul edition.
step "read_backend_license" {
- skip_step = matrix.backend == "raft" || var.backend_edition == "ce"
- module = module.read_license
+ description = global.description.read_backend_license
+ skip_step = matrix.backend == "raft" || matrix.consul_edition == "ce"
+ module = module.read_license
variables {
file_name = global.backend_license_path
@@ -100,8 +133,9 @@ scenario "proxy" {
}
step "read_vault_license" {
- skip_step = matrix.edition == "ce"
- module = module.read_license
+ description = global.description.read_vault_license
+ skip_step = matrix.edition == "ce"
+ module = module.read_license
variables {
file_name = global.vault_license_path
@@ -109,8 +143,9 @@ scenario "proxy" {
}
step "create_seal_key" {
- module = "seal_${matrix.seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -123,8 +158,9 @@ scenario "proxy" {
}
step "create_vault_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
@@ -140,15 +176,16 @@ scenario "proxy" {
}
step "create_vault_cluster_backend_targets" {
- module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_seal_key.resource_names
@@ -157,7 +194,8 @@ scenario "proxy" {
}
step "create_backend_cluster" {
- module = "backend_${matrix.backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.backend}"
depends_on = [
step.create_vault_cluster_backend_targets
]
@@ -166,20 +204,38 @@ scenario "proxy" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_server,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_cli_validate,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_notified,
+ quality.consul_service_systemd_unit,
+ ]
+
variables {
cluster_name = step.create_vault_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
- license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_vault_cluster_backend_targets.hosts
+ license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
}
- target_hosts = step.create_vault_cluster_backend_targets.hosts
}
}
step "create_vault_cluster" {
- module = module.vault_cluster
+ description = global.description.create_vault_cluster
+ module = module.vault_cluster
depends_on = [
step.create_backend_cluster,
step.build_vault,
@@ -190,49 +246,93 @@ scenario "proxy" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.consul_service_start_client,
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_service_systemd_notified,
+ quality.vault_service_systemd_unit,
+ quality.vault_cli_status_exit_code,
+ ]
+
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
backend_cluster_name = step.create_vault_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
cluster_name = step.create_vault_cluster_targets.cluster_name
config_mode = matrix.config_mode
- consul_license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
consul_release = matrix.backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
- install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
local_artifact_path = local.artifact_path
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
seal_attributes = step.create_seal_key.attributes
seal_type = matrix.seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
// Wait for our cluster to elect a leader
step "wait_for_leader" {
- module = module.vault_wait_for_leader
- depends_on = [step.create_vault_cluster]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_vault_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "start_vault_proxy" {
- module = "vault_proxy"
+ module = module.vault_proxy
depends_on = [
step.build_vault,
step.create_vault_cluster,
@@ -242,40 +342,89 @@ scenario "proxy" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_cli_auth_enable_approle,
+ quality.vault_proxy_auto_auth_approle,
+ quality.vault_proxy_cli_access,
+ ]
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_leader]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
- step "verify_vault_version" {
- module = module.vault_verify_version
- depends_on = [step.create_vault_cluster]
+ step "verify_vault_unsealed" {
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
+ depends_on = [step.create_vault_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ }
+ }
+
+ step "verify_vault_version" {
+ description = global.description.verify_vault_version
+ module = module.vault_verify_version
+ depends_on = [step.verify_vault_unsealed]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_version_history_keys,
+ quality.vault_api_sys_version_history_key_info,
+ quality.vault_version_build_date,
+ quality.vault_version_edition,
+ quality.vault_version_release,
+ ]
+
+ variables {
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_revision = matrix.artifact_source == "local" ? step.get_local_metadata.revision : var.vault_revision
vault_build_date = matrix.artifact_source == "local" ? step.get_local_metadata.build_date : var.vault_build_date
@@ -283,73 +432,77 @@ scenario "proxy" {
}
}
- step "verify_vault_unsealed" {
- module = module.vault_verify_unsealed
- depends_on = [step.create_vault_cluster]
+ step "verify_write_test_data" {
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_write_data
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
- variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
- }
- }
-
- step "verify_write_test_data" {
- module = module.vault_verify_write_data
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
+ verifies = [
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
]
- providers = {
- enos = local.enos_provider[matrix.distro]
- }
-
variables {
- leader_public_ip = step.get_vault_cluster_ips.leader_public_ip
- leader_private_ip = step.get_vault_cluster_ips.leader_private_ip
- vault_instances = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ leader_host = step.get_vault_cluster_ips.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_raft_auto_join_voter" {
- skip_step = matrix.backend != "raft"
- module = module.vault_verify_raft_auto_join_voter
- depends_on = [step.create_vault_cluster]
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+ skip_step = matrix.backend != "raft"
+ module = module.vault_verify_raft_auto_join_voter
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_raft_voters
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_replication" {
- module = module.vault_verify_replication
- depends_on = [step.create_vault_cluster]
+ description = global.description.verify_replication_status
+ module = module.vault_verify_replication
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_replication_ce_disabled,
+ quality.vault_replication_ent_dr_available,
+ quality.vault_replication_ent_pr_available,
+ ]
+
variables {
- vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_edition = matrix.edition
}
}
step "verify_read_test_data" {
- module = module.vault_verify_read_data
+ description = global.description.verify_read_test_data
+ module = module.vault_verify_read_data
depends_on = [
step.verify_write_test_data,
step.verify_replication
@@ -359,22 +512,29 @@ scenario "proxy" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_secrets_kv_read
+
variables {
- node_public_ips = step.get_vault_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_vault_cluster_ips.follower_hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_ui" {
- module = module.vault_verify_ui
- depends_on = [step.create_vault_cluster]
+ description = global.description.verify_ui
+ module = module.vault_verify_ui
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_ui_assets
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
}
}
@@ -390,7 +550,7 @@ scenario "proxy" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "private_ips" {
diff --git a/enos/enos-scenario-replication.hcl b/enos/enos-scenario-replication.hcl
index 0634d2ffa1..9c38096d71 100644
--- a/enos/enos-scenario-replication.hcl
+++ b/enos/enos-scenario-replication.hcl
@@ -1,44 +1,80 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
-// The replication scenario configures performance replication between two Vault clusters and verifies
-// known_primary_cluster_addrs are updated on secondary Vault cluster with the IP addresses of replaced
-// nodes on primary Vault cluster
scenario "replication" {
+ description = <<-EOF
+ The replication scenario configures performance replication between two Vault clusters and
+ verifies behavior and failure tolerance. The build can be a local branch, any CRT built Vault
+ Enterprise artifact saved to the local machine, or any CRT built Vault Enterprise artifact in
+ the stable channel in Artifactory.
+
+ The scenario deploys two Vault Enterprise clusters and establishes performance replication
+ between the primary cluster and the performance replication secondary cluster. Next, we simulate
+ a catastrophic failure event whereby the primary leader and a primary follower as ungracefully
+ removed from the cluster while running. This forces a leader election in the primary cluster
+ and requires the secondary cluster to recover replication and establish replication to the new
+ primary leader. The scenario also performs standard baseline verification that is not specific
+ to performance replication.
+
+ If you want to use the 'distro:leap' variant you must first accept SUSE's terms for the AWS
+ account. To verify that your account has agreed, sign-in to your AWS through Doormat,
+ and visit the following links to verify your subscription or subscribe:
+ arm64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+ amd64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+ EOF
+
matrix {
arch = global.archs
artifact_source = global.artifact_sources
artifact_type = global.artifact_types
config_mode = global.config_modes
+ consul_edition = global.consul_editions
consul_version = global.consul_versions
distro = global.distros
- edition = global.editions
+ edition = global.enterprise_editions
+ ip_version = global.ip_versions
primary_backend = global.backends
primary_seal = global.seals
secondary_backend = global.backends
secondary_seal = global.seals
- # Our local builder always creates bundles
+ // Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}
- # HSM and FIPS 140-2 are only supported on amd64
- exclude {
- arch = ["arm64"]
- edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
- }
-
- # PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
+ // PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
exclude {
primary_seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
}
exclude {
secondary_seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
+ }
+
+ // softhsm packages not available for leap/sles.
+ exclude {
+ primary_seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ exclude {
+ secondary_seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ // Testing in IPV6 mode is currently implemented for integrated Raft storage only
+ exclude {
+ ip_version = ["6"]
+ primary_backend = ["consul"]
+ }
+
+ exclude {
+ ip_version = ["6"]
+ secondary_backend = ["consul"]
}
}
@@ -46,27 +82,26 @@ scenario "replication" {
terraform = terraform.default
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
locals {
artifact_path = matrix.artifact_source != "artifactory" ? abspath(var.vault_artifact_path) : null
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
manage_service = matrix.artifact_type == "bundle"
- vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
- }
-
- step "get_local_metadata" {
- skip_step = matrix.artifact_source != "local"
- module = module.get_local_metadata
+ vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir[matrix.artifact_type]
}
step "build_vault" {
- module = "build_${matrix.artifact_source}"
+ description = global.description.build_vault
+ module = "build_${matrix.artifact_source}"
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : global.build_tags[matrix.edition]
@@ -87,22 +122,26 @@ scenario "replication" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = global.tags
+ ip_version = matrix.ip_version
}
}
// This step reads the contents of the backend license if we're using a Consul backend and
- // the edition is "ent".
+ // an "ent" Consul edition.
step "read_backend_license" {
- skip_step = (matrix.primary_backend == "raft" && matrix.secondary_backend == "raft") || var.backend_edition == "ce"
- module = module.read_license
+ description = global.description.read_backend_license
+ skip_step = (matrix.primary_backend == "raft" && matrix.secondary_backend == "raft") || matrix.consul_edition == "ce"
+ module = module.read_license
variables {
file_name = global.backend_license_path
@@ -110,7 +149,8 @@ scenario "replication" {
}
step "read_vault_license" {
- module = module.read_license
+ description = global.description.read_vault_license
+ module = module.read_license
variables {
file_name = abspath(joinpath(path.root, "./support/vault.hclic"))
@@ -118,8 +158,9 @@ scenario "replication" {
}
step "create_primary_seal_key" {
- module = "seal_${matrix.primary_seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.primary_seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -133,8 +174,9 @@ scenario "replication" {
}
step "create_secondary_seal_key" {
- module = "seal_${matrix.secondary_seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.secondary_seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -148,9 +190,10 @@ scenario "replication" {
}
}
- # Create all of our instances for both primary and secondary clusters
+ // Create all of our instances for both primary and secondary clusters
step "create_primary_cluster_targets" {
- module = module.target_ec2_instances
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
depends_on = [
step.create_vpc,
]
@@ -169,7 +212,8 @@ scenario "replication" {
}
step "create_primary_cluster_backend_targets" {
- module = matrix.primary_backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ description = global.description.create_vault_cluster_targets
+ module = matrix.primary_backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
depends_on = [
step.create_vpc,
]
@@ -179,7 +223,7 @@ scenario "replication" {
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_primary_seal_key.resource_names
@@ -188,7 +232,8 @@ scenario "replication" {
}
step "create_primary_cluster_additional_targets" {
- module = module.target_ec2_instances
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
depends_on = [
step.create_vpc,
step.create_primary_cluster_targets,
@@ -209,8 +254,9 @@ scenario "replication" {
}
step "create_secondary_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
@@ -226,15 +272,16 @@ scenario "replication" {
}
step "create_secondary_cluster_backend_targets" {
- module = matrix.secondary_backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = matrix.secondary_backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_secondary_seal_key.resource_names
@@ -243,7 +290,8 @@ scenario "replication" {
}
step "create_primary_backend_cluster" {
- module = "backend_${matrix.primary_backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.primary_backend}"
depends_on = [
step.create_primary_cluster_backend_targets,
]
@@ -252,20 +300,38 @@ scenario "replication" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_server,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_cli_validate,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_notified,
+ quality.consul_service_systemd_unit,
+ ]
+
variables {
cluster_name = step.create_primary_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
- license = (matrix.primary_backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_primary_cluster_backend_targets.hosts
+ license = (matrix.primary_backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
}
- target_hosts = step.create_primary_cluster_backend_targets.hosts
}
}
step "create_primary_cluster" {
- module = module.vault_cluster
+ description = global.description.create_vault_cluster
+ module = module.vault_cluster
depends_on = [
step.create_primary_backend_cluster,
step.build_vault,
@@ -276,32 +342,98 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.consul_service_start_client,
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_cli_status_exit_code,
+ quality.vault_service_systemd_notified,
+ quality.vault_service_systemd_unit,
+ ]
+
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
backend_cluster_name = step.create_primary_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
config_mode = matrix.config_mode
- consul_license = (matrix.primary_backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.primary_backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
cluster_name = step.create_primary_cluster_targets.cluster_name
consul_release = matrix.primary_backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
- install_dir = local.vault_install_dir
+ hosts = step.create_primary_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
local_artifact_path = local.artifact_path
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
seal_attributes = step.create_primary_seal_key.attributes
seal_type = matrix.primary_seal
storage_backend = matrix.primary_backend
- target_hosts = step.create_primary_cluster_targets.hosts
+ }
+ }
+
+ step "get_local_metadata" {
+ skip_step = matrix.artifact_source != "local"
+ module = module.get_local_metadata
+ }
+
+ step "wait_for_primary_cluster_leader" {
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_primary_cluster]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
+ variables {
+ hosts = step.create_primary_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
+ vault_root_token = step.create_primary_cluster.root_token
}
}
step "create_secondary_backend_cluster" {
- module = "backend_${matrix.secondary_backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.secondary_backend}"
depends_on = [
step.create_secondary_cluster_backend_targets
]
@@ -313,12 +445,12 @@ scenario "replication" {
variables {
cluster_name = step.create_secondary_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
- license = (matrix.secondary_backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_secondary_cluster_backend_targets.hosts
+ license = (matrix.secondary_backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
}
- target_hosts = step.create_secondary_cluster_backend_targets.hosts
}
}
@@ -334,76 +466,193 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_client,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_notified,
+ quality.consul_service_systemd_unit,
+ ]
+
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
backend_cluster_name = step.create_secondary_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
config_mode = matrix.config_mode
- consul_license = (matrix.secondary_backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.secondary_backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
cluster_name = step.create_secondary_cluster_targets.cluster_name
consul_release = matrix.secondary_backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
- install_dir = local.vault_install_dir
+ hosts = step.create_secondary_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
local_artifact_path = local.artifact_path
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
seal_attributes = step.create_secondary_seal_key.attributes
seal_type = matrix.secondary_seal
storage_backend = matrix.secondary_backend
- target_hosts = step.create_secondary_cluster_targets.hosts
+ }
+ }
+
+ step "wait_for_secondary_cluster_leader" {
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_secondary_cluster]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
+ variables {
+ hosts = step.create_secondary_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = local.vault_install_dir
+ vault_root_token = step.create_secondary_cluster.root_token
}
}
step "verify_that_vault_primary_cluster_is_unsealed" {
- module = module.vault_verify_unsealed
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
depends_on = [
- step.create_primary_cluster
+ step.create_primary_cluster,
+ step.wait_for_primary_cluster_leader,
]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_auto_unseals_after_autopilot_upgrade,
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_primary_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_primary_cluster_targets.hosts
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_that_vault_secondary_cluster_is_unsealed" {
- module = module.vault_verify_unsealed
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
depends_on = [
- step.create_secondary_cluster
+ step.create_secondary_cluster,
+ step.wait_for_secondary_cluster_leader,
]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_auto_unseals_after_autopilot_upgrade,
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_secondary_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_secondary_cluster_targets.hosts
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ }
+ }
+
+ step "get_primary_cluster_ips" {
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.verify_that_vault_primary_cluster_is_unsealed]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
+ variables {
+ hosts = step.create_primary_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ vault_root_token = step.create_primary_cluster.root_token
+ }
+ }
+
+ step "get_secondary_cluster_ips" {
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.verify_that_vault_secondary_cluster_is_unsealed]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
+ variables {
+ hosts = step.create_secondary_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ vault_root_token = step.create_secondary_cluster.root_token
}
}
step "verify_vault_version" {
- module = module.vault_verify_version
- depends_on = [
- step.create_primary_cluster
- ]
+ description = global.description.verify_vault_version
+ module = module.vault_verify_version
+ depends_on = [step.get_primary_cluster_ips]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_version_history_keys,
+ quality.vault_api_sys_version_history_key_info,
+ quality.vault_version_build_date,
+ quality.vault_version_edition,
+ quality.vault_version_release,
+ ]
+
variables {
- vault_instances = step.create_primary_cluster_targets.hosts
+ hosts = step.create_primary_cluster_targets.hosts
+ vault_addr = step.create_primary_cluster.api_addr_localhost
vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_revision = matrix.artifact_source == "local" ? step.get_local_metadata.revision : var.vault_revision
vault_build_date = matrix.artifact_source == "local" ? step.get_local_metadata.build_date : var.vault_build_date
@@ -412,104 +661,93 @@ scenario "replication" {
}
step "verify_ui" {
- module = module.vault_verify_ui
- depends_on = [
- step.create_primary_cluster
- ]
+ description = global.description.verify_ui
+ module = module.vault_verify_ui
+ depends_on = [step.get_primary_cluster_ips]
providers = {
enos = local.enos_provider[matrix.distro]
}
- variables {
- vault_instances = step.create_primary_cluster_targets.hosts
- }
- }
-
- step "get_primary_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [
- step.verify_vault_version,
- step.verify_ui,
- step.verify_that_vault_primary_cluster_is_unsealed,
- ]
-
- providers = {
- enos = local.enos_provider[matrix.distro]
- }
+ verifies = quality.vault_ui_assets
variables {
- vault_hosts = step.create_primary_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
- vault_root_token = step.create_primary_cluster.root_token
- }
- }
-
- step "get_primary_cluster_replication_data" {
- module = module.replication_data
- depends_on = [step.get_primary_cluster_ips]
-
- variables {
- follower_hosts = step.get_primary_cluster_ips.follower_hosts
- }
- }
-
- step "get_secondary_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.verify_that_vault_secondary_cluster_is_unsealed]
-
- providers = {
- enos = local.enos_provider[matrix.distro]
- }
-
- variables {
- vault_hosts = step.create_secondary_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
- vault_root_token = step.create_secondary_cluster.root_token
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ hosts = step.create_primary_cluster_targets.hosts
}
}
step "write_test_data_on_primary" {
- module = module.vault_verify_write_data
- depends_on = [step.get_primary_cluster_ips]
-
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_write_data
+ depends_on = [step.get_primary_cluster_ips]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
+ ]
+
variables {
- leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
- leader_private_ip = step.get_primary_cluster_ips.leader_private_ip
- vault_instances = step.create_primary_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_primary_cluster_targets.hosts
+ leader_host = step.get_primary_cluster_ips.leader_host
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_primary_cluster.root_token
}
}
step "configure_performance_replication_primary" {
- module = module.vault_setup_perf_primary
+ description = <<-EOF
+ Create the necessary superuser auth policy necessary for performance replicaztion, assign it
+ to a our previously create test user, and enable performance replication on the primary
+ cluster.
+ EOF
+ module = module.vault_setup_perf_primary
depends_on = [
+ // Wait for both clusters to be up and healthy...
step.get_primary_cluster_ips,
step.get_secondary_cluster_ips,
- step.write_test_data_on_primary
+ step.write_test_data_on_primary,
+ // Wait base verification to complete...
+ step.verify_vault_version,
+ step.verify_ui,
]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_auth_userpass_user_write,
+ quality.vault_api_sys_policy_write,
+ quality.vault_api_sys_replication_performance_primary_enable_write,
+ quality.vault_cli_policy_write,
+ ]
+
variables {
- primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
- primary_leader_private_ip = step.get_primary_cluster_ips.leader_private_ip
- vault_install_dir = local.vault_install_dir
- vault_root_token = step.create_primary_cluster.root_token
+ primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ vault_root_token = step.create_primary_cluster.root_token
}
}
step "generate_secondary_token" {
- module = module.generate_secondary_token
- depends_on = [step.configure_performance_replication_primary]
+ description = <<-EOF
+ Generate a random token and configure the performance replication primary secondary-token and
+ configure the Vault cluster primary replication with the token. Export the wrapping token
+ so that secondary clusters can utilize it.
+ EOF
+ module = module.generate_secondary_token
+ depends_on = [step.configure_performance_replication_primary]
+
+ verifies = quality.vault_api_sys_replication_performance_primary_secondary_token_write
providers = {
enos = local.enos_provider[matrix.distro]
@@ -517,32 +755,43 @@ scenario "replication" {
variables {
primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
- vault_install_dir = local.vault_install_dir
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_primary_cluster.root_token
}
}
step "configure_performance_replication_secondary" {
- module = module.vault_setup_perf_secondary
- depends_on = [step.generate_secondary_token]
+ description = <<-EOF
+ Enable performance replication on the secondary cluster with the wrapping token created by
+ the primary cluster.
+ EOF
+ module = module.vault_setup_perf_secondary
+ depends_on = [step.generate_secondary_token]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_api_sys_replication_performance_secondary_enable_write
+
variables {
- secondary_leader_public_ip = step.get_secondary_cluster_ips.leader_public_ip
- secondary_leader_private_ip = step.get_secondary_cluster_ips.leader_private_ip
- vault_install_dir = local.vault_install_dir
- vault_root_token = step.create_secondary_cluster.root_token
- wrapping_token = step.generate_secondary_token.secondary_token
+ secondary_leader_public_ip = step.get_secondary_cluster_ips.leader_public_ip
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ vault_root_token = step.create_secondary_cluster.root_token
+ wrapping_token = step.generate_secondary_token.secondary_token
}
}
- // After replication is enabled, the secondary cluster followers need to be unsealed
- // Secondary unseal keys are passed using the guide https://developer.hashicorp.com/vault/docs/enterprise/replication#seals
step "unseal_secondary_followers" {
- module = module.vault_unseal_nodes
+ description = <<-EOF
+ After replication is enabled the secondary cluster followers need to be unsealed.
+ Secondary unseal keys are passed differently depending primary and secondary seal
+ type combinations. See the guide for more information:
+ https://developer.hashicorp.com/vault/docs/enterprise/replication#seals
+ EOF
+ module = module.vault_unseal_nodes
depends_on = [
step.create_primary_cluster,
step.create_secondary_cluster,
@@ -555,15 +804,17 @@ scenario "replication" {
}
variables {
- follower_public_ips = step.get_secondary_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
- vault_unseal_keys = matrix.primary_seal == "shamir" ? step.create_primary_cluster.unseal_keys_hex : step.create_primary_cluster.recovery_keys_hex
- vault_seal_type = matrix.primary_seal == "shamir" ? matrix.primary_seal : matrix.secondary_seal
+ hosts = step.get_secondary_cluster_ips.follower_hosts
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ vault_seal_type = matrix.primary_seal == "shamir" ? matrix.primary_seal : matrix.secondary_seal
+ vault_unseal_keys = matrix.primary_seal == "shamir" ? step.create_primary_cluster.unseal_keys_hex : step.create_primary_cluster.recovery_keys_hex
}
}
step "verify_secondary_cluster_is_unsealed_after_enabling_replication" {
- module = module.vault_verify_unsealed
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
depends_on = [
step.unseal_secondary_followers
]
@@ -572,31 +823,52 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_auto_unseals_after_autopilot_upgrade,
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_secondary_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_secondary_cluster_targets.hosts
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_performance_replication" {
- module = module.vault_verify_performance_replication
- depends_on = [step.verify_secondary_cluster_is_unsealed_after_enabling_replication]
+ description = <<-EOF
+ Verify that the performance replication status meets our expectations after enabling replication
+ and ensuring that all secondary nodes are unsealed.
+ EOF
+ module = module.vault_verify_performance_replication
+ depends_on = [step.verify_secondary_cluster_is_unsealed_after_enabling_replication]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_replication_performance_read_connection_status_connected,
+ quality.vault_api_sys_replication_performance_status_read,
+ quality.vault_api_sys_replication_performance_status_read_cluster_address,
+ quality.vault_api_sys_replication_performance_status_read_state_not_idle,
+ quality.vault_api_sys_replication_performance_status_known_primary_cluster_addrs,
+ ]
+
variables {
- primary_leader_public_ip = step.get_primary_cluster_ips.leader_public_ip
- primary_leader_private_ip = step.get_primary_cluster_ips.leader_private_ip
- secondary_leader_public_ip = step.get_secondary_cluster_ips.leader_public_ip
- secondary_leader_private_ip = step.get_secondary_cluster_ips.leader_private_ip
- vault_install_dir = local.vault_install_dir
+ ip_version = matrix.ip_version
+ primary_leader_host = step.get_primary_cluster_ips.leader_host
+ secondary_leader_host = step.get_secondary_cluster_ips.leader_host
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_replicated_data" {
- module = module.vault_verify_read_data
+ description = global.description.verify_read_test_data
+ module = module.vault_verify_read_data
depends_on = [
step.verify_performance_replication,
step.get_secondary_cluster_ips,
@@ -607,14 +879,21 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_secrets_kv_read
+
variables {
- node_public_ips = step.get_secondary_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_secondary_cluster_ips.follower_hosts
+ vault_addr = step.create_secondary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "add_additional_nodes_to_primary_cluster" {
- module = module.vault_cluster
+ description = <<-EOF
+ Add additional nodes the Vault Cluster to prepare for our catostrophic failure simulation.
+ These nodes will use a different storage storage_node_prefix
+ EOF
+ module = module.vault_cluster
depends_on = [
step.create_vpc,
step.create_primary_backend_cluster,
@@ -627,52 +906,100 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // unique to this invocation of the module
+ quality.vault_autojoins_new_nodes_into_initialized_cluster,
+ // verified in modules
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_service_systemd_notified,
+ quality.vault_service_systemd_unit,
+ quality.vault_cli_status_exit_code,
+ ]
+
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
backend_cluster_name = step.create_primary_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
cluster_name = step.create_primary_cluster_targets.cluster_name
config_mode = matrix.config_mode
- consul_license = (matrix.primary_backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.primary_backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
consul_release = matrix.primary_backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
force_unseal = matrix.primary_seal == "shamir"
- initialize_cluster = false
- install_dir = local.vault_install_dir
- license = matrix.edition != "ce" ? step.read_vault_license.license : null
- local_artifact_path = local.artifact_path
- manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
- root_token = step.create_primary_cluster.root_token
- seal_attributes = step.create_primary_seal_key.attributes
- seal_type = matrix.primary_seal
- shamir_unseal_keys = matrix.primary_seal == "shamir" ? step.create_primary_cluster.unseal_keys_hex : null
- storage_backend = matrix.primary_backend
- storage_node_prefix = "newprimary_node"
- target_hosts = step.create_primary_cluster_additional_targets.hosts
+ hosts = step.create_primary_cluster_additional_targets.hosts
+ // Don't init when adding nodes into the cluster.
+ initialize_cluster = false
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
+ license = matrix.edition != "ce" ? step.read_vault_license.license : null
+ local_artifact_path = local.artifact_path
+ manage_service = local.manage_service
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
+ root_token = step.create_primary_cluster.root_token
+ seal_attributes = step.create_primary_seal_key.attributes
+ seal_type = matrix.primary_seal
+ shamir_unseal_keys = matrix.primary_seal == "shamir" ? step.create_primary_cluster.unseal_keys_hex : null
+ storage_backend = matrix.primary_backend
+ storage_node_prefix = "newprimary_node"
}
}
step "verify_additional_primary_nodes_are_unsealed" {
- module = module.vault_verify_unsealed
- depends_on = [step.add_additional_nodes_to_primary_cluster]
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
+ depends_on = [step.add_additional_nodes_to_primary_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_auto_unseals_after_autopilot_upgrade,
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_primary_cluster_additional_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_primary_cluster_additional_targets.hosts
+ vault_addr = step.add_additional_nodes_to_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_raft_auto_join_voter" {
- skip_step = matrix.primary_backend != "raft"
- module = module.vault_verify_raft_auto_join_voter
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+ skip_step = matrix.primary_backend != "raft"
+ module = module.vault_verify_raft_auto_join_voter
depends_on = [
step.add_additional_nodes_to_primary_cluster,
step.create_primary_cluster,
@@ -683,18 +1010,25 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_raft_voters
+
variables {
- vault_instances = step.create_primary_cluster_additional_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_primary_cluster_additional_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_primary_cluster.root_token
}
}
step "remove_primary_follower_1" {
- module = module.shutdown_node
+ description = <<-EOF
+ Simulate a catostrophic failure by forcefully removing the a follower node from the Vault
+ Cluster.
+ EOF
+ module = module.shutdown_node
depends_on = [
- step.get_primary_cluster_replication_data,
- step.verify_additional_primary_nodes_are_unsealed
+ step.verify_additional_primary_nodes_are_unsealed,
]
providers = {
@@ -702,12 +1036,16 @@ scenario "replication" {
}
variables {
- node_public_ip = step.get_primary_cluster_replication_data.follower_public_ip_1
+ host = step.get_primary_cluster_ips.follower_hosts["0"]
}
}
step "remove_primary_leader" {
- module = module.shutdown_node
+ description = <<-EOF
+ Simulate a catostrophic failure by forcefully removing the the primary leader node from the
+ Vault Cluster without allowing a graceful shutdown.
+ EOF
+ module = module.shutdown_node
depends_on = [
step.get_primary_cluster_ips,
step.remove_primary_follower_1
@@ -718,13 +1056,19 @@ scenario "replication" {
}
variables {
- node_public_ip = step.get_primary_cluster_ips.leader_public_ip
+ host = step.get_primary_cluster_ips.leader_host
}
}
- // After we've removed two nodes from the cluster we need to get an updated set of vault hosts
- // to work with.
step "get_remaining_hosts_replication_data" {
+ description = <<-EOF
+ An arithmetic module that we use to determine various metadata about the the leader and
+ follower nodes of the primary cluster so that we can correctly enable performance replication.
+
+ We execute this to determine information about our hosts after having forced the leader
+ and a follower from the cluster.
+ EOF
+
module = module.replication_data
depends_on = [
step.get_primary_cluster_ips,
@@ -733,17 +1077,15 @@ scenario "replication" {
variables {
added_hosts = step.create_primary_cluster_additional_targets.hosts
- added_hosts_count = var.vault_instance_count
initial_hosts = step.create_primary_cluster_targets.hosts
- initial_hosts_count = var.vault_instance_count
- removed_follower_host = step.get_primary_cluster_replication_data.follower_host_1
+ removed_follower_host = step.get_primary_cluster_ips.follower_hosts["0"]
removed_primary_host = step.get_primary_cluster_ips.leader_host
}
}
- // Wait for the remaining hosts in our cluster to elect a new leader.
step "wait_for_leader_in_remaining_hosts" {
- module = module.vault_wait_for_leader
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
depends_on = [
step.remove_primary_leader,
step.get_remaining_hosts_replication_data,
@@ -753,17 +1095,24 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_remaining_hosts_replication_data.remaining_hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_primary_cluster.root_token
- vault_hosts = step.get_remaining_hosts_replication_data.remaining_hosts
}
}
- // Get our new leader and follower IP addresses.
step "get_updated_primary_cluster_ips" {
- module = module.vault_get_cluster_ips
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
depends_on = [
step.get_remaining_hosts_replication_data,
step.wait_for_leader_in_remaining_hosts,
@@ -773,16 +1122,27 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.get_remaining_hosts_replication_data.remaining_hosts
- vault_install_dir = local.vault_install_dir
- vault_instance_count = step.get_remaining_hosts_replication_data.remaining_hosts_count
- vault_root_token = step.create_primary_cluster.root_token
+ hosts = step.get_remaining_hosts_replication_data.remaining_hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ vault_root_token = step.create_primary_cluster.root_token
}
}
- // Make sure the cluster has the correct performance replication state after the new leader election.
step "verify_updated_performance_replication" {
+ description = <<-EOF
+ Verify that the performance replication status meets our expectations after the new leader
+ election.
+ EOF
+
module = module.vault_verify_performance_replication
depends_on = [
step.get_remaining_hosts_replication_data,
@@ -794,12 +1154,20 @@ scenario "replication" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_replication_performance_read_connection_status_connected,
+ quality.vault_api_sys_replication_performance_status_known_primary_cluster_addrs,
+ quality.vault_api_sys_replication_performance_status_read,
+ quality.vault_api_sys_replication_performance_status_read_state_not_idle,
+ quality.vault_api_sys_replication_performance_status_read_cluster_address,
+ ]
+
variables {
- primary_leader_public_ip = step.get_updated_primary_cluster_ips.leader_public_ip
- primary_leader_private_ip = step.get_updated_primary_cluster_ips.leader_private_ip
- secondary_leader_public_ip = step.get_secondary_cluster_ips.leader_public_ip
- secondary_leader_private_ip = step.get_secondary_cluster_ips.leader_private_ip
- vault_install_dir = local.vault_install_dir
+ ip_version = matrix.ip_version
+ primary_leader_host = step.get_updated_primary_cluster_ips.leader_host
+ secondary_leader_host = step.get_secondary_cluster_ips.leader_host
+ vault_addr = step.create_primary_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
@@ -874,7 +1242,7 @@ scenario "replication" {
}
output "initial_known_primary_cluster_addresses" {
- description = "The Vault secondary cluster performance replication status"
+ description = "The initial known Vault primary cluster addresses"
value = step.verify_performance_replication.known_primary_cluster_addrs
}
@@ -889,7 +1257,7 @@ scenario "replication" {
}
output "initial_secondary_replication_data_primaries" {
- description = "The Vault secondary cluster primaries connection status"
+ description = "The Vault secondary cluster primaries connection status"
value = step.verify_performance_replication.secondary_replication_data_primaries
}
diff --git a/enos/enos-scenario-seal-ha.hcl b/enos/enos-scenario-seal-ha.hcl
index 0d02d1225a..918ea2f082 100644
--- a/enos/enos-scenario-seal-ha.hcl
+++ b/enos/enos-scenario-seal-ha.hcl
@@ -1,41 +1,73 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "seal_ha" {
+ description = <<-EOF
+ The seal_ha scenario verifies Vault Enterprises seal HA capabilities. The build can be a local
+ branch, any CRT built Vault Enterprise artifact saved to the local machine, or any CRT built
+ Vault Enterprise artifact in the stable channel in Artifactory.
+
+ The scenario deploys a Vault Enterprise cluster with the candidate build and enables a single
+ primary seal, mounts various engines and writes data, then establishes seal HA with a secondary
+ seal, the removes the primary and verifies data integrity and seal data migration. It also
+ verifies that the cluster is able to recover from a forced leader election after the initial
+ seal rewrap. The scenario also performs standard baseline verification that is not specific to
+ seal_ha.
+
+ If you want to use the 'distro:leap' variant you must first accept SUSE's terms for the AWS
+ account. To verify that your account has agreed, sign-in to your AWS through Doormat,
+ and visit the following links to verify your subscription or subscribe:
+ arm64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+ amd64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+ EOF
+
matrix {
arch = global.archs
artifact_source = global.artifact_sources
artifact_type = global.artifact_types
backend = global.backends
config_mode = global.config_modes
+ consul_edition = global.consul_editions
consul_version = global.consul_versions
distro = global.distros
- edition = global.editions
+ edition = global.enterprise_editions
+ ip_version = global.ip_versions
// Seal HA is only supported with auto-unseal devices.
primary_seal = ["awskms", "pkcs11"]
secondary_seal = ["awskms", "pkcs11"]
- # Our local builder always creates bundles
+ // Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}
- # HSM and FIPS 140-2 are only supported on amd64
- exclude {
- arch = ["arm64"]
- edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
- }
-
- # PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
+ // PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
exclude {
primary_seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
}
exclude {
secondary_seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
+ }
+
+ // softhsm packages not available for leap/sles.
+ exclude {
+ primary_seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ exclude {
+ secondary_seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ // Testing in IPV6 mode is currently implemented for integrated Raft storage only
+ exclude {
+ ip_version = ["6"]
+ backend = ["consul"]
}
}
@@ -43,27 +75,31 @@ scenario "seal_ha" {
terraform = terraform.default
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
locals {
artifact_path = matrix.artifact_source != "artifactory" ? abspath(var.vault_artifact_path) : null
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
- manage_service = matrix.artifact_type == "bundle"
- vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
+ manage_service = matrix.artifact_type == "bundle"
}
step "get_local_metadata" {
- skip_step = matrix.artifact_source != "local"
- module = module.get_local_metadata
+ description = global.description.get_local_metadata
+ skip_step = matrix.artifact_source != "local"
+ module = module.get_local_metadata
}
step "build_vault" {
- module = "build_${matrix.artifact_source}"
+ description = global.description.build_vault
+ module = "build_${matrix.artifact_source}"
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : global.build_tags[matrix.edition]
@@ -84,20 +120,46 @@ scenario "seal_ha" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = global.tags
+ ip_version = matrix.ip_version
+ }
+ }
+
+ // This step reads the contents of the backend license if we're using a Consul backend and
+ // the edition is "ent".
+ step "read_backend_license" {
+ description = global.description.read_backend_license
+ skip_step = matrix.backend == "raft" || matrix.consul_edition == "ce"
+ module = module.read_license
+
+ variables {
+ file_name = global.backend_license_path
+ }
+ }
+
+ step "read_vault_license" {
+ description = global.description.read_vault_license
+ skip_step = matrix.edition == "ce"
+ module = module.read_license
+
+ variables {
+ file_name = global.vault_license_path
}
}
step "create_primary_seal_key" {
- module = "seal_${matrix.primary_seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.primary_seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -111,8 +173,9 @@ scenario "seal_ha" {
}
step "create_secondary_seal_key" {
- module = "seal_${matrix.secondary_seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.secondary_seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -126,29 +189,10 @@ scenario "seal_ha" {
}
}
- // This step reads the contents of the backend license if we're using a Consul backend and
- // the edition is "ent".
- step "read_backend_license" {
- skip_step = matrix.backend == "raft" || var.backend_edition == "ce"
- module = module.read_license
-
- variables {
- file_name = global.backend_license_path
- }
- }
-
- step "read_vault_license" {
- skip_step = matrix.edition == "ce"
- module = module.read_license
-
- variables {
- file_name = global.vault_license_path
- }
- }
-
step "create_vault_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
@@ -164,15 +208,16 @@ scenario "seal_ha" {
}
step "create_vault_cluster_backend_targets" {
- module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_secondary_seal_key.resource_names
@@ -181,7 +226,8 @@ scenario "seal_ha" {
}
step "create_backend_cluster" {
- module = "backend_${matrix.backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.backend}"
depends_on = [
step.create_vault_cluster_backend_targets
]
@@ -190,20 +236,38 @@ scenario "seal_ha" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_server,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_cli_validate,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_notified,
+ quality.consul_service_systemd_unit,
+ ]
+
variables {
cluster_name = step.create_vault_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
- license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_vault_cluster_backend_targets.hosts
+ license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
}
- target_hosts = step.create_vault_cluster_backend_targets.hosts
}
}
step "create_vault_cluster" {
- module = module.vault_cluster
+ description = global.description.create_vault_cluster
+ module = module.vault_cluster
depends_on = [
step.create_backend_cluster,
step.build_vault,
@@ -214,80 +278,141 @@ scenario "seal_ha" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_cli_status_exit_code,
+ quality.vault_service_systemd_notified,
+ quality.vault_service_systemd_unit,
+ ]
+
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
backend_cluster_name = step.create_vault_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
cluster_name = step.create_vault_cluster_targets.cluster_name
config_mode = matrix.config_mode
- consul_license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
consul_release = matrix.backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
- install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
local_artifact_path = local.artifact_path
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
// Only configure our primary seal during our initial cluster setup
seal_attributes = step.create_primary_seal_key.attributes
seal_type = matrix.primary_seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
// Wait for our cluster to elect a leader
step "wait_for_leader" {
- module = module.vault_wait_for_leader
- depends_on = [step.create_vault_cluster]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_vault_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_leader]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_vault_unsealed" {
- module = module.vault_verify_unsealed
- depends_on = [step.wait_for_leader]
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
+ depends_on = [step.wait_for_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
// Write some test data before we create the new seal
step "verify_write_test_data" {
- module = module.vault_verify_write_data
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_write_data
depends_on = [
step.create_vault_cluster,
step.get_vault_cluster_ips,
@@ -298,18 +423,26 @@ scenario "seal_ha" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
+ ]
+
variables {
- leader_public_ip = step.get_vault_cluster_ips.leader_public_ip
- leader_private_ip = step.get_vault_cluster_ips.leader_private_ip
- vault_instances = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ leader_host = step.get_vault_cluster_ips.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Wait for the initial seal rewrap to complete before we add our HA seal.
step "wait_for_initial_seal_rewrap" {
- module = module.vault_wait_for_seal_rewrap
+ description = global.description.wait_for_seal_rewrap
+ module = module.vault_wait_for_seal_rewrap
depends_on = [
step.verify_write_test_data,
]
@@ -318,16 +451,24 @@ scenario "seal_ha" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_sealwrap_rewrap_read_entries_processed_eq_entries_succeeded_post_rewrap,
+ quality.vault_api_sys_sealwrap_rewrap_read_entries_processed_gt_zero_post_rewrap,
+ quality.vault_api_sys_sealwrap_rewrap_read_is_running_false_post_rewrap,
+ quality.vault_api_sys_sealwrap_rewrap_read_no_entries_fail_during_rewrap,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
- // Stop the vault service on all nodes before we restart with new seal config
step "stop_vault" {
- module = module.stop_vault
+ description = "${global.description.stop_vault}. We do this to write new seal configuration."
+ module = module.stop_vault
depends_on = [
step.create_vault_cluster,
step.verify_write_test_data,
@@ -339,22 +480,27 @@ scenario "seal_ha" {
}
variables {
- target_hosts = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
}
}
// Add the secondary seal to the cluster
step "add_ha_seal_to_cluster" {
- module = module.start_vault
- depends_on = [step.stop_vault]
+ description = global.description.enable_multiseal
+ module = module.start_vault
+ depends_on = [step.stop_vault]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_multiseal_enable
+
variables {
cluster_name = step.create_vault_cluster_targets.cluster_name
- install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
manage_service = local.manage_service
seal_attributes = step.create_primary_seal_key.attributes
@@ -362,107 +508,156 @@ scenario "seal_ha" {
seal_type = matrix.primary_seal
seal_type_secondary = matrix.secondary_seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
// Wait for our cluster to elect a leader
step "wait_for_leader_election" {
- module = module.vault_wait_for_leader
- depends_on = [step.add_ha_seal_to_cluster]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.add_ha_seal_to_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_leader_ip_for_step_down" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_leader_election]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader_election]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Force a step down to trigger a new leader election
step "vault_leader_step_down" {
- module = module.vault_step_down
- depends_on = [step.get_leader_ip_for_step_down]
+ description = global.description.vault_leader_step_down
+ module = module.vault_step_down
+ depends_on = [step.get_leader_ip_for_step_down]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_step_down_steps_down,
+ quality.vault_cli_operator_step_down,
+ ]
+
variables {
- vault_install_dir = local.vault_install_dir
leader_host = step.get_leader_ip_for_step_down.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Wait for our cluster to elect a leader
step "wait_for_new_leader" {
- module = module.vault_wait_for_leader
- depends_on = [step.vault_leader_step_down]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.vault_leader_step_down]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ timeout = 120 // seconds
+ ip_version = matrix.ip_version
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_updated_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_new_leader]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_new_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_vault_unsealed_with_new_seal" {
- module = module.vault_verify_unsealed
- depends_on = [step.wait_for_new_leader]
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
+ depends_on = [step.wait_for_new_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
// Wait for the seal rewrap to complete and verify that no entries failed
step "wait_for_seal_rewrap" {
- module = module.vault_wait_for_seal_rewrap
+ description = global.description.wait_for_seal_rewrap
+ module = module.vault_wait_for_seal_rewrap
depends_on = [
step.add_ha_seal_to_cluster,
step.verify_vault_unsealed_with_new_seal,
@@ -472,26 +667,44 @@ scenario "seal_ha" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_sealwrap_rewrap_read_entries_processed_eq_entries_succeeded_post_rewrap,
+ quality.vault_api_sys_sealwrap_rewrap_read_entries_processed_gt_zero_post_rewrap,
+ quality.vault_api_sys_sealwrap_rewrap_read_is_running_false_post_rewrap,
+ quality.vault_api_sys_sealwrap_rewrap_read_no_entries_fail_during_rewrap,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Perform all of our standard verifications after we've enabled multiseal
step "verify_vault_version" {
- module = module.vault_verify_version
- depends_on = [step.wait_for_seal_rewrap]
+ description = global.description.verify_vault_version
+ module = module.vault_verify_version
+ depends_on = [step.wait_for_seal_rewrap]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_version_history_keys,
+ quality.vault_api_sys_version_history_key_info,
+ quality.vault_version_build_date,
+ quality.vault_version_edition,
+ quality.vault_version_release,
+ ]
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_revision = matrix.artifact_source == "local" ? step.get_local_metadata.revision : var.vault_revision
vault_build_date = matrix.artifact_source == "local" ? step.get_local_metadata.build_date : var.vault_build_date
@@ -500,66 +713,86 @@ scenario "seal_ha" {
}
step "verify_raft_auto_join_voter" {
- skip_step = matrix.backend != "raft"
- module = module.vault_verify_raft_auto_join_voter
- depends_on = [step.wait_for_seal_rewrap]
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+ skip_step = matrix.backend != "raft"
+ module = module.vault_verify_raft_auto_join_voter
+ depends_on = [step.wait_for_seal_rewrap]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_raft_voters
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_replication" {
- module = module.vault_verify_replication
- depends_on = [step.wait_for_seal_rewrap]
+ description = global.description.verify_replication_status
+ module = module.vault_verify_replication
+ depends_on = [step.wait_for_seal_rewrap]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_replication_ce_disabled,
+ quality.vault_replication_ent_dr_available,
+ quality.vault_replication_ent_pr_available,
+ ]
+
variables {
- vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_edition = matrix.edition
}
}
// Make sure our data is still available
step "verify_read_test_data" {
- module = module.vault_verify_read_data
- depends_on = [step.wait_for_seal_rewrap]
+ description = global.description.verify_read_test_data
+ module = module.vault_verify_read_data
+ depends_on = [step.wait_for_seal_rewrap]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_secrets_kv_read
+
variables {
- node_public_ips = step.get_updated_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_updated_cluster_ips.follower_hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_ui" {
- module = module.vault_verify_ui
- depends_on = [step.wait_for_seal_rewrap]
+ description = global.description.verify_ui
+ module = module.vault_verify_ui
+ depends_on = [step.wait_for_seal_rewrap]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_ui_assets
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
}
}
- // Make sure we have a "multiseal" seal type
step "verify_seal_type" {
+ description = "${global.description.verify_seal_type} In this case we expect to have 'multiseal'."
// Don't run this on versions less than 1.16.0-beta1 until VAULT-21053 is fixed on prior branches.
skip_step = semverconstraint(var.vault_product_version, "< 1.16.0-beta1")
module = module.verify_seal_type
@@ -569,10 +802,13 @@ scenario "seal_ha" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_status_seal_type
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_hosts = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
seal_type = "multiseal"
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
@@ -580,7 +816,8 @@ scenario "seal_ha" {
// Stop the vault service on all nodes before we restart with new seal config
step "stop_vault_for_migration" {
- module = module.stop_vault
+ description = "${global.description.stop_vault}. We do this to remove the old primary seal."
+ module = module.stop_vault
depends_on = [
step.wait_for_seal_rewrap,
step.verify_read_test_data,
@@ -591,62 +828,86 @@ scenario "seal_ha" {
}
variables {
- target_hosts = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
}
}
// Remove the "primary" seal from the cluster. Set our "secondary" seal to priority 1. We do this
// by restarting vault with the correct config.
step "remove_primary_seal" {
- module = module.start_vault
- depends_on = [step.stop_vault_for_migration]
+ description = <<-EOF
+ Reconfigure the vault cluster seal configuration with only our secondary seal config which
+ will force a seal migration to a single seal.
+ EOF
+ module = module.start_vault
+ depends_on = [step.stop_vault_for_migration]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_config_multiseal_is_toggleable
+
variables {
cluster_name = step.create_vault_cluster_targets.cluster_name
- install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
manage_service = local.manage_service
seal_alias = "secondary"
seal_attributes = step.create_secondary_seal_key.attributes
seal_type = matrix.secondary_seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
// Wait for our cluster to elect a leader after restarting vault with a new primary seal
step "wait_for_leader_after_migration" {
- module = module.vault_wait_for_leader
- depends_on = [step.remove_primary_seal]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.remove_primary_seal]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ timeout = 120 // seconds
+ ip_version = matrix.ip_version
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Since we've restarted our cluster we might have a new leader and followers. Get the new IPs.
step "get_cluster_ips_after_migration" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_leader_after_migration]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader_after_migration]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
@@ -661,8 +922,9 @@ scenario "seal_ha" {
}
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
@@ -679,8 +941,9 @@ scenario "seal_ha" {
}
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
@@ -695,8 +958,9 @@ scenario "seal_ha" {
}
variables {
- node_public_ips = step.get_cluster_ips_after_migration.follower_public_ips
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_cluster_ips_after_migration.follower_hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
@@ -712,9 +976,10 @@ scenario "seal_ha" {
}
variables {
- vault_install_dir = local.vault_install_dir
- vault_hosts = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
seal_type = matrix.secondary_seal
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
@@ -730,7 +995,7 @@ scenario "seal_ha" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "initial_seal_rewrap" {
diff --git a/enos/enos-scenario-smoke.hcl b/enos/enos-scenario-smoke.hcl
index 2a4675c1a1..2aaf3919e6 100644
--- a/enos/enos-scenario-smoke.hcl
+++ b/enos/enos-scenario-smoke.hcl
@@ -1,34 +1,57 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "smoke" {
+ description = <<-EOF
+ The smoke scenario verifies a Vault cluster in a fresh installation. The build can be a local
+ branch, any CRT built Vault artifact saved to the local machine, or any CRT built Vault artifact
+ in the stable channel in Artifactory.
+
+ The scenario deploys a Vault cluster with the candidate build performs an extended set of
+ baseline verification.
+
+ If you want to use the 'distro:leap' variant you must first accept SUSE's terms for the AWS
+ account. To verify that your account has agreed, sign-in to your AWS through Doormat,
+ and visit the following links to verify your subscription or subscribe:
+ arm64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+ amd64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+ EOF
+
matrix {
arch = global.archs
artifact_source = global.artifact_sources
artifact_type = global.artifact_types
backend = global.backends
config_mode = global.config_modes
+ consul_edition = global.consul_editions
consul_version = global.consul_versions
distro = global.distros
edition = global.editions
+ ip_version = global.ip_versions
seal = global.seals
- # Our local builder always creates bundles
+ // Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}
- # HSM and FIPS 140-2 are only supported on amd64
- exclude {
- arch = ["arm64"]
- edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
- }
-
- # PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
+ // PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
exclude {
seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
+ }
+
+ // softhsm packages not available for leap/sles.
+ exclude {
+ seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ // Testing in IPV6 mode is currently implemented for integrated Raft storage only
+ exclude {
+ ip_version = ["6"]
+ backend = ["consul"]
}
}
@@ -36,27 +59,25 @@ scenario "smoke" {
terraform = terraform.default
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
locals {
artifact_path = matrix.artifact_source != "artifactory" ? abspath(var.vault_artifact_path) : null
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
- manage_service = matrix.artifact_type == "bundle"
- vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
- }
-
- step "get_local_metadata" {
- skip_step = matrix.artifact_source != "local"
- module = module.get_local_metadata
+ manage_service = matrix.artifact_type == "bundle"
}
step "build_vault" {
- module = "build_${matrix.artifact_source}"
+ description = global.description.build_vault
+ module = "build_${matrix.artifact_source}"
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : global.build_tags[matrix.edition]
@@ -77,22 +98,24 @@ scenario "smoke" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = global.tags
+ ip_version = matrix.ip_version
}
}
- // This step reads the contents of the backend license if we're using a Consul backend and
- // the edition is "ent".
step "read_backend_license" {
- skip_step = matrix.backend == "raft" || var.backend_edition == "ce"
- module = module.read_license
+ description = global.description.read_backend_license
+ module = module.read_license
+ skip_step = matrix.backend == "raft" || matrix.consul_edition == "ce"
variables {
file_name = global.backend_license_path
@@ -100,8 +123,9 @@ scenario "smoke" {
}
step "read_vault_license" {
- skip_step = matrix.edition == "ce"
- module = module.read_license
+ description = global.description.read_vault_license
+ skip_step = matrix.edition == "ce"
+ module = module.read_license
variables {
file_name = global.vault_license_path
@@ -109,8 +133,9 @@ scenario "smoke" {
}
step "create_seal_key" {
- module = "seal_${matrix.seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -123,8 +148,9 @@ scenario "smoke" {
}
step "create_vault_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
@@ -140,15 +166,16 @@ scenario "smoke" {
}
step "create_vault_cluster_backend_targets" {
- module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_seal_key.resource_names
@@ -157,7 +184,8 @@ scenario "smoke" {
}
step "create_backend_cluster" {
- module = "backend_${matrix.backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.backend}"
depends_on = [
step.create_vault_cluster_backend_targets
]
@@ -166,20 +194,38 @@ scenario "smoke" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_server,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_cli_validate,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_notified,
+ quality.consul_service_systemd_unit,
+ ]
+
variables {
cluster_name = step.create_vault_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
- license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_vault_cluster_backend_targets.hosts
+ license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
}
- target_hosts = step.create_vault_cluster_backend_targets.hosts
}
}
step "create_vault_cluster" {
- module = module.vault_cluster
+ description = global.description.create_vault_cluster
+ module = module.vault_cluster
depends_on = [
step.create_backend_cluster,
step.build_vault,
@@ -190,122 +236,237 @@ scenario "smoke" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.consul_service_start_client,
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_cli_status_exit_code,
+ quality.vault_service_systemd_notified,
+ quality.vault_service_systemd_unit,
+ ]
+
variables {
artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
backend_cluster_name = step.create_vault_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
cluster_name = step.create_vault_cluster_targets.cluster_name
config_mode = matrix.config_mode
- consul_license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
consul_release = matrix.backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
- install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ install_dir = global.vault_install_dir[matrix.artifact_type]
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
local_artifact_path = local.artifact_path
manage_service = local.manage_service
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
seal_attributes = step.create_seal_key.attributes
seal_type = matrix.seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
+ step "get_local_metadata" {
+ description = global.description.get_local_metadata
+ skip_step = matrix.artifact_source != "local"
+ module = module.get_local_metadata
+ }
+
// Wait for our cluster to elect a leader
step "wait_for_new_leader" {
- module = module.vault_wait_for_leader
- depends_on = [step.create_vault_cluster]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_vault_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ timeout = 120 // seconds
+ ip_version = matrix.ip_version
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_leader_ip_for_step_down" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_new_leader]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_new_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Force a step down to trigger a new leader election
step "vault_leader_step_down" {
- module = module.vault_step_down
- depends_on = [step.get_leader_ip_for_step_down]
+ description = global.description.vault_leader_step_down
+ module = module.vault_step_down
+ depends_on = [step.get_leader_ip_for_step_down]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_step_down_steps_down,
+ quality.vault_cli_operator_step_down,
+ ]
+
variables {
- vault_install_dir = local.vault_install_dir
leader_host = step.get_leader_ip_for_step_down.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Wait for our cluster to elect a leader
step "wait_for_leader" {
- module = module.vault_wait_for_leader
- depends_on = [step.vault_leader_step_down]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.vault_leader_step_down]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_step_down,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ timeout = 120 // seconds
+ ip_version = matrix.ip_version
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_leader]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
- step "verify_vault_version" {
- module = module.vault_verify_version
- depends_on = [step.create_vault_cluster]
+ step "verify_vault_unsealed" {
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
+ depends_on = [step.wait_for_leader]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ }
+ }
+
+ step "verify_vault_version" {
+ description = global.description.verify_vault_version
+ module = module.vault_verify_version
+ depends_on = [step.verify_vault_unsealed]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_version_history_keys,
+ quality.vault_api_sys_version_history_key_info,
+ quality.vault_version_build_date,
+ quality.vault_version_edition,
+ quality.vault_version_release,
+ ]
+
+ variables {
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_revision = matrix.artifact_source == "local" ? step.get_local_metadata.revision : var.vault_revision
vault_build_date = matrix.artifact_source == "local" ? step.get_local_metadata.build_date : var.vault_build_date
@@ -313,79 +474,77 @@ scenario "smoke" {
}
}
- step "verify_vault_unsealed" {
- module = module.vault_verify_unsealed
- depends_on = [step.wait_for_leader]
+ step "verify_write_test_data" {
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_write_data
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
- variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
- }
- }
-
- step "verify_write_test_data" {
- module = module.vault_verify_write_data
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
+ verifies = [
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
]
- providers = {
- enos = local.enos_provider[matrix.distro]
- }
-
variables {
- leader_public_ip = step.get_vault_cluster_ips.leader_public_ip
- leader_private_ip = step.get_vault_cluster_ips.leader_private_ip
- vault_instances = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ leader_host = step.get_vault_cluster_ips.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_raft_auto_join_voter" {
- skip_step = matrix.backend != "raft"
- module = module.vault_verify_raft_auto_join_voter
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
- ]
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+ skip_step = matrix.backend != "raft"
+ module = module.vault_verify_raft_auto_join_voter
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_raft_voters
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_replication" {
- module = module.vault_verify_replication
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
- ]
+ description = global.description.verify_replication_status
+ module = module.vault_verify_replication
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_replication_ce_disabled,
+ quality.vault_replication_ent_dr_available,
+ quality.vault_replication_ent_pr_available,
+ ]
+
variables {
- vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_edition = matrix.edition
}
}
step "verify_read_test_data" {
- module = module.vault_verify_read_data
+ description = global.description.verify_read_test_data
+ module = module.vault_verify_read_data
depends_on = [
step.verify_write_test_data,
step.verify_replication
@@ -395,25 +554,29 @@ scenario "smoke" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_secrets_kv_read
+
variables {
- node_public_ips = step.get_vault_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_vault_cluster_ips.follower_hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_ui" {
- module = module.vault_verify_ui
- depends_on = [
- step.create_vault_cluster,
- step.get_vault_cluster_ips
- ]
+ description = global.description.verify_ui
+ module = module.vault_verify_ui
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_ui_assets
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
}
}
@@ -429,7 +592,7 @@ scenario "smoke" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "private_ips" {
diff --git a/enos/enos-scenario-ui.hcl b/enos/enos-scenario-ui.hcl
index 6e7e7c6126..0e1ee47ced 100644
--- a/enos/enos-scenario-ui.hcl
+++ b/enos/enos-scenario-ui.hcl
@@ -1,10 +1,21 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "ui" {
+ description = <<-EOF
+ The UI scenario is designed to create a new cluster and run the existing Ember test suite
+ against a live Vault cluster instead of a binary in dev mode.
+
+ The UI scenario verifies the Vault ember test suite against a Vault cluster. The build can be a
+ local branch, any CRT built Vault artifact saved to the local machine, or any CRT built Vault
+ artifact in the stable channel in Artifactory.
+
+ The scenario deploys a Vault cluster with the candidate build and executes the ember test suite.
+ EOF
matrix {
- backend = global.backends
- edition = ["ce", "ent"]
+ backend = global.backends
+ consul_edition = global.consul_editions
+ edition = ["ce", "ent"]
}
terraform_cli = terraform_cli.default
@@ -23,19 +34,16 @@ scenario "ui" {
"ce" = ["ui"]
"ent" = ["ui", "enterprise", "ent"]
}
- bundle_path = abspath(var.vault_artifact_path)
+ artifact_path = abspath(var.vault_artifact_path)
distro = "ubuntu"
consul_version = "1.17.0"
+ ip_version = 4
seal = "awskms"
tags = merge({
"Project Name" : var.project_name
"Project" : "Enos",
"Environment" : "ci"
}, var.tags)
- vault_install_dir_packages = {
- rhel = "/bin"
- ubuntu = "/usr/bin"
- }
vault_install_dir = var.vault_install_dir
vault_license_path = abspath(var.vault_license_path != null ? var.vault_license_path : joinpath(path.root, "./support/vault.hclic"))
vault_tag_key = "Type" // enos_vault_start expects Type as the tag key
@@ -43,11 +51,12 @@ scenario "ui" {
}
step "build_vault" {
- module = module.build_local
+ description = global.description.build_vault
+ module = module.build_local
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : local.build_tags[matrix.edition]
- bundle_path = local.bundle_path
+ artifact_path = local.artifact_path
goarch = local.arch
goos = "linux"
product_version = var.vault_product_version
@@ -57,31 +66,26 @@ scenario "ui" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = local.tags
- }
- }
-
- step "create_seal_key" {
- module = "seal_${local.seal}"
-
- variables {
- cluster_id = step.create_vpc.cluster_id
- common_tags = global.tags
+ ip_version = local.ip_version
}
}
// This step reads the contents of the backend license if we're using a Consul backend and
// the edition is "ent".
step "read_backend_license" {
- skip_step = matrix.backend == "raft" || var.backend_edition == "ce"
- module = module.read_license
+ description = global.description.read_backend_license
+ skip_step = matrix.backend == "raft" || matrix.consul_edition == "ce"
+ module = module.read_license
variables {
file_name = local.backend_license_path
@@ -89,50 +93,64 @@ scenario "ui" {
}
step "read_vault_license" {
- skip_step = matrix.edition == "ce"
- module = module.read_license
+ description = global.description.read_vault_license
+ skip_step = matrix.edition == "ce"
+ module = module.read_license
variables {
file_name = local.vault_license_path
}
}
+ step "create_seal_key" {
+ description = global.description.create_seal_key
+ module = "seal_${local.seal}"
+
+ variables {
+ cluster_id = step.create_vpc.cluster_id
+ common_tags = global.tags
+ }
+ }
+
step "create_vault_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids[local.arch][local.distro][var.ubuntu_distro_version]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = local.vault_tag_key
common_tags = local.tags
- seal_names = step.create_seal_key.resource_names
+ seal_key_names = step.create_seal_key.resource_names
vpc_id = step.create_vpc.id
}
}
step "create_vault_cluster_backend_targets" {
- module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = local.backend_tag_key
common_tags = local.tags
- seal_names = step.create_seal_key.resource_names
+ seal_key_names = step.create_seal_key.resource_names
vpc_id = step.create_vpc.id
}
}
step "create_backend_cluster" {
- module = "backend_${matrix.backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.backend}"
depends_on = [
step.create_vault_cluster_backend_targets,
]
@@ -141,20 +159,38 @@ scenario "ui" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_server,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_cli_validate,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_notified,
+ quality.consul_service_systemd_unit,
+ ]
+
variables {
cluster_name = step.create_vault_cluster_backend_targets.cluster_name
cluster_tag_key = local.backend_tag_key
- license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_vault_cluster_backend_targets.hosts
+ license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = local.consul_version
}
- target_hosts = step.create_vault_cluster_backend_targets.hosts
}
}
step "create_vault_cluster" {
- module = module.vault_cluster
+ description = global.description.create_vault_cluster
+ module = module.vault_cluster
depends_on = [
step.create_backend_cluster,
step.build_vault,
@@ -165,47 +201,98 @@ scenario "ui" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_service_start_client,
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_consul,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_cli_status_exit_code,
+ quality.vault_service_systemd_notified,
+ quality.vault_service_systemd_unit,
+ ]
+
variables {
backend_cluster_name = step.create_vault_cluster_backend_targets.cluster_name
backend_cluster_tag_key = local.backend_tag_key
cluster_name = step.create_vault_cluster_targets.cluster_name
- consul_license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ config_mode = "file"
+ consul_license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
consul_release = matrix.backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = local.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
+ hosts = step.create_vault_cluster_targets.hosts
install_dir = local.vault_install_dir
+ ip_version = local.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
- local_artifact_path = local.bundle_path
- packages = global.distro_packages["ubuntu"]
- seal_name = step.create_seal_key.resource_name
+ local_artifact_path = local.artifact_path
+ packages = concat(global.packages, global.distro_packages["ubuntu"][global.distro_version["ubuntu"]])
+ seal_attributes = step.create_seal_key.attributes
seal_type = local.seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
// Wait for our cluster to elect a leader
step "wait_for_leader" {
- module = module.vault_wait_for_leader
- depends_on = [step.create_vault_cluster]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_vault_cluster]
providers = {
enos = provider.enos.ubuntu
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
+ timeout = 120 // seconds
+ ip_version = local.ip_version
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_vault_cluster.root_token
}
}
step "test_ui" {
- module = module.vault_test_ui
- depends_on = [step.wait_for_leader]
+ description = <<-EOF
+ Verify that the Vault Web UI test suite can run against a live cluster with the compiled
+ assets.
+ EOF
+ module = module.vault_test_ui
+ depends_on = [step.wait_for_leader]
+
+ verifies = quality.vault_ui_test
variables {
vault_addr = step.create_vault_cluster_targets.hosts[0].public_ip
@@ -228,7 +315,7 @@ scenario "ui" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "private_ips" {
diff --git a/enos/enos-scenario-upgrade.hcl b/enos/enos-scenario-upgrade.hcl
index 1eb398511a..0dc244fa63 100644
--- a/enos/enos-scenario-upgrade.hcl
+++ b/enos/enos-scenario-upgrade.hcl
@@ -1,47 +1,80 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
scenario "upgrade" {
+ description = <<-EOF
+ The upgrade scenario verifies in-place upgrades between previously released versions of Vault
+ against another candidate build. The build can be a local branch, any CRT built Vault artifact
+ saved to the local machine, or any CRT built Vault artifact in the stable channel in
+ Artifactory.
+
+ The scenario will first create a new Vault Cluster with a previously released version of Vault,
+ mount engines and create data, then perform an in-place upgrade with any candidate built and
+ perform quality verification.
+
+ If you want to use the 'distro:leap' variant you must first accept SUSE's terms for the AWS
+ account. To verify that your account has agreed, sign-in to your AWS through Doormat,
+ and visit the following links to verify your subscription or subscribe:
+ arm64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+ amd64 AMI: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+ EOF
+
matrix {
arch = global.archs
artifact_source = global.artifact_sources
artifact_type = global.artifact_types
backend = global.backends
config_mode = global.config_modes
+ consul_edition = global.consul_editions
consul_version = global.consul_versions
distro = global.distros
edition = global.editions
- // NOTE: when backporting the initial version make sure we don't include initial versions that
- // are a higher minor version that our release candidate. Also, prior to 1.11.x the
- // /v1/sys/seal-status API has known issues that could cause this scenario to fail when using
- // those earlier versions, therefore support from 1.8.x to 1.10.x is unreliable. Prior to 1.8.x
- // is not supported due to changes with vault's signaling of systemd and the enos-provider
- // no longer supporting setting the license via the license API.
- initial_version = global.upgrade_initial_versions
+ initial_version = global.upgrade_initial_versions_ce
+ ip_version = global.ip_versions
seal = global.seals
- # Our local builder always creates bundles
+ // Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}
- # HSM and FIPS 140-2 are only supported on amd64
+ // Don't upgrade from super-ancient versions in CI because there are known reliability issues
+ // in those versions that have already been fixed.
+ exclude {
+ initial_version = [for e in matrix.initial_version : e if semverconstraint(e, "<1.11.0-0")]
+ }
+
+ // FIPS 140-2 editions were not supported until 1.11.x, even though there are 1.10.x binaries
+ // published.
+ exclude {
+ edition = ["ent.fips1402", "ent.hsm.fips1402"]
+ initial_version = [for e in matrix.initial_version : e if semverconstraint(e, "<1.11.0-0")]
+ }
+
+ // There are no published versions of these artifacts yet. We'll update this to exclude older
+ // versions after our initial publication of these editions for arm64.
exclude {
arch = ["arm64"]
edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
}
- # FIPS 140-2 editions began at 1.10
- exclude {
- edition = ["ent.fips1402", "ent.hsm.fips1402"]
- initial_version = ["1.8.12", "1.9.10"]
- }
-
- # PKCS#11 can only be used on ent.hsm and ent.hsm.fips1402.
+ // PKCS#11 can only be used with hsm editions
exclude {
seal = ["pkcs11"]
- edition = ["ce", "ent", "ent.fips1402"]
+ edition = [for e in matrix.edition : e if !strcontains(e, "hsm")]
+ }
+
+ // softhsm packages not available for leap/sles.
+ exclude {
+ seal = ["pkcs11"]
+ distro = ["leap", "sles"]
+ }
+
+ // Testing in IPV6 mode is currently implemented for integrated Raft storage only
+ exclude {
+ ip_version = ["6"]
+ backend = ["consul"]
}
}
@@ -49,28 +82,25 @@ scenario "upgrade" {
terraform = terraform.default
providers = [
provider.aws.default,
- provider.enos.ubuntu,
- provider.enos.rhel
+ provider.enos.ec2_user,
+ provider.enos.ubuntu
]
locals {
artifact_path = matrix.artifact_source != "artifactory" ? abspath(var.vault_artifact_path) : null
enos_provider = {
- rhel = provider.enos.rhel
+ amzn = provider.enos.ec2_user
+ leap = provider.enos.ec2_user
+ rhel = provider.enos.ec2_user
+ sles = provider.enos.ec2_user
ubuntu = provider.enos.ubuntu
}
- manage_service = matrix.artifact_type == "bundle"
- vault_install_dir = matrix.artifact_type == "bundle" ? var.vault_install_dir : global.vault_install_dir_packages[matrix.distro]
+ manage_service = matrix.artifact_type == "bundle"
}
- step "get_local_metadata" {
- skip_step = matrix.artifact_source != "local"
- module = module.get_local_metadata
- }
-
- # This step gets/builds the upgrade artifact that we will upgrade to
step "build_vault" {
- module = "build_${matrix.artifact_source}"
+ description = global.description.build_vault
+ module = "build_${matrix.artifact_source}"
variables {
build_tags = var.vault_local_build_tags != null ? var.vault_local_build_tags : global.build_tags[matrix.edition]
@@ -91,22 +121,26 @@ scenario "upgrade" {
}
step "ec2_info" {
- module = module.ec2_info
+ description = global.description.ec2_info
+ module = module.ec2_info
}
step "create_vpc" {
- module = module.create_vpc
+ description = global.description.create_vpc
+ module = module.create_vpc
variables {
common_tags = global.tags
+ ip_version = matrix.ip_version
}
}
// This step reads the contents of the backend license if we're using a Consul backend and
- // the edition is "ent".
+ // an "ent" Consul edition.
step "read_backend_license" {
- skip_step = matrix.backend == "raft" || var.backend_edition == "ce"
- module = module.read_license
+ description = global.description.read_backend_license
+ skip_step = matrix.backend == "raft" || matrix.consul_edition == "ce"
+ module = module.read_license
variables {
file_name = global.backend_license_path
@@ -114,8 +148,9 @@ scenario "upgrade" {
}
step "read_vault_license" {
- skip_step = matrix.edition == "ce"
- module = module.read_license
+ description = global.description.read_vault_license
+ skip_step = matrix.edition == "ce"
+ module = module.read_license
variables {
file_name = global.vault_license_path
@@ -123,8 +158,9 @@ scenario "upgrade" {
}
step "create_seal_key" {
- module = "seal_${matrix.seal}"
- depends_on = [step.create_vpc]
+ description = global.description.create_seal_key
+ module = "seal_${matrix.seal}"
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
@@ -137,8 +173,9 @@ scenario "upgrade" {
}
step "create_vault_cluster_targets" {
- module = module.target_ec2_instances
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = module.target_ec2_instances
+ depends_on = [step.create_vpc]
providers = {
enos = local.enos_provider[matrix.distro]
@@ -154,15 +191,16 @@ scenario "upgrade" {
}
step "create_vault_cluster_backend_targets" {
- module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
- depends_on = [step.create_vpc]
+ description = global.description.create_vault_cluster_targets
+ module = matrix.backend == "consul" ? module.target_ec2_instances : module.target_ec2_shim
+ depends_on = [step.create_vpc]
providers = {
enos = provider.enos.ubuntu
}
variables {
- ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"]["22.04"]
+ ami_id = step.ec2_info.ami_ids["arm64"]["ubuntu"][global.distro_version["ubuntu"]]
cluster_tag_key = global.backend_tag_key
common_tags = global.tags
seal_key_names = step.create_seal_key.resource_names
@@ -171,7 +209,8 @@ scenario "upgrade" {
}
step "create_backend_cluster" {
- module = "backend_${matrix.backend}"
+ description = global.description.create_backend_cluster
+ module = "backend_${matrix.backend}"
depends_on = [
step.create_vault_cluster_backend_targets,
]
@@ -180,20 +219,38 @@ scenario "upgrade" {
enos = provider.enos.ubuntu
}
+ verifies = [
+ // verified in modules
+ quality.consul_autojoin_aws,
+ quality.consul_config_file,
+ quality.consul_ha_leader_election,
+ quality.consul_service_start_server,
+ // verified in enos_consul_start resource
+ quality.consul_api_agent_host_read,
+ quality.consul_api_health_node_read,
+ quality.consul_api_operator_raft_config_read,
+ quality.consul_cli_validate,
+ quality.consul_health_state_passing_read_nodes_minimum,
+ quality.consul_operator_raft_configuration_read_voters_minimum,
+ quality.consul_service_systemd_notified,
+ quality.consul_service_systemd_unit,
+ ]
+
variables {
cluster_name = step.create_vault_cluster_backend_targets.cluster_name
cluster_tag_key = global.backend_tag_key
- license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ hosts = step.create_vault_cluster_backend_targets.hosts
+ license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
release = {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
}
- target_hosts = step.create_vault_cluster_backend_targets.hosts
}
}
step "create_vault_cluster" {
- module = module.vault_cluster
+ description = global.description.create_vault_cluster
+ module = module.vault_cluster
depends_on = [
step.create_backend_cluster,
step.build_vault,
@@ -204,20 +261,57 @@ scenario "upgrade" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ // verified in modules
+ quality.consul_service_start_client,
+ quality.vault_artifact_bundle,
+ quality.vault_artifact_deb,
+ quality.vault_artifact_rpm,
+ quality.vault_audit_log,
+ quality.vault_audit_socket,
+ quality.vault_audit_syslog,
+ quality.vault_autojoin_aws,
+ quality.vault_storage_backend_consul,
+ quality.vault_config_env_variables,
+ quality.vault_config_file,
+ quality.vault_config_log_level,
+ quality.vault_init,
+ quality.vault_license_required_ent,
+ quality.vault_listener_ipv4,
+ quality.vault_listener_ipv6,
+ quality.vault_service_start,
+ quality.vault_storage_backend_raft,
+ // verified in enos_vault_start resource
+ quality.vault_api_sys_config_read,
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_health_read,
+ quality.vault_api_sys_host_info_read,
+ quality.vault_api_sys_replication_status_read,
+ quality.vault_api_sys_seal_status_api_read_matches_sys_health,
+ quality.vault_api_sys_storage_raft_autopilot_configuration_read,
+ quality.vault_api_sys_storage_raft_autopilot_state_read,
+ quality.vault_api_sys_storage_raft_configuration_read,
+ quality.vault_cli_status_exit_code,
+ quality.vault_service_systemd_unit,
+ quality.vault_service_systemd_notified,
+ ]
+
variables {
backend_cluster_name = step.create_vault_cluster_backend_targets.cluster_name
backend_cluster_tag_key = global.backend_tag_key
cluster_name = step.create_vault_cluster_targets.cluster_name
config_mode = matrix.config_mode
- consul_license = (matrix.backend == "consul" && var.backend_edition == "ent") ? step.read_backend_license.license : null
+ consul_license = (matrix.backend == "consul" && matrix.consul_edition == "ent") ? step.read_backend_license.license : null
consul_release = matrix.backend == "consul" ? {
- edition = var.backend_edition
+ edition = matrix.consul_edition
version = matrix.consul_version
} : null
enable_audit_devices = var.vault_enable_audit_devices
- install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
license = matrix.edition != "ce" ? step.read_vault_license.license : null
- packages = concat(global.packages, global.distro_packages[matrix.distro])
+ manage_service = true # always handle systemd for released bundles
+ packages = concat(global.packages, global.distro_packages[matrix.distro][global.distro_version[matrix.distro]])
release = {
edition = matrix.edition
version = matrix.initial_version
@@ -225,27 +319,69 @@ scenario "upgrade" {
seal_attributes = step.create_seal_key.attributes
seal_type = matrix.seal
storage_backend = matrix.backend
- target_hosts = step.create_vault_cluster_targets.hosts
}
}
- step "get_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
- depends_on = [step.create_vault_cluster]
+ step "get_local_metadata" {
+ description = global.description.get_local_metadata
+ skip_step = matrix.artifact_source != "local"
+ module = module.get_local_metadata
+ }
+
+ // Wait for our cluster to elect a leader
+ step "wait_for_leader" {
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.create_vault_cluster]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ // Use the install dir for our initial version, which always comes from a zip bundle
+ vault_install_dir = global.vault_install_dir["bundle"]
+ vault_root_token = step.create_vault_cluster.root_token
+ }
+ }
+
+ step "get_vault_cluster_ips" {
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
+ variables {
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ // Use the install dir for our initial version, which always comes from a zip bundle
+ vault_install_dir = global.vault_install_dir["bundle"]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_write_test_data" {
- module = module.vault_verify_write_data
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_write_data
depends_on = [
step.create_vault_cluster,
step.get_vault_cluster_ips,
@@ -255,19 +391,31 @@ scenario "upgrade" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
+ ]
+
variables {
- leader_public_ip = step.get_vault_cluster_ips.leader_public_ip
- leader_private_ip = step.get_vault_cluster_ips.leader_private_ip
- vault_instances = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ leader_host = step.get_vault_cluster_ips.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ // Use the install dir for our initial version, which always comes from a zip bundle
+ vault_install_dir = global.vault_install_dir["bundle"]
vault_root_token = step.create_vault_cluster.root_token
}
}
- # This step upgrades the Vault cluster to the var.vault_product_version
- # by getting a bundle or package of that version from the matrix.artifact_source
+ // This step upgrades the Vault cluster to the var.vault_product_version
+ // by getting a bundle or package of that version from the matrix.artifact_source
step "upgrade_vault" {
- module = module.vault_upgrade
+ description = <<-EOF
+ Perform an in-place upgrade of the Vault Cluster nodes by first installing a new version
+ of Vault on the cluster node machines and restarting the service.
+ EOF
+ module = module.vault_upgrade
depends_on = [
step.create_vault_cluster,
step.verify_write_test_data,
@@ -277,20 +425,28 @@ scenario "upgrade" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_cluster_upgrade_in_place,
+ quality.vault_service_restart,
+ ]
+
variables {
- vault_api_addr = "http://localhost:8200"
- vault_instances = step.create_vault_cluster_targets.hosts
- vault_local_artifact_path = local.artifact_path
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_artifactory_release = matrix.artifact_source == "artifactory" ? step.build_vault.vault_artifactory_release : null
- vault_install_dir = local.vault_install_dir
- vault_unseal_keys = matrix.seal == "shamir" ? step.create_vault_cluster.unseal_keys_hex : null
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ vault_local_artifact_path = local.artifact_path
+ vault_root_token = step.create_vault_cluster.root_token
vault_seal_type = matrix.seal
+ vault_unseal_keys = matrix.seal == "shamir" ? step.create_vault_cluster.unseal_keys_hex : null
}
}
// Wait for our upgraded cluster to elect a leader
step "wait_for_leader_after_upgrade" {
- module = module.vault_wait_for_leader
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
depends_on = [
step.create_vault_cluster,
step.upgrade_vault,
@@ -300,64 +456,96 @@ scenario "upgrade" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_leader_ip_for_step_down" {
- module = module.vault_get_cluster_ips
- depends_on = [step.wait_for_leader_after_upgrade]
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
+ depends_on = [step.wait_for_leader_after_upgrade]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Force a step down to trigger a new leader election
step "vault_leader_step_down" {
- module = module.vault_step_down
- depends_on = [step.get_leader_ip_for_step_down]
+ description = global.description.vault_leader_step_down
+ module = module.vault_step_down
+ depends_on = [step.get_leader_ip_for_step_down]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_step_down_steps_down,
+ quality.vault_cli_operator_step_down,
+ ]
+
variables {
- vault_install_dir = local.vault_install_dir
leader_host = step.get_leader_ip_for_step_down.leader_host
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
// Wait for our cluster to elect a leader
step "wait_for_leader_after_stepdown" {
- module = module.vault_wait_for_leader
- depends_on = [step.vault_leader_step_down]
+ description = global.description.wait_for_cluster_to_have_leader
+ module = module.vault_wait_for_leader
+ depends_on = [step.vault_leader_step_down]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_leader_read,
+ quality.vault_unseal_ha_leader_election,
+ ]
+
variables {
- timeout = 120 # seconds
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ timeout = 120 // seconds
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "get_updated_vault_cluster_ips" {
- module = module.vault_get_cluster_ips
+ description = global.description.get_vault_cluster_ip_addresses
+ module = module.vault_get_cluster_ips
depends_on = [
step.wait_for_leader_after_stepdown,
]
@@ -366,15 +554,24 @@ scenario "upgrade" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_api_sys_ha_status_read,
+ quality.vault_api_sys_leader_read,
+ quality.vault_cli_operator_members,
+ ]
+
variables {
- vault_hosts = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
- step "verify_vault_version" {
- module = module.vault_verify_version
+ step "verify_vault_unsealed" {
+ description = global.description.verify_vault_unsealed
+ module = module.vault_verify_unsealed
depends_on = [
step.get_updated_vault_cluster_ips,
]
@@ -383,10 +580,41 @@ scenario "upgrade" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_seal_awskms,
+ quality.vault_seal_pkcs11,
+ quality.vault_seal_shamir,
+ ]
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
+ }
+ }
+
+ step "verify_vault_version" {
+ description = global.description.verify_vault_version
+ module = module.vault_verify_version
+ depends_on = [step.verify_vault_unsealed]
+
+ providers = {
+ enos = local.enos_provider[matrix.distro]
+ }
+
+ verifies = [
+ quality.vault_api_sys_version_history_keys,
+ quality.vault_api_sys_version_history_key_info,
+ quality.vault_version_build_date,
+ quality.vault_version_edition,
+ quality.vault_version_release,
+ ]
+
+ variables {
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_product_version = matrix.artifact_source == "local" ? step.get_local_metadata.version : var.vault_product_version
vault_revision = matrix.artifact_source == "local" ? step.get_local_metadata.revision : var.vault_revision
vault_build_date = matrix.artifact_source == "local" ? step.get_local_metadata.build_date : var.vault_build_date
@@ -394,26 +622,10 @@ scenario "upgrade" {
}
}
- step "verify_vault_unsealed" {
- module = module.vault_verify_unsealed
- depends_on = [
- step.get_updated_vault_cluster_ips,
- ]
-
- providers = {
- enos = local.enos_provider[matrix.distro]
- }
-
- variables {
- vault_instances = step.create_vault_cluster_targets.hosts
- vault_install_dir = local.vault_install_dir
- }
- }
-
step "verify_read_test_data" {
- module = module.vault_verify_read_data
+ description = global.description.verify_write_test_data
+ module = module.vault_verify_read_data
depends_on = [
- step.get_updated_vault_cluster_ips,
step.verify_write_test_data,
step.verify_vault_unsealed
]
@@ -422,59 +634,77 @@ scenario "upgrade" {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_mount_auth,
+ quality.vault_mount_kv,
+ quality.vault_secrets_auth_user_policy_write,
+ quality.vault_secrets_kv_write,
+ ]
+
variables {
- node_public_ips = step.get_updated_vault_cluster_ips.follower_public_ips
- vault_install_dir = local.vault_install_dir
+ hosts = step.get_updated_vault_cluster_ips.follower_hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
}
}
step "verify_raft_auto_join_voter" {
- skip_step = matrix.backend != "raft"
- module = module.vault_verify_raft_auto_join_voter
- depends_on = [
- step.get_updated_vault_cluster_ips,
- ]
+ description = global.description.verify_raft_cluster_all_nodes_are_voters
+ skip_step = matrix.backend != "raft"
+ module = module.vault_verify_raft_auto_join_voter
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_raft_voters
+
variables {
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ ip_version = matrix.ip_version
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
}
}
step "verify_replication" {
- module = module.vault_verify_replication
- depends_on = [
- step.get_updated_vault_cluster_ips,
- ]
+ description = global.description.verify_replication_status
+ module = module.vault_verify_replication
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = [
+ quality.vault_replication_ce_disabled,
+ quality.vault_replication_ent_dr_available,
+ quality.vault_replication_ent_pr_available,
+ ]
+
variables {
- vault_edition = matrix.edition
- vault_install_dir = local.vault_install_dir
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
+ vault_edition = matrix.edition
}
}
step "verify_ui" {
- module = module.vault_verify_ui
- depends_on = [
- step.get_updated_vault_cluster_ips,
- ]
+ description = global.description.verify_ui
+ module = module.vault_verify_ui
+ depends_on = [step.verify_vault_unsealed]
providers = {
enos = local.enos_provider[matrix.distro]
}
+ verifies = quality.vault_ui_assets
+
variables {
- vault_instances = step.create_vault_cluster_targets.hosts
+ hosts = step.create_vault_cluster_targets.hosts
+ vault_addr = step.create_vault_cluster.api_addr_localhost
}
}
@@ -490,7 +720,7 @@ scenario "upgrade" {
output "hosts" {
description = "The Vault cluster target hosts"
- value = step.create_vault_cluster.target_hosts
+ value = step.create_vault_cluster.hosts
}
output "private_ips" {
diff --git a/enos/enos-terraform.hcl b/enos/enos-terraform.hcl
index 9320f54a57..a8f82f96ac 100644
--- a/enos/enos-terraform.hcl
+++ b/enos/enos-terraform.hcl
@@ -1,17 +1,19 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
terraform_cli "default" {
plugin_cache_dir = var.terraform_plugin_cache_dir != null ? abspath(var.terraform_plugin_cache_dir) : null
+}
+
+terraform_cli "dev" {
+ plugin_cache_dir = var.terraform_plugin_cache_dir != null ? abspath(var.terraform_plugin_cache_dir) : null
- /*
provider_installation {
dev_overrides = {
- "registry.terraform.io/hashicorp-forge/enos" = abspath("../../enos-provider/dist")
+ "registry.terraform.io/hashicorp-forge/enos" = try(abspath("../../terraform-provider-enos/dist"), null)
}
direct {}
}
- */
}
terraform "default" {
diff --git a/enos/enos-variables.hcl b/enos/enos-variables.hcl
index ff5aeec7cb..08909e844d 100644
--- a/enos/enos-variables.hcl
+++ b/enos/enos-variables.hcl
@@ -1,5 +1,5 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
variable "artifactory_username" {
type = string
@@ -75,10 +75,34 @@ variable "project_name" {
default = "vault-enos-integration"
}
-variable "rhel_distro_version" {
+variable "distro_version_amzn" {
+ description = "The version of Amazon Linux 2 to use"
+ type = string
+ default = "2023" // or "2", though pkcs11 has not been tested with 2
+}
+
+variable "distro_version_leap" {
+ description = "The version of openSUSE leap to use"
+ type = string
+ default = "15.6"
+}
+
+variable "distro_version_rhel" {
description = "The version of RHEL to use"
type = string
- default = "9.1" // or "8.8"
+ default = "9.4" // or "8.10"
+}
+
+variable "distro_version_sles" {
+ description = "The version of SUSE SLES to use"
+ type = string
+ default = "15.6"
+}
+
+variable "distro_version_ubuntu" {
+ description = "The version of ubuntu to use"
+ type = string
+ default = "24.04" // or "20.04", "22.04"
}
variable "tags" {
@@ -93,12 +117,6 @@ variable "terraform_plugin_cache_dir" {
default = null
}
-variable "ubuntu_distro_version" {
- description = "The version of ubuntu to use"
- type = string
- default = "22.04" // or "20.04", "18.04"
-}
-
variable "ui_test_filter" {
type = string
description = "A test filter to limit the ui tests to execute. Will be appended to the ember test command as '-f=\"\"'"
@@ -112,7 +130,7 @@ variable "ui_run_tests" {
}
variable "vault_artifact_type" {
- description = "The type of Vault artifact to use when installing Vault from artifactory. It should be 'package' for .deb or # .rpm package and 'bundle' for .zip bundles"
+ description = "The type of Vault artifact to use when installing Vault from artifactory. It should be 'package' for .deb or .rpm package and 'bundle' for .zip bundles"
default = "bundle"
}
diff --git a/enos/enos.vars.hcl b/enos/enos.vars.hcl
index 8397eda372..1d60711806 100644
--- a/enos/enos.vars.hcl
+++ b/enos/enos.vars.hcl
@@ -1,115 +1,121 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
-# artifactory_username is the username to use when testing an artifact stored in artfactory.
-# artifactory_username = "yourname@hashicorp.com"
+// artifactory_username is the username to use when testing an artifact stored in artfactory.
+// artifactory_username = "yourname@hashicorp.com"
-# artifactory_token is the token to use when authenticating to artifactory.
-# artifactory_token = "yourtoken"
+// artifactory_token is the token to use when authenticating to artifactory.
+// artifactory_token = "yourtoken"
-# artifactory_host is the artifactory host to search for vault artifacts.
-# artifactory_host = "https://artifactory.hashicorp.engineering/artifactory"
+// artifactory_host is the artifactory host to search for vault artifacts.
+// artifactory_host = "https://artifactory.hashicorp.engineering/artifactory"
-# artifactory_repo is the artifactory repo to search for vault artifacts.
-# artifactory_repo = "hashicorp-crt-stable-local*"
+// artifactory_repo is the artifactory repo to search for vault artifacts.
+// artifactory_repo = "hashicorp-crt-stable-local*"
-# aws_region is the AWS region where we'll create infrastructure
-# for the smoke scenario
-# aws_region = "us-east-1"
+// aws_region is the AWS region where we'll create infrastructure
+// for the smoke scenario
+// aws_region = "us-east-1"
-# aws_ssh_keypair_name is the AWS keypair to use for SSH
-# aws_ssh_keypair_name = "enos-ci-ssh-key"
+// aws_ssh_keypair_name is the AWS keypair to use for SSH
+// aws_ssh_keypair_name = "enos-ci-ssh-key"
-# aws_ssh_private_key_path is the path to the AWS keypair private key
-# aws_ssh_private_key_path = "./support/private_key.pem"
+// aws_ssh_private_key_path is the path to the AWS keypair private key
+// aws_ssh_private_key_path = "./support/private_key.pem"
-# backend_edition is the backend (consul) release edition if applicable to the scenario.
-# backend_edition = "ce"
+// backend_license_path is the license for the backend if applicable (Consul Enterprise)".
+// backend_license_path = "./support/consul.hclic"
-# backend_license_path is the license for the backend if applicable (Consul Enterprise)".
-# backend_license_path = "./support/consul.hclic"
+// backend_log_level is the server log level for the backend. Supported values include 'trace',
+// 'debug', 'info', 'warn', 'error'"
+// backend_log_level = "trace"
-# backend_log_level is the server log level for the backend. Supported values include 'trace',
-# 'debug', 'info', 'warn', 'error'"
-# backend_log_level = "trace"
+// backend_instance_type is the instance type to use for the Vault backend. Must support arm64
+// backend_instance_type = "t4g.small"
-# backend_instance_type is the instance type to use for the Vault backend. Must support arm64
-# backend_instance_type = "t4g.small"
+// project_name is the description of the project. It will often be used to tag infrastructure
+// resources.
+// project_name = "vault-enos-integration"
-# project_name is the description of the project. It will often be used to tag infrastructure
-# resources.
-# project_name = "vault-enos-integration"
+// distro_version_amzn is the version of Amazon Linux 2 to use for "distro:amzn" variants
+// distro_version_amzn = "2"
-# rhel_distro_version is the version of RHEL to use for "distro:rhel" variants.
-# rhel_distro_version = "9.1" // or "8.8"
+// distro_version_leap is the version of openSUSE Leap to use for "distro:leap" variants
+// distro_version_leap = "15.5"
-# tags are a map of tags that will be applied to infrastructure resources that
-# support tagging.
-# tags = { "Project Name" : "Vault", "Something Cool" : "Value" }
+// distro_version_rhel is the version of RHEL to use for "distro:rhel" variants.
+// distro_version_rhel = "9.3" // or "8.9"
-# terraform_plugin_cache_dir is the directory to cache Terraform modules and providers.
-# It must exist.
-# terraform_plugin_cache_dir = "/Users//.terraform/plugin-cache-dir
+// distro_version_sles is the version of SUSE SLES to use for "distro:sles" variants.
+// distro_version_sles = "v15_sp5_standard"
-# ui_test_filter is the test filter to limit the ui tests to execute for the ui scenario. It will
-# be appended to the ember test command as '-f=\"\"'.
-# ui_test_filter = "sometest"
+// distro_version_ubuntu is the version of ubuntu to use for "distro:ubuntu" variants
+// distro_version_ubuntu = "22.04" // or "20.04"
-# ui_run_tests sets whether to run the UI tests or not for the ui scenario. If set to false a
-# cluster will be created but no tests will be run.
-# ui_run_tests = true
+// tags are a map of tags that will be applied to infrastructure resources that
+// support tagging.
+// tags = { "Project Name" : "Vault", "Something Cool" : "Value" }
-# ubuntu_distro_version is the version of ubuntu to use for "distro:ubuntu" variants
-# ubuntu_distro_version = "22.04" // or "20.04", "18.04"
+// terraform_plugin_cache_dir is the directory to cache Terraform modules and providers.
+// It must exist.
+// terraform_plugin_cache_dir = "/Users//.terraform/plugin-cache-dir
-# vault_artifact_path is the path to CRT generated or local vault.zip bundle. When
-# using the "builder:local" variant a bundle will be built from the current branch.
-# In CI it will use the output of the build workflow.
-# vault_artifact_path = "./dist/vault.zip"
+// ui_test_filter is the test filter to limit the ui tests to execute for the ui scenario. It will
+// be appended to the ember test command as '-f=\"\"'.
+// ui_test_filter = "sometest"
-# vault_artifact_type is the type of Vault artifact to use when installing Vault from artifactory.
-# It should be 'package' for .deb or # .rpm package and 'bundle' for .zip bundles"
-# vault_artifact_type = "bundle"
+// ui_run_tests sets whether to run the UI tests or not for the ui scenario. If set to false a
+// cluster will be created but no tests will be run.
+// ui_run_tests = true
-# vault_build_date is the build date for Vault artifact. Some validations will require the binary build
-# date to match"
-# vault_build_date = "2023-07-07T14:06:37Z" // make ci-get-date for example
+// vault_artifact_path is the path to CRT generated or local vault.zip bundle. When
+// using the "builder:local" variant a bundle will be built from the current branch.
+// In CI it will use the output of the build workflow.
+// vault_artifact_path = "./dist/vault.zip"
-# vault_enable_audit_devices sets whether or not to enable every audit device. It true
-# a file audit device will be enabled at the path /var/log/vault_audit.log, the syslog
-# audit device will be enabled, and a socket audit device connecting to 127.0.0.1:9090
-# will be enabled. The netcat program is run in listening mode to provide an endpoint
-# that the socket audit device can connect to.
-# vault_enable_audit_devices = true
+// vault_artifact_type is the type of Vault artifact to use when installing Vault from artifactory.
+// It should be 'package' for .deb or # .rpm package and 'bundle' for .zip bundles"
+// vault_artifact_type = "bundle"
-# vault_install_dir is the directory where the vault binary will be installed on
-# the remote machines.
-# vault_install_dir = "/opt/vault/bin"
+// vault_build_date is the build date for Vault artifact. Some validations will require the binary build
+// date to match"
+// vault_build_date = "2023-07-07T14:06:37Z" // make ci-get-date for example
-# vault_local_binary_path is the path of the local binary that we're upgrading to.
-# vault_local_binary_path = "./support/vault"
+// vault_enable_audit_devices sets whether or not to enable every audit device. It true
+// a file audit device will be enabled at the path /var/log/vault_audit.log, the syslog
+// audit device will be enabled, and a socket audit device connecting to 127.0.0.1:9090
+// will be enabled. The netcat program is run in listening mode to provide an endpoint
+// that the socket audit device can connect to.
+// vault_enable_audit_devices = true
-# vault_instance_type is the instance type to use for the Vault backend
-# vault_instance_type = "t3.small"
+// vault_install_dir is the directory where the vault binary will be installed on
+// the remote machines.
+// vault_install_dir = "/opt/vault/bin"
-# vault_instance_count is how many instances to create for the Vault cluster.
-# vault_instance_count = 3
+// vault_local_binary_path is the path of the local binary that we're upgrading to.
+// vault_local_binary_path = "./support/vault"
-# vault_license_path is the path to a valid Vault enterprise edition license.
-# This is only required for non-ce editions"
-# vault_license_path = "./support/vault.hclic"
+// vault_instance_type is the instance type to use for the Vault backend
+// vault_instance_type = "t3.small"
-# vault_local_build_tags override the build tags we pass to the Go compiler for builder:local variants.
-# vault_local_build_tags = ["ui", "ent"]
+// vault_instance_count is how many instances to create for the Vault cluster.
+// vault_instance_count = 3
-# vault_log_level is the server log level for Vault logs. Supported values (in order of detail) are
-# trace, debug, info, warn, and err."
-# vault_log_level = "trace"
+// vault_license_path is the path to a valid Vault enterprise edition license.
+// This is only required for non-ce editions"
+// vault_license_path = "./support/vault.hclic"
-# vault_product_version is the version of Vault we are testing. Some validations will expect the vault
-# binary and cluster to report this version.
-# vault_product_version = "1.15.0"
+// vault_local_build_tags override the build tags we pass to the Go compiler for builder:local variants.
+// vault_local_build_tags = ["ui", "ent"]
-# vault_revision is the git sha of Vault artifact we are testing. Some validations will expect the vault
-# binary and cluster to report this revision.
-# vault_revision = "df733361af26f8bb29b63704168bbc5ab8d083de"
+// vault_log_level is the server log level for Vault logs. Supported values (in order of detail) are
+// trace, debug, info, warn, and err."
+// vault_log_level = "trace"
+
+// vault_product_version is the version of Vault we are testing. Some validations will expect the vault
+// binary and cluster to report this version.
+// vault_product_version = "1.15.0"
+
+// vault_revision is the git sha of Vault artifact we are testing. Some validations will expect the vault
+// binary and cluster to report this revision.
+// vault_revision = "df733361af26f8bb29b63704168bbc5ab8d083de"
diff --git a/enos/k8s/enos-scenario-k8s.hcl b/enos/k8s/enos-scenario-k8s.hcl
index e40c187059..33508249c6 100644
--- a/enos/k8s/enos-scenario-k8s.hcl
+++ b/enos/k8s/enos-scenario-k8s.hcl
@@ -99,19 +99,6 @@ scenario "k8s" {
depends_on = [step.deploy_vault]
}
- step "verify_ui" {
- module = module.k8s_verify_ui
- skip_step = matrix.edition == "ce"
-
- variables {
- vault_pods = step.deploy_vault.vault_pods
- kubeconfig_base64 = step.create_kind_cluster.kubeconfig_base64
- context_name = step.create_kind_cluster.context_name
- }
-
- depends_on = [step.deploy_vault]
- }
-
step "verify_version" {
module = module.k8s_verify_version
diff --git a/enos/modules/backend_consul/main.tf b/enos/modules/backend_consul/main.tf
index 2af4632bbd..1d0a514e0e 100644
--- a/enos/modules/backend_consul/main.tf
+++ b/enos/modules/backend_consul/main.tf
@@ -17,7 +17,7 @@ locals {
}
resource "enos_bundle_install" "consul" {
- for_each = var.target_hosts
+ for_each = var.hosts
destination = var.install_dir
release = merge(var.release, { product = "consul" })
@@ -40,7 +40,7 @@ resource "enos_consul_start" "consul" {
datacenter = "dc1"
retry_join = ["provider=aws tag_key=${var.cluster_tag_key} tag_value=${var.cluster_name}"]
server = true
- bootstrap_expect = length(var.target_hosts)
+ bootstrap_expect = length(var.hosts)
log_level = var.log_level
log_file = var.log_dir
}
@@ -50,7 +50,7 @@ resource "enos_consul_start" "consul" {
transport = {
ssh = {
- host = var.target_hosts[each.key].public_ip
+ host = var.hosts[each.key].public_ip
}
}
}
diff --git a/enos/modules/backend_consul/outputs.tf b/enos/modules/backend_consul/outputs.tf
index 8f32783e8d..5f78e3f850 100644
--- a/enos/modules/backend_consul/outputs.tf
+++ b/enos/modules/backend_consul/outputs.tf
@@ -3,16 +3,16 @@
output "private_ips" {
description = "Consul cluster target host private_ips"
- value = [for host in var.target_hosts : host.private_ip]
+ value = [for host in var.hosts : host.private_ip]
}
output "public_ips" {
description = "Consul cluster target host public_ips"
- value = [for host in var.target_hosts : host.public_ip]
+ value = [for host in var.hosts : host.public_ip]
}
-output "target_hosts" {
+output "hosts" {
description = "The Consul cluster instances that were created"
- value = var.target_hosts
+ value = var.hosts
}
diff --git a/enos/modules/backend_consul/variables.tf b/enos/modules/backend_consul/variables.tf
index 34a96d8535..c404c0ff5e 100644
--- a/enos/modules/backend_consul/variables.tf
+++ b/enos/modules/backend_consul/variables.tf
@@ -25,6 +25,15 @@ variable "data_dir" {
default = "/opt/consul/data"
}
+variable "hosts" {
+ description = "The target machines host addresses to use for the consul cluster"
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+}
+
variable "install_dir" {
type = string
description = "The directory where the consul binary will be installed"
@@ -66,11 +75,3 @@ variable "release" {
edition = "ce"
}
}
-
-variable "target_hosts" {
- description = "The target machines host addresses to use for the consul cluster"
- type = map(object({
- private_ip = string
- public_ip = string
- }))
-}
diff --git a/enos/modules/backend_raft/main.tf b/enos/modules/backend_raft/main.tf
index bc070235eb..415b058a3b 100644
--- a/enos/modules/backend_raft/main.tf
+++ b/enos/modules/backend_raft/main.tf
@@ -53,18 +53,18 @@ variable "release" {
default = null
}
-variable "target_hosts" {
+variable "hosts" {
default = null
}
output "private_ips" {
- value = [for host in var.target_hosts : host.private_ip]
+ value = [for host in var.hosts : host.private_ip]
}
output "public_ips" {
- value = [for host in var.target_hosts : host.public_ip]
+ value = [for host in var.hosts : host.public_ip]
}
-output "target_hosts" {
- value = var.target_hosts
+output "hosts" {
+ value = var.hosts
}
diff --git a/enos/modules/build_artifactory_artifact/locals.tf b/enos/modules/build_artifactory_artifact/locals.tf
index 77b4532279..97a3ab689c 100644
--- a/enos/modules/build_artifactory_artifact/locals.tf
+++ b/enos/modules/build_artifactory_artifact/locals.tf
@@ -6,12 +6,18 @@ locals {
// file name extensions for the install packages of vault for the various architectures, distributions and editions
package_extensions = {
amd64 = {
- ubuntu = "-1_amd64.deb"
+ amzn = "-1.x86_64.rpm"
+ leap = "-1.x86_64.rpm"
rhel = "-1.x86_64.rpm"
+ sles = "-1.x86_64.rpm"
+ ubuntu = "-1_amd64.deb"
}
arm64 = {
- ubuntu = "-1_arm64.deb"
+ amzn = "-1.aarch64.rpm"
+ leap = "-1.aarch64.rpm"
rhel = "-1.aarch64.rpm"
+ sles = "-1.aarch64.rpm"
+ ubuntu = "-1_arm64.deb"
}
}
@@ -20,12 +26,19 @@ locals {
// file name prefixes for the install packages of vault for the various distributions and artifact types (package or bundle)
artifact_package_release_names = {
- ubuntu = {
- "ce" = "vault_"
- "ent" = "vault-enterprise_",
- "ent.fips1402" = "vault-enterprise-fips1402_",
- "ent.hsm" = "vault-enterprise-hsm_",
- "ent.hsm.fips1402" = "vault-enterprise-hsm-fips1402_",
+ amzn = {
+ "ce" = "vault-"
+ "ent" = "vault-enterprise-",
+ "ent.fips1402" = "vault-enterprise-fips1402-",
+ "ent.hsm" = "vault-enterprise-hsm-",
+ "ent.hsm.fips1402" = "vault-enterprise-hsm-fips1402-",
+ },
+ leap = {
+ "ce" = "vault-"
+ "ent" = "vault-enterprise-",
+ "ent.fips1402" = "vault-enterprise-fips1402-",
+ "ent.hsm" = "vault-enterprise-hsm-",
+ "ent.hsm.fips1402" = "vault-enterprise-hsm-fips1402-",
},
rhel = {
"ce" = "vault-"
@@ -33,19 +46,27 @@ locals {
"ent.fips1402" = "vault-enterprise-fips1402-",
"ent.hsm" = "vault-enterprise-hsm-",
"ent.hsm.fips1402" = "vault-enterprise-hsm-fips1402-",
+ },
+ sles = {
+ "ce" = "vault-"
+ "ent" = "vault-enterprise-",
+ "ent.fips1402" = "vault-enterprise-fips1402-",
+ "ent.hsm" = "vault-enterprise-hsm-",
+ "ent.hsm.fips1402" = "vault-enterprise-hsm-fips1402-",
+ }
+ ubuntu = {
+ "ce" = "vault_"
+ "ent" = "vault-enterprise_",
+ "ent.fips1402" = "vault-enterprise-fips1402_",
+ "ent.hsm" = "vault-enterprise-hsm_",
+ "ent.hsm.fips1402" = "vault-enterprise-hsm-fips1402_",
}
}
- // edition --> artifact name edition
- artifact_name_edition = {
- "ce" = ""
- "ent" = ""
- "ent.hsm" = ".hsm"
- "ent.fips1402" = ".fips1402"
- "ent.hsm.fips1402" = ".hsm.fips1402"
- }
-
- artifact_name_prefix = var.artifact_type == "package" ? local.artifact_package_release_names[var.distro][var.edition] : "vault_"
+ # Prefix for the artifact name. Ex: vault_, vault-, vault-enterprise_, vault-enterprise-hsm-fips1402-, etc
+ artifact_name_prefix = var.artifact_type == "package" ? local.artifact_package_release_names[var.distro][var.edition] : "vault_"
+ # Suffix and extension for the artifact name. Ex: _linux_.zip,
artifact_name_extension = var.artifact_type == "package" ? local.package_extensions[var.arch][var.distro] : "_linux_${var.arch}.zip"
- artifact_name = var.artifact_type == "package" ? "${local.artifact_name_prefix}${replace(local.artifact_version, "-", "~")}${local.artifact_name_extension}" : "${local.artifact_name_prefix}${var.product_version}${local.artifact_name_extension}"
+ # Combine prefix/suffix/extension together to form the artifact name
+ artifact_name = var.artifact_type == "package" ? "${local.artifact_name_prefix}${replace(local.artifact_version, "-", "~")}${local.artifact_name_extension}" : "${local.artifact_name_prefix}${var.product_version}${local.artifact_name_extension}"
}
diff --git a/enos/modules/create_vpc/main.tf b/enos/modules/create_vpc/main.tf
index 2e7c3ebfcf..55cbf0165b 100644
--- a/enos/modules/create_vpc/main.tf
+++ b/enos/modules/create_vpc/main.tf
@@ -19,9 +19,11 @@ resource "random_string" "cluster_id" {
}
resource "aws_vpc" "vpc" {
- cidr_block = var.cidr
- enable_dns_hostnames = true
- enable_dns_support = true
+ // Always set the ipv4 cidr block as it's required in "dual-stack" VPCs which we create.
+ cidr_block = var.ipv4_cidr
+ enable_dns_hostnames = true
+ enable_dns_support = true
+ assign_generated_ipv6_cidr_block = var.ip_version == 6
tags = merge(
var.common_tags,
@@ -32,11 +34,18 @@ resource "aws_vpc" "vpc" {
}
resource "aws_subnet" "subnet" {
- count = length(data.aws_availability_zones.available.names)
- vpc_id = aws_vpc.vpc.id
- cidr_block = cidrsubnet(var.cidr, 8, count.index)
- availability_zone = data.aws_availability_zones.available.names[count.index]
+ count = length(data.aws_availability_zones.available.names)
+ vpc_id = aws_vpc.vpc.id
+ availability_zone = data.aws_availability_zones.available.names[count.index]
+
+ // IPV4, but since we need to support ipv4 connections from the machine running enos, we're
+ // always going to need ipv4 available.
map_public_ip_on_launch = true
+ cidr_block = cidrsubnet(var.ipv4_cidr, 8, count.index)
+
+ // IPV6, only set these when we want to run in ipv6 mode.
+ assign_ipv6_address_on_creation = var.ip_version == 6
+ ipv6_cidr_block = var.ip_version == 6 ? cidrsubnet(aws_vpc.vpc.ipv6_cidr_block, 4, count.index) : null
tags = merge(
var.common_tags,
@@ -46,7 +55,7 @@ resource "aws_subnet" "subnet" {
)
}
-resource "aws_internet_gateway" "igw" {
+resource "aws_internet_gateway" "ipv4" {
vpc_id = aws_vpc.vpc.id
tags = merge(
@@ -57,29 +66,43 @@ resource "aws_internet_gateway" "igw" {
)
}
-resource "aws_route" "igw" {
+resource "aws_egress_only_internet_gateway" "ipv6" {
+ count = var.ip_version == 6 ? 1 : 0
+ vpc_id = aws_vpc.vpc.id
+}
+
+resource "aws_route" "igw_ipv4" {
route_table_id = aws_vpc.vpc.default_route_table_id
destination_cidr_block = "0.0.0.0/0"
- gateway_id = aws_internet_gateway.igw.id
+ gateway_id = aws_internet_gateway.ipv4.id
+}
+
+resource "aws_route" "igw_ipv6" {
+ count = var.ip_version == 6 ? 1 : 0
+ route_table_id = aws_vpc.vpc.default_route_table_id
+ destination_ipv6_cidr_block = "::/0"
+ egress_only_gateway_id = aws_egress_only_internet_gateway.ipv6[0].id
}
resource "aws_security_group" "default" {
vpc_id = aws_vpc.vpc.id
ingress {
- description = "allow_ingress_from_all"
- from_port = 0
- to_port = 0
- protocol = "tcp"
- cidr_blocks = ["0.0.0.0/0"]
+ description = "allow_ingress_from_all"
+ from_port = 0
+ to_port = 0
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ ipv6_cidr_blocks = var.ip_version == 6 ? ["::/0"] : null
}
egress {
- description = "allow_egress_from_all"
- from_port = 0
- to_port = 0
- protocol = "-1"
- cidr_blocks = ["0.0.0.0/0"]
+ description = "allow_egress_from_all"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ ipv6_cidr_blocks = var.ip_version == 6 ? ["::/0"] : null
}
tags = merge(
diff --git a/enos/modules/create_vpc/outputs.tf b/enos/modules/create_vpc/outputs.tf
index a064644d31..d54fbd8131 100644
--- a/enos/modules/create_vpc/outputs.tf
+++ b/enos/modules/create_vpc/outputs.tf
@@ -6,9 +6,14 @@ output "id" {
value = aws_vpc.vpc.id
}
-output "cidr" {
- description = "CIDR for whole VPC"
- value = var.cidr
+output "ipv4_cidr" {
+ description = "The VPC subnet CIDR for ipv4 mode"
+ value = var.ipv4_cidr
+}
+
+output "ipv6_cidr" {
+ description = "The VPC subnet CIDR for ipv6 mode"
+ value = aws_vpc.vpc.ipv6_cidr_block
}
output "cluster_id" {
diff --git a/enos/modules/create_vpc/variables.tf b/enos/modules/create_vpc/variables.tf
index 1986136229..80c64ea3c1 100644
--- a/enos/modules/create_vpc/variables.tf
+++ b/enos/modules/create_vpc/variables.tf
@@ -7,10 +7,21 @@ variable "name" {
description = "The name of the VPC"
}
-variable "cidr" {
+variable "ip_version" {
+ type = number
+ default = 4
+ description = "The IP version to use for the default subnet"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "ipv4_cidr" {
type = string
default = "10.13.0.0/16"
- description = "CIDR block for the VPC"
+ description = "The CIDR block for the VPC when using IPV4 mode"
}
variable "environment" {
diff --git a/enos/modules/disable_selinux/main.tf b/enos/modules/disable_selinux/main.tf
new file mode 100644
index 0000000000..7ed2f52637
--- /dev/null
+++ b/enos/modules/disable_selinux/main.tf
@@ -0,0 +1,31 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+terraform {
+ required_providers {
+ enos = {
+ source = "registry.terraform.io/hashicorp-forge/enos"
+ }
+ }
+}
+
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The hosts to install packages on"
+}
+
+resource "enos_remote_exec" "make_selinux_permissive" {
+ for_each = var.hosts
+
+ scripts = [abspath("${path.module}/scripts/make-selinux-permissive.sh")]
+
+ transport = {
+ ssh = {
+ host = each.value.public_ip
+ }
+ }
+}
diff --git a/enos/modules/disable_selinux/scripts/make-selinux-permissive.sh b/enos/modules/disable_selinux/scripts/make-selinux-permissive.sh
new file mode 100644
index 0000000000..cedc23d46d
--- /dev/null
+++ b/enos/modules/disable_selinux/scripts/make-selinux-permissive.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+set -e
+
+fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+if ! type getenforce &> /dev/null; then
+ exit 0
+fi
+
+if sudo getenforce | grep Enforcing; then
+ sudo setenforce 0
+fi
diff --git a/enos/modules/ec2_info/main.tf b/enos/modules/ec2_info/main.tf
index 0b78e2b370..1ca8d575f6 100644
--- a/enos/modules/ec2_info/main.tf
+++ b/enos/modules/ec2_info/main.tf
@@ -1,44 +1,126 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
+# Note: in order to use the openSUSE Leap AMIs, the AWS account in use must "subscribe"
+# and accept SUSE's terms of use. You can do this at the links below. If the AWS account
+# you are using is already subscribed, this confirmation will be displayed on each page.
+# openSUSE Leap arm64 subscription: https://aws.amazon.com/marketplace/server/procurement?productId=a516e959-df54-4035-bb1a-63599b7a6df9
+# openSUSE Leap amd64 subscription: https://aws.amazon.com/marketplace/server/procurement?productId=5535c495-72d4-4355-b169-54ffa874f849
+
locals {
architectures = toset(["arm64", "x86_64"])
+ amazon_owner_id = "591542846629"
canonical_owner_id = "099720109477"
- rhel_owner_id = "309956199498"
+ suse_owner_id = "013907871322"
+ opensuse_owner_id = "679593333241"
+ redhat_owner_id = "309956199498"
ids = {
+ // NOTE: If you modify these versions you'll probably also need to update the `softhsm_install`
+ // module to match.
"arm64" = {
+ "amzn" = {
+ "2" = data.aws_ami.amzn_2["arm64"].id
+ "2023" = data.aws_ami.amzn_2023["arm64"].id
+ }
+ "leap" = {
+ "15.6" = data.aws_ami.leap_15["arm64"].id
+ }
"rhel" = {
- "8.8" = data.aws_ami.rhel_88["arm64"].id
- "9.1" = data.aws_ami.rhel_91["arm64"].id
+ "8.10" = data.aws_ami.rhel_8["arm64"].id
+ "9.4" = data.aws_ami.rhel_9["arm64"].id
+ }
+ "sles" = {
+ "15.6" = data.aws_ami.sles_15["arm64"].id
}
"ubuntu" = {
- "18.04" = data.aws_ami.ubuntu_1804["arm64"].id
"20.04" = data.aws_ami.ubuntu_2004["arm64"].id
"22.04" = data.aws_ami.ubuntu_2204["arm64"].id
+ "24.04" = data.aws_ami.ubuntu_2404["arm64"].id
}
}
"amd64" = {
+ "amzn" = {
+ "2" = data.aws_ami.amzn_2["x86_64"].id
+ "2023" = data.aws_ami.amzn_2023["x86_64"].id
+ }
+ "leap" = {
+ "15.6" = data.aws_ami.leap_15["x86_64"].id
+ }
"rhel" = {
- "7.9" = data.aws_ami.rhel_79.id
- "8.8" = data.aws_ami.rhel_88["x86_64"].id
- "9.1" = data.aws_ami.rhel_91["x86_64"].id
+ "8.10" = data.aws_ami.rhel_8["x86_64"].id
+ "9.4" = data.aws_ami.rhel_9["x86_64"].id
+ }
+ "sles" = {
+ "15.6" = data.aws_ami.sles_15["x86_64"].id
}
"ubuntu" = {
- "18.04" = data.aws_ami.ubuntu_1804["x86_64"].id
"20.04" = data.aws_ami.ubuntu_2004["x86_64"].id
"22.04" = data.aws_ami.ubuntu_2204["x86_64"].id
+ "24.04" = data.aws_ami.ubuntu_2404["x86_64"].id
}
}
}
}
-data "aws_ami" "ubuntu_1804" {
+data "aws_ami" "amzn_2" {
most_recent = true
for_each = local.architectures
filter {
name = "name"
- values = ["ubuntu/images/hvm-ssd/ubuntu-*-18.04-*-server-*"]
+ values = ["amzn2-ami-ecs-hvm-2.0*"]
+ }
+
+ filter {
+ name = "architecture"
+ values = [each.value]
+ }
+
+ owners = [local.amazon_owner_id]
+}
+
+data "aws_ami" "amzn_2023" {
+ most_recent = true
+ for_each = local.architectures
+
+ filter {
+ name = "name"
+ values = ["al2023-ami-ecs-hvm*"]
+ }
+
+ filter {
+ name = "architecture"
+ values = [each.value]
+ }
+
+ owners = [local.amazon_owner_id]
+}
+
+data "aws_ami" "leap_15" {
+ most_recent = true
+ for_each = local.architectures
+
+ filter {
+ name = "name"
+ values = ["openSUSE-Leap-15-6*"]
+ }
+
+ filter {
+ name = "architecture"
+ values = [each.value]
+ }
+
+ owners = [local.opensuse_owner_id]
+}
+
+data "aws_ami" "rhel_8" {
+ most_recent = true
+ for_each = local.architectures
+
+ # Currently latest latest point release-1
+ filter {
+ name = "name"
+ values = ["RHEL-8.10*HVM-20*"]
}
filter {
@@ -51,7 +133,47 @@ data "aws_ami" "ubuntu_1804" {
values = [each.value]
}
- owners = [local.canonical_owner_id]
+ owners = [local.redhat_owner_id]
+}
+
+data "aws_ami" "rhel_9" {
+ most_recent = true
+ for_each = local.architectures
+
+ # Currently latest latest point release-1
+ filter {
+ name = "name"
+ values = ["RHEL-9.4*HVM-20*"]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+
+ filter {
+ name = "architecture"
+ values = [each.value]
+ }
+
+ owners = [local.redhat_owner_id]
+}
+
+data "aws_ami" "sles_15" {
+ most_recent = true
+ for_each = local.architectures
+
+ filter {
+ name = "name"
+ values = ["suse-sles-15-sp6-v*-hvm-*"]
+ }
+
+ filter {
+ name = "architecture"
+ values = [each.value]
+ }
+
+ owners = [local.suse_owner_id]
}
data "aws_ami" "ubuntu_2004" {
@@ -98,36 +220,13 @@ data "aws_ami" "ubuntu_2204" {
owners = [local.canonical_owner_id]
}
-data "aws_ami" "rhel_79" {
- most_recent = true
-
- # Currently latest latest point release-1
- filter {
- name = "name"
- values = ["RHEL-7.9*HVM-20*"]
- }
-
- filter {
- name = "virtualization-type"
- values = ["hvm"]
- }
-
- filter {
- name = "architecture"
- values = ["x86_64"]
- }
-
- owners = [local.rhel_owner_id]
-}
-
-data "aws_ami" "rhel_88" {
+data "aws_ami" "ubuntu_2404" {
most_recent = true
for_each = local.architectures
- # Currently latest latest point release-1
filter {
name = "name"
- values = ["RHEL-8.8*HVM-20*"]
+ values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-*-server-*"]
}
filter {
@@ -140,30 +239,7 @@ data "aws_ami" "rhel_88" {
values = [each.value]
}
- owners = [local.rhel_owner_id]
-}
-
-data "aws_ami" "rhel_91" {
- most_recent = true
- for_each = local.architectures
-
- # Currently latest latest point release-1
- filter {
- name = "name"
- values = ["RHEL-9.1*HVM-20*"]
- }
-
- filter {
- name = "virtualization-type"
- values = ["hvm"]
- }
-
- filter {
- name = "architecture"
- values = [each.value]
- }
-
- owners = [local.rhel_owner_id]
+ owners = [local.canonical_owner_id]
}
data "aws_region" "current" {}
diff --git a/enos/modules/generate_secondary_token/main.tf b/enos/modules/generate_secondary_token/main.tf
index 5bc63b2f3d..e7eb3f2123 100644
--- a/enos/modules/generate_secondary_token/main.tf
+++ b/enos/modules/generate_secondary_token/main.tf
@@ -13,6 +13,11 @@ terraform {
}
}
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
@@ -32,12 +37,13 @@ locals {
token_id = random_uuid.token_id.id
secondary_token = enos_remote_exec.fetch_secondary_token.stdout
}
+
resource "random_uuid" "token_id" {}
resource "enos_remote_exec" "fetch_secondary_token" {
depends_on = [random_uuid.token_id]
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
}
diff --git a/enos/modules/install_packages/main.tf b/enos/modules/install_packages/main.tf
index 96717edcab..78ef41c803 100644
--- a/enos/modules/install_packages/main.tf
+++ b/enos/modules/install_packages/main.tf
@@ -9,6 +9,29 @@ terraform {
}
}
+locals {
+ arch = {
+ "amd64" = "x86_64"
+ "arm64" = "aarch64"
+ }
+ package_manager = {
+ "amzn" = "yum"
+ "opensuse-leap" = "zypper"
+ "rhel" = "dnf"
+ "sles" = "zypper"
+ "ubuntu" = "apt"
+ }
+ distro_repos = {
+ "sles" = {
+ "15.6" = "https://download.opensuse.org/repositories/network:utilities/SLE_15_SP6/network:utilities.repo"
+ }
+ "rhel" = {
+ "8.10" = "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm"
+ "9.4" = "https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm"
+ }
+ }
+}
+
variable "packages" {
type = list(string)
default = []
@@ -16,6 +39,7 @@ variable "packages" {
variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
@@ -24,7 +48,7 @@ variable "hosts" {
variable "timeout" {
type = number
- description = "The max number of seconds to wait before timing out"
+ description = "The max number of seconds to wait before timing out. This is applied to each step so total timeout will be longer."
default = 120
}
@@ -34,10 +58,69 @@ variable "retry_interval" {
default = 2
}
-resource "enos_remote_exec" "install_packages" {
+resource "enos_host_info" "hosts" {
+ for_each = var.hosts
+
+ transport = {
+ ssh = {
+ host = each.value.public_ip
+ }
+ }
+}
+
+# Synchronize repositories on remote machines. This does not update packages but only ensures that
+# the remote hosts are configured with default upstream repositories that have been refreshed to
+# the latest metedata.
+resource "enos_remote_exec" "synchronize_repos" {
for_each = var.hosts
environment = {
+ DISTRO = enos_host_info.hosts[each.key].distro
+ PACKAGE_MANAGER = local.package_manager[enos_host_info.hosts[each.key].distro]
+ RETRY_INTERVAL = var.retry_interval
+ TIMEOUT_SECONDS = var.timeout
+ }
+
+ scripts = [abspath("${path.module}/scripts/synchronize-repos.sh")]
+
+ transport = {
+ ssh = {
+ host = each.value.public_ip
+ }
+ }
+}
+
+# Add any additional repositories.
+resource "enos_remote_exec" "add_repos" {
+ for_each = var.hosts
+ depends_on = [enos_remote_exec.synchronize_repos]
+
+ environment = {
+ DISTRO_REPOS = try(local.distro_repos[enos_host_info.hosts[each.key].distro][enos_host_info.hosts[each.key].distro_version], "__none")
+ PACKAGE_MANAGER = local.package_manager[enos_host_info.hosts[each.key].distro]
+ RETRY_INTERVAL = var.retry_interval
+ TIMEOUT_SECONDS = var.timeout
+ }
+
+ scripts = [abspath("${path.module}/scripts/add-repos.sh")]
+
+ transport = {
+ ssh = {
+ host = each.value.public_ip
+ }
+ }
+}
+
+# Install any required packages.
+resource "enos_remote_exec" "install_packages" {
+ for_each = var.hosts
+ depends_on = [
+ enos_remote_exec.synchronize_repos,
+ enos_remote_exec.add_repos,
+ ]
+
+ environment = {
+ PACKAGE_MANAGER = local.package_manager[enos_host_info.hosts[each.key].distro]
PACKAGES = length(var.packages) >= 1 ? join(" ", var.packages) : "__skip"
RETRY_INTERVAL = var.retry_interval
TIMEOUT_SECONDS = var.timeout
diff --git a/enos/modules/install_packages/scripts/add-repos.sh b/enos/modules/install_packages/scripts/add-repos.sh
new file mode 100644
index 0000000000..3f4ee881e2
--- /dev/null
+++ b/enos/modules/install_packages/scripts/add-repos.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+set -e
+
+fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+[[ -z "${PACKAGE_MANAGER}" ]] && fail "PACKAGE_MANAGER env variable has not been set"
+[[ -z "${RETRY_INTERVAL}" ]] && fail "RETRY_INTERVAL env variable has not been set"
+[[ -z "${TIMEOUT_SECONDS}" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
+
+# Add any repositories that have have been passed in
+add_repos() {
+ # If we don't have any repos on the list for this distro, no action needed.
+ if [ ${#DISTRO_REPOS[@]} -lt 1 ]; then
+ echo "DISTRO_REPOS is empty; No repos required for the packages for this Linux distro."
+ return 0
+ fi
+
+ case $PACKAGE_MANAGER in
+ apt)
+ # NOTE: We do not currently add any apt repositories in our scenarios. I suspect if that time
+ # comes we'll need to add support for apt-key here.
+ for repo in ${DISTRO_REPOS}; do
+ if [ "$repo" == "__none" ]; then
+ continue
+ fi
+ sudo add-apt-repository "${repo}"
+ done
+ ;;
+ dnf)
+ for repo in ${DISTRO_REPOS}; do
+ if [ "$repo" == "__none" ]; then
+ continue
+ fi
+ sudo dnf install -y "${repo}"
+ sudo dnf makecache -y
+ done
+ ;;
+ yum)
+ for repo in ${DISTRO_REPOS}; do
+ if [ "$repo" == "__none" ]; then
+ continue
+ fi
+ sudo yum install -y "${repo}"
+ sudo yum makecache -y
+ done
+ ;;
+ zypper)
+ # Add each repo
+ for repo in ${DISTRO_REPOS}; do
+ if [ "$repo" == "__none" ]; then
+ continue
+ fi
+ if sudo zypper lr "${repo}"; then
+ echo "A repo named ${repo} already exists, skipping..."
+ continue
+ fi
+ sudo zypper --gpg-auto-import-keys --non-interactive addrepo "${repo}"
+ done
+ sudo zypper --gpg-auto-import-keys ref
+ sudo zypper --gpg-auto-import-keys refs
+ ;;
+ *)
+ fail "Unsupported package manager: ${PACKAGE_MANAGER}"
+ esac
+}
+
+begin_time=$(date +%s)
+end_time=$((begin_time + TIMEOUT_SECONDS))
+while [ "$(date +%s)" -lt "$end_time" ]; do
+ if add_repos; then
+ exit 0
+ fi
+
+ sleep "$RETRY_INTERVAL"
+done
+
+fail "Timed out waiting for distro repos to be set up"
diff --git a/enos/modules/install_packages/scripts/install-packages.sh b/enos/modules/install_packages/scripts/install-packages.sh
index 29868cd33d..cb771d2b9d 100644
--- a/enos/modules/install_packages/scripts/install-packages.sh
+++ b/enos/modules/install_packages/scripts/install-packages.sh
@@ -9,41 +9,97 @@ fail() {
exit 1
}
-[[ -z "$RETRY_INTERVAL" ]] && fail "RETRY_INTERVAL env variable has not been set"
-[[ -z "$TIMEOUT_SECONDS" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
-[[ -z "$PACKAGES" ]] && fail "PACKAGES env variable has not been set"
+[[ -z "${RETRY_INTERVAL}" ]] && fail "RETRY_INTERVAL env variable has not been set"
+[[ -z "${TIMEOUT_SECONDS}" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
+[[ -z "${PACKAGES}" ]] && fail "PACKAGES env variable has not been set"
+[[ -z "${PACKAGE_MANAGER}" ]] && fail "PACKAGE_MANAGER env variable has not been set"
+# Install packages based on the provided packages and package manager. We assume that the repositories
+# have already been synchronized by the repo setup that is a prerequisite for this script.
install_packages() {
- if [ "$PACKAGES" = "__skip" ]; then
+ if [[ "${PACKAGES}" = "__skip" ]]; then
return 0
fi
- echo "Installing Dependencies: $PACKAGES"
- if [ -f /etc/debian_version ]; then
- # Do our best to make sure that we don't race with cloud-init. Wait a reasonable time until we
- # see ec2 in the sources list. Very rarely cloud-init will take longer than we wait. In that case
- # we'll just install our packages.
- grep ec2 /etc/apt/sources.list || true
+ set -x
+ echo "Installing Dependencies: ${PACKAGES}"
- cd /tmp
- sudo apt update
- # shellcheck disable=2068
- sudo apt install -y ${PACKAGES[@]}
- else
- cd /tmp
- # shellcheck disable=2068
- sudo yum -y install ${PACKAGES[@]}
- fi
+ # Use the default package manager of the current Linux distro to install packages
+ case $PACKAGE_MANAGER in
+ apt)
+ for package in ${PACKAGES}; do
+ if dpkg -s "${package}"; then
+ echo "Skipping installation of ${package} because it is already installed"
+ continue
+ else
+ echo "Installing ${package}"
+ local output
+ if ! output=$(sudo apt install -y "${package}" 2>&1); then
+ echo "Failed to install ${package}: ${output}" 1>&2
+ return 1
+ fi
+ fi
+ done
+ ;;
+ dnf)
+ for package in ${PACKAGES}; do
+ if rpm -q "${package}"; then
+ echo "Skipping installation of ${package} because it is already installed"
+ continue
+ else
+ echo "Installing ${package}"
+ local output
+ if ! output=$(sudo dnf -y install "${package}" 2>&1); then
+ echo "Failed to install ${package}: ${output}" 1>&2
+ return 1
+ fi
+ fi
+ done
+ ;;
+ yum)
+ for package in ${PACKAGES}; do
+ if rpm -q "${package}"; then
+ echo "Skipping installation of ${package} because it is already installed"
+ continue
+ else
+ echo "Installing ${package}"
+ local output
+ if ! output=$(sudo yum -y install "${package}" 2>&1); then
+ echo "Failed to install ${package}: ${output}" 1>&2
+ return 1
+ fi
+ fi
+ done
+ ;;
+ zypper)
+ for package in ${PACKAGES}; do
+ if rpm -q "${package}"; then
+ echo "Skipping installation of ${package} because it is already installed"
+ continue
+ else
+ echo "Installing ${package}"
+ local output
+ if ! output=$(sudo zypper --non-interactive install -y -l --force-resolution "${package}" 2>&1); then
+ echo "Failed to install ${package}: ${output}" 1>&2
+ return 1
+ fi
+ fi
+ done
+ ;;
+ *)
+ fail "No matching package manager provided."
+ ;;
+ esac
}
begin_time=$(date +%s)
end_time=$((begin_time + TIMEOUT_SECONDS))
-while [ "$(date +%s)" -lt "$end_time" ]; do
+while [[ "$(date +%s)" -lt "${end_time}" ]]; do
if install_packages; then
exit 0
fi
- sleep "$RETRY_INTERVAL"
+ sleep "${RETRY_INTERVAL}"
done
fail "Timed out waiting for packages to install"
diff --git a/enos/modules/install_packages/scripts/synchronize-repos.sh b/enos/modules/install_packages/scripts/synchronize-repos.sh
new file mode 100644
index 0000000000..034b04b90d
--- /dev/null
+++ b/enos/modules/install_packages/scripts/synchronize-repos.sh
@@ -0,0 +1,118 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+set -e
+
+fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+[[ -z "${PACKAGE_MANAGER}" ]] && fail "PACKAGE_MANAGER env variable has not been set"
+[[ -z "${RETRY_INTERVAL}" ]] && fail "RETRY_INTERVAL env variable has not been set"
+[[ -z "${TIMEOUT_SECONDS}" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
+
+# The SLES AMI's do not come configured with Zypper repositories by default. To get them you
+# have to run SUSEConnect to register the instance with SUSE. On the AMI this is handled
+# automatically by a oneshot systemd unit called guestregister.service. This oneshot service needs
+# to complete before any other repo or package steps are completed. At the time of writing it's very
+# unreliable so we have to ensure that it has correctly executed ourselves or restart it. We do this
+# by checking if the guestregister.service has reached the correct "inactive" state that we need.
+# If it hasn't reached that state it's usually in some sort of active state, i.e. running, or it has
+# failed. If it's in one of the active states we need to let it continue and check the status when
+# it completes. If it has completed but is failed we'll restart the service to re-run the script that
+# executes SUSEConnect.
+sles_check_guestregister_service_and_restart_if_failed() {
+ local active_state
+ local failed_state
+
+ # systemctl returns non-zero exit codes. We rely on output here because all states don't have
+ # their own exit code.
+ set +e
+ active_state=$(sudo systemctl is-active guestregister.service)
+ failed_state=$(sudo systemctl is-failed guestregister.service)
+ set -e
+
+ case "$active_state" in
+ active|activating|deactivating)
+ # It's running so we'll return 1 and get retried by the caller
+ echo "the guestregister.service is still in the ${active_state} state" 1>&2
+ return 1
+ ;;
+ *)
+ if [ "$active_state" == "inactive" ] && [ "$failed_state" == "inactive" ]; then
+ # The oneshot has completed and hasn't "failed"
+ echo "the guestregister.service is 'inactive' for both active and failed states"
+ return 0
+ fi
+
+ # Our service is stopped and failed, restart it and hope it works the next time
+ sudo systemctl restart --wait guestregister.service
+ ;;
+ esac
+}
+
+# Check or restart the guestregister service if it has failed. If it passes do another check to make
+# sure that the zypper repositories list isn't empty.
+sles_ensure_suseconnect() {
+ local health_output
+ if ! health_output=$(sles_check_guestregister_service_and_restart_if_failed); then
+ echo "the guestregister.service failed to reach a healthy state: ${health_output}" 1>&2
+ return 1
+ fi
+
+ # Make sure Zypper has repositories.
+ if ! lr_output=$(zypper lr); then
+ echo "The guestregister.service failed. Unable to SUSEConnect and thus have no Zypper repositories: ${lr_output}: ${health_output}." 1>&2
+ return 1
+ fi
+
+ return 0
+}
+
+# Synchronize our repositories so that futher installation steps are working with updated cache
+# and repo metadata.
+synchronize_repos() {
+ case $PACKAGE_MANAGER in
+ apt)
+ sudo apt update
+ ;;
+ dnf)
+ sudo dnf makecache
+ ;;
+ yum)
+ sudo yum makecache
+ ;;
+ zypper)
+ if [ "$DISTRO" == "sles" ]; then
+ if ! sles_ensure_suseconnect; then
+ return 1
+ fi
+ fi
+ sudo zypper --gpg-auto-import-keys --non-interactive ref
+ sudo zypper --gpg-auto-import-keys --non-interactive refs
+ ;;
+ *)
+ return 0
+ ;;
+ esac
+}
+
+# Before we start to modify repositories and install packages we'll wait for cloud-init to finish
+# so it doesn't race with any of our package installations.
+# We run as sudo becase Amazon Linux 2 throws Python 2.7 errors when running `cloud-init status` as
+# non-root user (known bug).
+sudo cloud-init status --wait
+
+begin_time=$(date +%s)
+end_time=$((begin_time + TIMEOUT_SECONDS))
+while [ "$(date +%s)" -lt "$end_time" ]; do
+ if synchronize_repos; then
+ exit 0
+ fi
+
+ sleep "$RETRY_INTERVAL"
+done
+
+fail "Timed out waiting for distro repos to be set up"
diff --git a/enos/modules/replication_data/main.tf b/enos/modules/replication_data/main.tf
index dec9640837..91c89a4b08 100644
--- a/enos/modules/replication_data/main.tf
+++ b/enos/modules/replication_data/main.tf
@@ -3,68 +3,28 @@
// An arithmetic module for calculating inputs and outputs for various replication steps.
-// Get the first follower out of the hosts set
-variable "follower_hosts" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- default = {}
-}
-
-output "follower_host_1" {
- value = try(var.follower_hosts[0], null)
-}
-
-output "follower_public_ip_1" {
- value = try(var.follower_hosts[0].public_ip, null)
-}
-
-output "follower_private_ip_1" {
- value = try(var.follower_hosts[0].private_ip, null)
-}
-
-output "follower_host_2" {
- value = try(var.follower_hosts[1], null)
-}
-
-output "follower_public_ip_2" {
- value = try(var.follower_hosts[1].public_ip, null)
-}
-
-output "follower_private_ip_2" {
- value = try(var.follower_hosts[1].private_ip, null)
-}
-
-// Calculate our remainder hosts after we've added and removed leader
-variable "initial_hosts" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- default = {}
-}
-
-variable "initial_hosts_count" {
- type = number
- default = 0
-}
-
variable "added_hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
default = {}
}
-variable "added_hosts_count" {
- type = number
- default = 0
+variable "initial_hosts" {
+ description = "The initial set of Vault cluster hosts before removing and adding hosts"
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ default = {}
}
variable "removed_primary_host" {
type = object({
+ ipv6 = string
private_ip = string
public_ip = string
})
@@ -73,6 +33,7 @@ variable "removed_primary_host" {
variable "removed_follower_host" {
type = object({
+ ipv6 = string
private_ip = string
public_ip = string
})
@@ -80,23 +41,9 @@ variable "removed_follower_host" {
}
locals {
- remaining_hosts_count = max((var.initial_hosts_count + var.added_hosts_count - 2), 0)
- indices = [for idx in range(local.remaining_hosts_count) : idx]
- remaining_initial = setsubtract(values(var.initial_hosts), [var.removed_primary_host, var.removed_follower_host])
- remaining_hosts_list = tolist(setunion(values(var.added_hosts), local.remaining_initial))
- remaining_hosts = zipmap(local.indices, local.remaining_hosts_list)
-}
-
-output "remaining_initial_count" {
- value = length(local.remaining_initial)
-}
-
-output "remaining_initial_hosts" {
- value = local.remaining_initial
-}
-
-output "remaining_hosts_count" {
- value = local.remaining_hosts_count
+ remaining_initial = setsubtract(values(var.initial_hosts), [var.removed_primary_host, var.removed_follower_host])
+ remaining_hosts_list = tolist(setunion(values(var.added_hosts), local.remaining_initial))
+ remaining_hosts = { for idx in range(length(local.remaining_hosts_list)) : idx => local.remaining_hosts_list[idx] }
}
output "remaining_hosts" {
diff --git a/enos/modules/seal_pkcs11/main.tf b/enos/modules/seal_pkcs11/main.tf
index 8157808932..084d364028 100644
--- a/enos/modules/seal_pkcs11/main.tf
+++ b/enos/modules/seal_pkcs11/main.tf
@@ -100,6 +100,13 @@ module "target" {
amd64 = "t3a.small"
arm64 = "t4g.small"
}
+ ports_ingress = [
+ {
+ description = "SSH"
+ port = 22
+ protocol = "tcp"
+ },
+ ]
// Make sure it's not too long as we use this for aws resources that size maximums that are easy
// to hit.
project_name = substr("vault-ci-softhsm-${local.id}", 0, 32)
diff --git a/enos/modules/shutdown_multiple_nodes/main.tf b/enos/modules/shutdown_multiple_nodes/main.tf
index 27f23c74c9..2cfe646c25 100644
--- a/enos/modules/shutdown_multiple_nodes/main.tf
+++ b/enos/modules/shutdown_multiple_nodes/main.tf
@@ -9,12 +9,7 @@ terraform {
}
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "old_vault_instances" {
+variable "old_hosts" {
type = map(object({
private_ip = string
public_ip = string
@@ -22,17 +17,8 @@ variable "old_vault_instances" {
description = "The vault cluster instances to be shutdown"
}
-locals {
- public_ips = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.old_vault_instances)[idx].public_ip
- private_ip = values(var.old_vault_instances)[idx].private_ip
- }
- }
-}
-
resource "enos_remote_exec" "shutdown_multiple_nodes" {
- for_each = local.public_ips
+ for_each = var.old_hosts
inline = ["sudo shutdown -H --no-wall; exit 0"]
transport = {
diff --git a/enos/modules/shutdown_node/main.tf b/enos/modules/shutdown_node/main.tf
index b31762f37f..a077a334f9 100644
--- a/enos/modules/shutdown_node/main.tf
+++ b/enos/modules/shutdown_node/main.tf
@@ -9,9 +9,13 @@ terraform {
}
}
-variable "node_public_ip" {
- type = string
- description = "Node Public IP address"
+variable "host" {
+ type = object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ })
+ description = "The node to shut down"
}
resource "enos_remote_exec" "shutdown_node" {
@@ -19,7 +23,7 @@ resource "enos_remote_exec" "shutdown_node" {
transport = {
ssh = {
- host = var.node_public_ip
+ host = var.host.public_ip
}
}
}
diff --git a/enos/modules/softhsm_create_vault_keys/main.tf b/enos/modules/softhsm_create_vault_keys/main.tf
index d503e0ce65..4132de8f22 100644
--- a/enos/modules/softhsm_create_vault_keys/main.tf
+++ b/enos/modules/softhsm_create_vault_keys/main.tf
@@ -15,6 +15,7 @@ variable "cluster_id" {
variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
@@ -22,11 +23,12 @@ variable "hosts" {
}
locals {
- pin = resource.random_string.pin.result
- aes_label = "vault_hsm_aes_${local.pin}"
- hmac_label = "vault_hsm_hmac_${local.pin}"
- target = tomap({ "1" = var.hosts[0] })
- token = "${var.cluster_id}_${local.pin}"
+ pin = resource.random_string.pin.result
+ aes_label = "vault_hsm_aes_${local.pin}"
+ hmac_label = "vault_hsm_hmac_${local.pin}"
+ seal_attributes = jsondecode(resource.enos_remote_exec.create_keys.stdout)
+ target = tomap({ "0" = var.hosts[0] })
+ token = "${var.cluster_id}_${local.pin}"
}
resource "random_string" "pin" {
@@ -95,10 +97,6 @@ resource "enos_remote_exec" "get_keys" {
}
}
-locals {
- seal_attributes = jsondecode(resource.enos_remote_exec.create_keys.stdout)
-}
-
output "seal_attributes" {
description = "Seal device specific attributes. Contains all required keys for the seal stanza"
value = local.seal_attributes
diff --git a/enos/modules/softhsm_distribute_vault_keys/main.tf b/enos/modules/softhsm_distribute_vault_keys/main.tf
index 394f13faf1..0ccebe1c71 100644
--- a/enos/modules/softhsm_distribute_vault_keys/main.tf
+++ b/enos/modules/softhsm_distribute_vault_keys/main.tf
@@ -12,6 +12,7 @@ terraform {
variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
@@ -26,6 +27,7 @@ variable "token_base64" {
locals {
// The user/group name for softhsm
softhsm_groups = {
+ "amzn" = "ods"
"rhel" = "ods"
"ubuntu" = "softhsm"
}
diff --git a/enos/modules/softhsm_init/main.tf b/enos/modules/softhsm_init/main.tf
index 3d31803e52..edadca849a 100644
--- a/enos/modules/softhsm_init/main.tf
+++ b/enos/modules/softhsm_init/main.tf
@@ -12,6 +12,7 @@ terraform {
variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
@@ -30,6 +31,7 @@ locals {
// Where the default configuration is
config_paths = {
+ "amzn" = "/etc/softhsm2.conf"
"rhel" = "/etc/softhsm2.conf"
"ubuntu" = "/etc/softhsm/softhsm2.conf"
}
diff --git a/enos/modules/softhsm_install/main.tf b/enos/modules/softhsm_install/main.tf
index 3e49ce8cfa..8659104d5b 100644
--- a/enos/modules/softhsm_install/main.tf
+++ b/enos/modules/softhsm_install/main.tf
@@ -11,6 +11,7 @@ terraform {
variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
@@ -36,14 +37,51 @@ variable "timeout" {
}
locals {
- packages = var.include_tools ? ["softhsm", "opensc"] : ["softhsm"]
+ packages = var.include_tools ? {
+ // These packages match the distros that are currently defined in the `ec2_info` module.
+ amzn = {
+ "2023" = ["softhsm", "opensc"]
+ }
+ rhel = {
+ "8.10" = ["softhsm", "opensc"]
+ "9.4" = ["softhsm", "opensc"]
+ }
+ ubuntu = {
+ "20.04" = ["softhsm", "opensc"]
+ "22.04" = ["softhsm", "opensc"]
+ "24.04" = ["softhsm2", "opensc"]
+ }
+ } : {
+ amzn = {
+ "2023" = ["softhsm"]
+ }
+ rhel = {
+ "8.10" = ["softhsm"]
+ "9.4" = ["softhsm"]
+ }
+ ubuntu = {
+ "20.04" = ["softhsm"]
+ "22.04" = ["softhsm"]
+ "24.04" = ["softhsm2"]
+ }
+ }
+}
+
+// Get the host information so we can ensure that we install the correct packages depending on the
+// distro and distro version
+resource "enos_host_info" "target" {
+ transport = {
+ ssh = {
+ host = var.hosts["0"].public_ip
+ }
+ }
}
module "install_softhsm" {
source = "../install_packages"
hosts = var.hosts
- packages = local.packages
+ packages = local.packages[enos_host_info.target.distro][enos_host_info.target.distro_version]
}
resource "enos_remote_exec" "find_shared_object" {
diff --git a/enos/modules/start_vault/main.tf b/enos/modules/start_vault/main.tf
index b0286d24f8..9e386e01e4 100644
--- a/enos/modules/start_vault/main.tf
+++ b/enos/modules/start_vault/main.tf
@@ -7,18 +7,36 @@ terraform {
# to the public registry
enos = {
source = "registry.terraform.io/hashicorp-forge/enos"
- version = ">= 0.4.10"
+ version = ">= 0.5.3"
}
}
}
locals {
+ api_addr_localhost = var.ip_version == 4 ? "http://127.0.0.1:${var.listener_port}" : "http://[::1]:${var.listener_port}"
+ api_addrs = tolist([for h in var.hosts : {
+ 4 : "http://${h.public_ip}:${var.listener_port}",
+ 6 : "http://[${h.ipv6}]:${var.listener_port}",
+ }])
+ api_addrs_internal = tolist([for h in var.hosts : {
+ 4 : "http://${h.private_ip}:${var.listener_port}",
+ 6 : "http://[${h.ipv6}]:${var.listener_port}",
+ }])
bin_path = "${var.install_dir}/vault"
+ cluster_addrs = tolist([for h in var.hosts : {
+ 4 : "http://${h.public_ip}:${var.cluster_port}",
+ 6 : "http://[${h.ipv6}]:${var.cluster_port}",
+ }])
+ cluster_addrs_internal = tolist([for h in var.hosts : {
+ 4 : "http://${h.private_ip}:${var.cluster_port}",
+ 6 : "http://[${h.ipv6}]:${var.cluster_port}",
+ }])
// In order to get Terraform to plan we have to use collections with keys that are known at plan
// time. Here we're creating locals that keep track of index values that point to our target hosts.
- followers = toset(slice(local.instances, 1, length(local.instances)))
- instances = [for idx in range(length(var.target_hosts)) : tostring(idx)]
- leader = toset(slice(local.instances, 0, 1))
+ followers = toset(slice(local.instances, 1, length(local.instances)))
+ instances = [for idx in range(length(var.hosts)) : tostring(idx)]
+ leader = toset(slice(local.instances, 0, 1))
+ listener_address = var.ip_version == 4 ? "0.0.0.0:${var.listener_port}" : "[::]:${var.listener_port}"
// Handle cases where we might have to distribute HSM tokens for the pkcs11 seal before starting
// vault.
token_base64 = try(lookup(var.seal_attributes, "token_base64", ""), "")
@@ -52,7 +70,9 @@ locals {
// keys on a machines that have different shared object locations.
merge(
try({ for key, val in var.seal_attributes : key => val if key != "token_base64" && key != "token_dir" }, {}),
- try({ lib = module.maybe_configure_hsm.lib }, {})
+ # Note: the below reference has to point to a specific instance of the maybe_configure_hsm
+ # module (in this case [0]) due to the maybe_configure_hsm module call using `count` to control whether it runs or not.
+ try({ lib = module.maybe_configure_hsm[0].lib }, {})
),
)
}
@@ -81,7 +101,9 @@ locals {
},
merge(
try({ for key, val in var.seal_attributes_secondary : key => val if key != "token_base64" && key != "token_dir" }, {}),
- try({ lib = module.maybe_configure_hsm_secondary.lib }, {})
+ # Note: the below reference has to point to a specific instance of the maybe_configure_hsm_secondary
+ # module (in this case [0]) due to the maybe_configure_hsm_secondary module call using `count` to control whether it runs or not.
+ try({ lib = module.maybe_configure_hsm_secondary[0].lib }, {})
),
)
}
@@ -90,8 +112,9 @@ locals {
attributes = null
}
}
- seal_secondary = local.seals_secondary[var.seal_type_secondary]
- storage_config = [for idx, host in var.target_hosts : (var.storage_backend == "raft" ?
+ seal_secondary = local.seals_secondary[var.seal_type_secondary]
+ storage_address = var.ip_version == 4 ? "0.0.0.0:${var.external_storage_port}" : "[::]:${var.external_storage_port}"
+ storage_attributes = [for idx, host in var.hosts : (var.storage_backend == "raft" ?
merge(
{
node_id = "${var.storage_node_prefix}_${idx}"
@@ -99,10 +122,16 @@ locals {
var.storage_backend_attrs
) :
{
- address = "127.0.0.1:8500"
+ address = local.storage_address
path = "vault"
})
]
+ storage_retry_join = {
+ "raft" : {
+ auto_join : "provider=aws addr_type=${var.ip_version == 4 ? "private_v4" : "public_v6"} tag_key=${var.cluster_tag_key} tag_value=${var.cluster_name}",
+ auto_join_scheme : "http",
+ },
+ }
}
# You might be wondering why our start_vault module, which supports shamir, awskms, and pkcs11 seal
@@ -135,16 +164,18 @@ locals {
# the key data that was passed in via seal attributes.
module "maybe_configure_hsm" {
source = "../softhsm_distribute_vault_keys"
+ count = (var.seal_type == "pkcs11" || var.seal_type_secondary == "pkcs11") ? 1 : 0
- hosts = var.target_hosts
+ hosts = var.hosts
token_base64 = local.token_base64
}
module "maybe_configure_hsm_secondary" {
source = "../softhsm_distribute_vault_keys"
depends_on = [module.maybe_configure_hsm]
+ count = (var.seal_type == "pkcs11" || var.seal_type_secondary == "pkcs11") ? 1 : 0
- hosts = var.target_hosts
+ hosts = var.hosts
token_base64 = local.token_base64_secondary
}
@@ -159,20 +190,21 @@ resource "enos_vault_start" "leader" {
config_mode = var.config_mode
environment = var.environment
config = {
- api_addr = "http://${var.target_hosts[each.value].private_ip}:8200"
- cluster_addr = "http://${var.target_hosts[each.value].private_ip}:8201"
+ api_addr = local.api_addrs_internal[tonumber(each.value)][var.ip_version]
+ cluster_addr = local.cluster_addrs_internal[tonumber(each.value)][var.ip_version]
cluster_name = var.cluster_name
listener = {
type = "tcp"
attributes = {
- address = "0.0.0.0:8200"
+ address = local.listener_address
tls_disable = "true"
}
}
log_level = var.log_level
storage = {
type = var.storage_backend
- attributes = ({ for key, value in local.storage_config[each.key] : key => value })
+ attributes = local.storage_attributes[each.key]
+ retry_join = try(local.storage_retry_join[var.storage_backend], null)
}
seals = local.seals
ui = true
@@ -184,7 +216,7 @@ resource "enos_vault_start" "leader" {
transport = {
ssh = {
- host = var.target_hosts[each.value].public_ip
+ host = var.hosts[each.value].public_ip
}
}
}
@@ -200,20 +232,21 @@ resource "enos_vault_start" "followers" {
config_mode = var.config_mode
environment = var.environment
config = {
- api_addr = "http://${var.target_hosts[each.value].private_ip}:8200"
- cluster_addr = "http://${var.target_hosts[each.value].private_ip}:8201"
+ api_addr = local.api_addrs_internal[tonumber(each.value)][var.ip_version]
+ cluster_addr = local.cluster_addrs_internal[tonumber(each.value)][var.ip_version]
cluster_name = var.cluster_name
listener = {
type = "tcp"
attributes = {
- address = "0.0.0.0:8200"
+ address = local.listener_address
tls_disable = "true"
}
}
log_level = var.log_level
storage = {
type = var.storage_backend
- attributes = { for key, value in local.storage_config[each.key] : key => value }
+ attributes = { for key, value in local.storage_attributes[each.key] : key => value }
+ retry_join = try(local.storage_retry_join[var.storage_backend], null)
}
seals = local.seals
ui = true
@@ -225,7 +258,7 @@ resource "enos_vault_start" "followers" {
transport = {
ssh = {
- host = var.target_hosts[each.value].public_ip
+ host = var.hosts[each.value].public_ip
}
}
}
diff --git a/enos/modules/start_vault/outputs.tf b/enos/modules/start_vault/outputs.tf
index b3107bc9d4..c20e7b8016 100644
--- a/enos/modules/start_vault/outputs.tf
+++ b/enos/modules/start_vault/outputs.tf
@@ -1,11 +1,31 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
+output "api_addr_localhost" {
+ description = "The localhost API address"
+ value = local.api_addr_localhost
+}
+
+output "api_addrs" {
+ description = "The external API addresses of all nodes the cluster"
+ value = local.api_addrs
+}
+
output "cluster_name" {
description = "The Vault cluster name"
value = var.cluster_name
}
+output "cluster_port" {
+ description = "The Vault cluster request forwarding listener port"
+ value = var.cluster_port
+}
+
+output "external_storage_port" {
+ description = "The Vault cluster non-raft external storage port"
+ value = var.external_storage_port
+}
+
output "followers" {
description = "The follower enos_vault_start resources"
value = enos_vault_start.followers
@@ -16,18 +36,28 @@ output "leader" {
value = enos_vault_start.leader
}
+output "ipv6s" {
+ description = "Vault cluster target host ipv6s"
+ value = [for host in var.hosts : host.ipv6]
+}
+
+output "listener_port" {
+ description = "The Vault cluster TCP listener port"
+ value = var.listener_port
+}
+
output "private_ips" {
description = "Vault cluster target host private_ips"
- value = [for host in var.target_hosts : host.private_ip]
+ value = [for host in var.hosts : host.private_ip]
}
output "public_ips" {
description = "Vault cluster target host public_ips"
- value = [for host in var.target_hosts : host.public_ip]
+ value = [for host in var.hosts : host.public_ip]
}
-output "target_hosts" {
+output "hosts" {
description = "The vault cluster instances that were created"
- value = var.target_hosts
+ value = var.hosts
}
diff --git a/enos/modules/start_vault/variables.tf b/enos/modules/start_vault/variables.tf
index bcfcbd85ae..2571b0c2dd 100644
--- a/enos/modules/start_vault/variables.tf
+++ b/enos/modules/start_vault/variables.tf
@@ -6,6 +6,18 @@ variable "cluster_name" {
description = "The Vault cluster name"
}
+variable "cluster_port" {
+ type = number
+ description = "The cluster port for Vault to listen on"
+ default = 8201
+}
+
+variable "cluster_tag_key" {
+ type = string
+ description = "The Vault cluster tag key"
+ default = "retry_join"
+}
+
variable "config_dir" {
type = string
description = "The directory to use for Vault configuration"
@@ -28,12 +40,37 @@ variable "environment" {
default = null
}
+variable "external_storage_port" {
+ type = number
+ description = "The port to connect to when using external storage"
+ default = 8500
+}
+
+variable "hosts" {
+ description = "The target machines host addresses to use for the Vault cluster"
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+}
+
variable "install_dir" {
type = string
description = "The directory where the vault binary will be installed"
default = "/opt/vault/bin"
}
+variable "ip_version" {
+ type = number
+ description = "The IP version to use for the Vault TCP listeners"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
variable "license" {
type = string
sensitive = true
@@ -58,6 +95,12 @@ variable "manage_service" {
default = true
}
+variable "listener_port" {
+ type = number
+ description = "The port for Vault to listen on"
+ default = 8200
+}
+
variable "seal_alias" {
type = string
description = "The primary seal alias name"
@@ -142,11 +185,3 @@ variable "storage_node_prefix" {
description = "A prefix to use for each node in the Vault storage configuration"
default = "node"
}
-
-variable "target_hosts" {
- description = "The target machines host addresses to use for the Vault cluster"
- type = map(object({
- private_ip = string
- public_ip = string
- }))
-}
diff --git a/enos/modules/stop_vault/main.tf b/enos/modules/stop_vault/main.tf
index 05582a2ab0..6dd477d4dd 100644
--- a/enos/modules/stop_vault/main.tf
+++ b/enos/modules/stop_vault/main.tf
@@ -18,16 +18,17 @@ variable "service_name" {
default = "vault"
}
-variable "target_hosts" {
+variable "hosts" {
description = "The target machines host addresses to use for the Vault cluster"
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
}
resource "enos_remote_exec" "shutdown_multiple_nodes" {
- for_each = var.target_hosts
+ for_each = var.hosts
inline = ["sudo systemctl stop ${var.service_name}.service; sleep 5"]
transport = {
diff --git a/enos/modules/target_ec2_fleet/main.tf b/enos/modules/target_ec2_fleet/main.tf
index 8375d33dae..411d1744b1 100644
--- a/enos/modules/target_ec2_fleet/main.tf
+++ b/enos/modules/target_ec2_fleet/main.tf
@@ -335,4 +335,5 @@ data "aws_instance" "targets" {
for_each = local.instances
instance_id = aws_ec2_fleet.targets.fleet_instance_set[0].instance_ids[each.key]
+
}
diff --git a/enos/modules/target_ec2_fleet/outputs.tf b/enos/modules/target_ec2_fleet/outputs.tf
index 1672a24179..505db0e4eb 100644
--- a/enos/modules/target_ec2_fleet/outputs.tf
+++ b/enos/modules/target_ec2_fleet/outputs.tf
@@ -10,5 +10,6 @@ output "hosts" {
value = { for idx in range(var.instance_count) : idx => {
public_ip = data.aws_instance.targets[idx].public_ip
private_ip = data.aws_instance.targets[idx].private_ip
+ ipv6 = try(data.aws_instance.targets[idx].ipv6_addresses[0], null)
} }
}
diff --git a/enos/modules/target_ec2_fleet/variables.tf b/enos/modules/target_ec2_fleet/variables.tf
index 606cf5c298..f0eb87bf5d 100644
--- a/enos/modules/target_ec2_fleet/variables.tf
+++ b/enos/modules/target_ec2_fleet/variables.tf
@@ -26,6 +26,12 @@ variable "common_tags" {
}
}
+variable "disable_selinux" {
+ description = "Optionally disable SELinux for certain distros/versions"
+ type = bool
+ default = true
+}
+
variable "instance_mem_min" {
description = "The minimum amount of memory in mebibytes for each instance in the fleet. (1 MiB = 1024 bytes)"
type = number
diff --git a/enos/modules/target_ec2_instances/locals.tf b/enos/modules/target_ec2_instances/locals.tf
new file mode 100644
index 0000000000..8831b7ec26
--- /dev/null
+++ b/enos/modules/target_ec2_instances/locals.tf
@@ -0,0 +1,11 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+locals {
+ hosts = { for idx in range(var.instance_count) : idx => {
+ ipv6 = try(aws_instance.targets[idx].ipv6_addresses[0], "")
+ public_ip = aws_instance.targets[idx].public_ip
+ private_ip = aws_instance.targets[idx].private_ip
+ }
+ }
+}
diff --git a/enos/modules/target_ec2_instances/main.tf b/enos/modules/target_ec2_instances/main.tf
index ddce7ffa74..68a584859b 100644
--- a/enos/modules/target_ec2_instances/main.tf
+++ b/enos/modules/target_ec2_instances/main.tf
@@ -141,78 +141,21 @@ resource "aws_security_group" "target" {
description = "Target instance security group"
vpc_id = var.vpc_id
- # SSH traffic
- ingress {
- from_port = 22
- to_port = 22
- protocol = "tcp"
- cidr_blocks = flatten([
- formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
- join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
- ])
- }
+ # External ingress
+ dynamic "ingress" {
+ for_each = var.ports_ingress
- # Vault traffic
- ingress {
- from_port = 8200
- to_port = 8201
- protocol = "tcp"
- cidr_blocks = flatten([
- formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
- join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
- formatlist("%s/32", var.ssh_allow_ips)
- ])
- }
-
- # Consul traffic
- ingress {
- from_port = 8300
- to_port = 8302
- protocol = "tcp"
- cidr_blocks = flatten([
- formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
- join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
- ])
- }
-
- ingress {
- from_port = 8301
- to_port = 8302
- protocol = "udp"
- cidr_blocks = flatten([
- formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
- join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
- ])
- }
-
- ingress {
- from_port = 8500
- to_port = 8503
- protocol = "tcp"
- cidr_blocks = flatten([
- formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
- join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
- ])
- }
-
- ingress {
- from_port = 8600
- to_port = 8600
- protocol = "tcp"
- cidr_blocks = flatten([
- formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
- join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
- ])
- }
-
- ingress {
- from_port = 8600
- to_port = 8600
- protocol = "udp"
- cidr_blocks = flatten([
- formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
- join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
- ])
+ content {
+ from_port = ingress.value.port
+ to_port = ingress.value.port
+ protocol = ingress.value.protocol
+ cidr_blocks = flatten([
+ formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
+ join(",", data.aws_vpc.vpc.cidr_block_associations.*.cidr_block),
+ formatlist("%s/32", var.ssh_allow_ips)
+ ])
+ ipv6_cidr_blocks = data.aws_vpc.vpc.ipv6_cidr_block != "" ? [data.aws_vpc.vpc.ipv6_cidr_block] : null
+ }
}
# Internal traffic
@@ -225,10 +168,11 @@ resource "aws_security_group" "target" {
# External traffic
egress {
- from_port = 0
- to_port = 0
- protocol = "-1"
- cidr_blocks = ["0.0.0.0/0"]
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ ipv6_cidr_blocks = ["::/0"]
}
tags = merge(
@@ -257,3 +201,11 @@ resource "aws_instance" "targets" {
},
)
}
+
+module "disable_selinux" {
+ depends_on = [aws_instance.targets]
+ source = "../disable_selinux"
+ count = var.disable_selinux == true ? 1 : 0
+
+ hosts = local.hosts
+}
diff --git a/enos/modules/target_ec2_instances/outputs.tf b/enos/modules/target_ec2_instances/outputs.tf
index b2bc75ce60..674c5cf7b1 100644
--- a/enos/modules/target_ec2_instances/outputs.tf
+++ b/enos/modules/target_ec2_instances/outputs.tf
@@ -7,8 +7,5 @@ output "cluster_name" {
output "hosts" {
description = "The ec2 instance target hosts"
- value = { for idx in range(var.instance_count) : idx => {
- public_ip = aws_instance.targets[idx].public_ip
- private_ip = aws_instance.targets[idx].private_ip
- } }
+ value = local.hosts
}
diff --git a/enos/modules/target_ec2_instances/variables.tf b/enos/modules/target_ec2_instances/variables.tf
index dc4bfc6c27..9718f2fdae 100644
--- a/enos/modules/target_ec2_instances/variables.tf
+++ b/enos/modules/target_ec2_instances/variables.tf
@@ -24,6 +24,21 @@ variable "common_tags" {
default = { "Project" : "vault-ci" }
}
+variable "ports_ingress" {
+ description = "Ports mappings to allow for ingress"
+ type = list(object({
+ description = string
+ port = number
+ protocol = string
+ }))
+}
+
+variable "disable_selinux" {
+ description = "Optionally disable SELinux for certain distros/versions"
+ type = bool
+ default = true
+}
+
variable "instance_count" {
description = "The number of target instances to create"
type = number
diff --git a/enos/modules/target_ec2_shim/main.tf b/enos/modules/target_ec2_shim/main.tf
index 429c49ab02..c755668865 100644
--- a/enos/modules/target_ec2_shim/main.tf
+++ b/enos/modules/target_ec2_shim/main.tf
@@ -16,6 +16,7 @@ variable "ami_id" { default = null }
variable "cluster_name" { default = null }
variable "cluster_tag_key" { default = null }
variable "common_tags" { default = null }
+variable "disable_selinux" { default = true }
variable "instance_count" { default = 3 }
variable "instance_cpu_max" { default = null }
variable "instance_cpu_min" { default = null }
@@ -23,6 +24,7 @@ variable "instance_mem_max" { default = null }
variable "instance_mem_min" { default = null }
variable "instance_types" { default = null }
variable "max_price" { default = null }
+variable "ports_ingress" { default = null }
variable "project_name" { default = null }
variable "seal_key_names" { default = null }
variable "ssh_allow_ips" { default = null }
@@ -45,5 +47,6 @@ output "hosts" {
value = { for idx in range(var.instance_count) : idx => {
public_ip = "null-public-${idx}"
private_ip = "null-private-${idx}"
+ ipv6 = "null-ipv6-${idx}"
} }
}
diff --git a/enos/modules/target_ec2_spot_fleet/main.tf b/enos/modules/target_ec2_spot_fleet/main.tf
index 37f8e9ffb4..4a762746e5 100644
--- a/enos/modules/target_ec2_spot_fleet/main.tf
+++ b/enos/modules/target_ec2_spot_fleet/main.tf
@@ -454,3 +454,13 @@ data "aws_instance" "targets" {
instance_id = data.aws_instances.targets.ids[each.key]
}
+
+module "disable_selinux" {
+ source = "../disable_selinux"
+ count = var.disable_selinux == true ? 1 : 0
+
+ hosts = { for idx in range(var.instance_count) : idx => {
+ public_ip = aws_instance.targets[idx].public_ip
+ private_ip = aws_instance.targets[idx].private_ip
+ } }
+}
diff --git a/enos/modules/target_ec2_spot_fleet/outputs.tf b/enos/modules/target_ec2_spot_fleet/outputs.tf
index 1672a24179..505db0e4eb 100644
--- a/enos/modules/target_ec2_spot_fleet/outputs.tf
+++ b/enos/modules/target_ec2_spot_fleet/outputs.tf
@@ -10,5 +10,6 @@ output "hosts" {
value = { for idx in range(var.instance_count) : idx => {
public_ip = data.aws_instance.targets[idx].public_ip
private_ip = data.aws_instance.targets[idx].private_ip
+ ipv6 = try(data.aws_instance.targets[idx].ipv6_addresses[0], null)
} }
}
diff --git a/enos/modules/target_ec2_spot_fleet/variables.tf b/enos/modules/target_ec2_spot_fleet/variables.tf
index c2f5bb6092..af6c0dc04f 100644
--- a/enos/modules/target_ec2_spot_fleet/variables.tf
+++ b/enos/modules/target_ec2_spot_fleet/variables.tf
@@ -26,6 +26,12 @@ variable "common_tags" {
}
}
+variable "disable_selinux" {
+ description = "Optionally disable SELinux for certain distros/versions"
+ type = bool
+ default = true
+}
+
variable "instance_mem_min" {
description = "The minimum amount of memory in mebibytes for each instance in the fleet. (1 MiB = 1024 bytes)"
type = number
diff --git a/enos/modules/vault_agent/main.tf b/enos/modules/vault_agent/main.tf
index c43501f234..e5d19667c2 100644
--- a/enos/modules/vault_agent/main.tf
+++ b/enos/modules/vault_agent/main.tf
@@ -12,6 +12,27 @@ terraform {
}
}
+variable "ip_version" {
+ type = number
+ default = 4
+ description = "The IP version to use for the Vault TCP listeners"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_agent_port" {
+ type = number
+ description = "The listener port number for the Vault Agent"
+}
+
variable "vault_agent_template_destination" {
type = string
description = "The destination of the template rendered by Agent"
@@ -27,35 +48,28 @@ variable "vault_root_token" {
description = "The Vault root token"
}
-variable "vault_instances" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
description = "The Vault cluster instances that were created"
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
}
locals {
- vault_instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
+ agent_listen_addr = "${var.ip_version == 4 ? "127.0.0.1" : "[::1]"}:${var.vault_agent_port}"
}
resource "enos_remote_exec" "set_up_approle_auth_and_agent" {
environment = {
+ AGENT_LISTEN_ADDR = local.agent_listen_addr,
+ VAULT_ADDR = var.vault_addr,
VAULT_INSTALL_DIR = var.vault_install_dir,
VAULT_TOKEN = var.vault_root_token,
VAULT_AGENT_TEMPLATE_DESTINATION = var.vault_agent_template_destination,
@@ -66,7 +80,12 @@ resource "enos_remote_exec" "set_up_approle_auth_and_agent" {
transport = {
ssh = {
- host = local.vault_instances[0].public_ip
+ host = var.hosts[0].public_ip
}
}
}
+
+output "vault_agent_listen_addr" {
+ description = "The vault agent listen address"
+ value = local.agent_listen_addr
+}
diff --git a/enos/modules/vault_agent/scripts/set-up-approle-and-agent.sh b/enos/modules/vault_agent/scripts/set-up-approle-and-agent.sh
index e939ea1d7c..6af219ab1b 100644
--- a/enos/modules/vault_agent/scripts/set-up-approle-and-agent.sh
+++ b/enos/modules/vault_agent/scripts/set-up-approle-and-agent.sh
@@ -2,21 +2,23 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
-
set -e
-binpath=${VAULT_INSTALL_DIR}/vault
-
fail() {
echo "$1" 1>&2
return 1
}
-test -x "$binpath" || fail "unable to locate vault binary at $binpath"
-
-export VAULT_ADDR='http://127.0.0.1:8200'
+[[ -z "$AGENT_LISTEN_ADDR" ]] && fail "AGENT_LISTEN_ADDR env variable has not been set"
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
+[[ -z "$VAULT_AGENT_TEMPLATE_CONTENTS" ]] && fail "VAULT_AGENT_TEMPLATE_CONTENTS env variable has not been set"
+[[ -z "$VAULT_AGENT_TEMPLATE_DESTINATION" ]] && fail "VAULT_AGENT_TEMPLATE_DESTINATION env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
+binpath=${VAULT_INSTALL_DIR}/vault
+test -x "$binpath" || fail "unable to locate vault binary at $binpath"
+
# If approle was already enabled, disable it as we're about to re-enable it (the || true is so we don't fail if it doesn't already exist)
$binpath auth disable approle || true
@@ -43,7 +45,7 @@ cat > /tmp/vault-agent.hcl <<- EOM
pid_file = "/tmp/pidfile"
vault {
- address = "http://127.0.0.1:8200"
+ address = "${VAULT_ADDR}"
tls_skip_verify = true
retry {
num_retries = 10
@@ -56,7 +58,7 @@ cache {
}
listener "tcp" {
- address = "127.0.0.1:8100"
+ address = "${AGENT_LISTEN_ADDR}"
tls_disable = true
}
@@ -92,4 +94,6 @@ pkill -F /tmp/pidfile || true
rm "${VAULT_AGENT_TEMPLATE_DESTINATION}" || true
# Run agent (it will kill itself when it finishes rendering the template)
-$binpath agent -config=/tmp/vault-agent.hcl > /tmp/agent-logs.txt 2>&1
+if ! $binpath agent -config=/tmp/vault-agent.hcl > /tmp/agent-logs.txt 2>&1; then
+ fail "failed to run vault agent: $(cat /tmp/agent-logs.txt)"
+fi
diff --git a/enos/modules/vault_cluster/main.tf b/enos/modules/vault_cluster/main.tf
index e0ee864b91..1fbe31547a 100644
--- a/enos/modules/vault_cluster/main.tf
+++ b/enos/modules/vault_cluster/main.tf
@@ -21,11 +21,11 @@ locals {
consul_bin_path = "${var.consul_install_dir}/consul"
enable_audit_devices = var.enable_audit_devices && var.initialize_cluster
// In order to get Terraform to plan we have to use collections with keys
- // that are known at plan time. In order for our module to work our var.target_hosts
+ // that are known at plan time. In order for our module to work our var.hosts
// must be a map with known keys at plan time. Here we're creating locals
// that keep track of index values that point to our target hosts.
followers = toset(slice(local.instances, 1, length(local.instances)))
- instances = [for idx in range(length(var.target_hosts)) : tostring(idx)]
+ instances = [for idx in range(length(var.hosts)) : tostring(idx)]
key_shares = {
"awskms" = null
"shamir" = 5
@@ -37,6 +37,13 @@ locals {
"pkcs11" = null
}
leader = toset(slice(local.instances, 0, 1))
+ netcat_command = {
+ amzn = "nc"
+ opensuse-leap = "netcat"
+ rhel = "nc"
+ sles = "nc"
+ ubuntu = "netcat"
+ }
recovery_shares = {
"awskms" = 5
"shamir" = null
@@ -50,9 +57,19 @@ locals {
vault_service_user = "vault"
}
+resource "enos_host_info" "hosts" {
+ for_each = var.hosts
+
+ transport = {
+ ssh = {
+ host = each.value.public_ip
+ }
+ }
+}
+
resource "enos_bundle_install" "consul" {
for_each = {
- for idx, host in var.target_hosts : idx => var.target_hosts[idx]
+ for idx, host in var.hosts : idx => var.hosts[idx]
if var.storage_backend == "consul"
}
@@ -66,8 +83,21 @@ resource "enos_bundle_install" "consul" {
}
}
+# We run install_packages before we install Vault because for some combinations of
+# certain Linux distros and artifact types (e.g. SLES and RPM packages), there may
+# be packages that are required to perform Vault installation (e.g. openssl).
+module "install_packages" {
+ source = "../install_packages"
+
+ hosts = var.hosts
+ packages = var.packages
+}
+
resource "enos_bundle_install" "vault" {
- for_each = var.target_hosts
+ for_each = var.hosts
+ depends_on = [
+ module.install_packages, // Don't race for the package manager locks with install_packages
+ ]
destination = var.install_dir
release = var.release == null ? var.release : merge({ product = "vault" }, var.release)
@@ -81,22 +111,17 @@ resource "enos_bundle_install" "vault" {
}
}
-module "install_packages" {
- source = "../install_packages"
- depends_on = [
- enos_bundle_install.vault, // Don't race for the package manager locks with vault install
- ]
-
- hosts = var.target_hosts
- packages = var.packages
-}
-
resource "enos_consul_start" "consul" {
for_each = enos_bundle_install.consul
bin_path = local.consul_bin_path
data_dir = var.consul_data_dir
config = {
+ # GetPrivateInterfaces is a go-sockaddr template that helps Consul get the correct
+ # addr in all of our default cases. This is required in the case of Amazon Linux,
+ # because amzn has a default docker listener that will make Consul try to use the
+ # incorrect addr.
+ bind_addr = "{{ GetPrivateInterfaces | include \"type\" \"IP\" | sort \"default\" | limit 1 | attr \"address\"}}"
data_dir = var.consul_data_dir
datacenter = "dc1"
retry_join = ["provider=aws tag_key=${var.backend_cluster_tag_key} tag_value=${var.backend_cluster_name}"]
@@ -112,7 +137,7 @@ resource "enos_consul_start" "consul" {
transport = {
ssh = {
- host = var.target_hosts[each.key].public_ip
+ host = var.hosts[each.key].public_ip
}
}
}
@@ -122,14 +147,21 @@ module "start_vault" {
depends_on = [
enos_consul_start.consul,
+ module.install_packages,
enos_bundle_install.vault,
]
cluster_name = var.cluster_name
+ cluster_port = var.cluster_port
+ cluster_tag_key = var.cluster_tag_key
config_dir = var.config_dir
config_mode = var.config_mode
+ external_storage_port = var.external_storage_port
+ hosts = var.hosts
install_dir = var.install_dir
+ ip_version = var.ip_version
license = var.license
+ listener_port = var.listener_port
log_level = var.log_level
manage_service = var.manage_service
seal_attributes = var.seal_attributes
@@ -140,7 +172,6 @@ module "start_vault" {
storage_backend = var.storage_backend
storage_backend_attrs = var.storage_backend_addl_config
storage_node_prefix = var.storage_node_prefix
- target_hosts = var.target_hosts
}
resource "enos_vault_init" "leader" {
@@ -163,7 +194,7 @@ resource "enos_vault_init" "leader" {
transport = {
ssh = {
- host = var.target_hosts[each.value].public_ip
+ host = var.hosts[each.value].public_ip
}
}
}
@@ -182,7 +213,7 @@ resource "enos_vault_unseal" "leader" {
transport = {
ssh = {
- host = var.target_hosts[tolist(local.leader)[0]].public_ip
+ host = var.hosts[tolist(local.leader)[0]].public_ip
}
}
}
@@ -206,7 +237,7 @@ resource "enos_vault_unseal" "followers" {
transport = {
ssh = {
- host = var.target_hosts[each.value].public_ip
+ host = var.hosts[each.value].public_ip
}
}
}
@@ -220,12 +251,12 @@ resource "enos_vault_unseal" "maybe_force_unseal" {
module.start_vault.followers,
]
for_each = {
- for idx, host in var.target_hosts : idx => host
+ for idx, host in var.hosts : idx => host
if var.force_unseal && !var.initialize_cluster
}
bin_path = local.bin_path
- vault_addr = "http://localhost:8200"
+ vault_addr = module.start_vault.api_addr_localhost
seal_type = var.seal_type
unseal_keys = coalesce(
var.shamir_unseal_keys,
@@ -246,10 +277,10 @@ resource "enos_remote_exec" "configure_login_shell_profile" {
enos_vault_init.leader,
enos_vault_unseal.leader,
]
- for_each = var.target_hosts
+ for_each = var.hosts
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = module.start_vault.api_addr_localhost
VAULT_TOKEN = var.root_token != null ? var.root_token : try(enos_vault_init.leader[0].root_token, "_")
VAULT_INSTALL_DIR = var.install_dir
}
@@ -263,6 +294,37 @@ resource "enos_remote_exec" "configure_login_shell_profile" {
}
}
+# Add a motd to assist people that might be logging in.
+resource "enos_file" "motd" {
+ depends_on = [
+ enos_remote_exec.configure_login_shell_profile
+ ]
+ for_each = var.hosts
+
+ destination = "/etc/motd"
+ content = <> /tmp/vault-socket.log 2>&1 < /dev/null &
+ case $IP_VERSION in
+ 4)
+ nohup nc -kl "$SOCKET_PORT" >> /tmp/vault-socket.log 2>&1 < /dev/null &
+ ;;
+ 6)
+ nohup nc -6 -kl "$SOCKET_PORT" >> /tmp/vault-socket.log 2>&1 < /dev/null &
+ ;;
+ *)
+ fail "unknown IP_VERSION: $IP_VERSION"
+ ;;
+ esac
}
read_log() {
diff --git a/enos/modules/vault_cluster/variables.tf b/enos/modules/vault_cluster/variables.tf
index b29ccfc80a..1e4de12e53 100644
--- a/enos/modules/vault_cluster/variables.tf
+++ b/enos/modules/vault_cluster/variables.tf
@@ -30,6 +30,18 @@ variable "cluster_name" {
default = null
}
+variable "cluster_port" {
+ type = number
+ description = "The cluster port for Vault to listen on"
+ default = 8201
+}
+
+variable "cluster_tag_key" {
+ type = string
+ description = "The Vault cluster tag key"
+ default = "retry_join"
+}
+
variable "config_dir" {
type = string
description = "The directory to use for Vault configuration"
@@ -100,18 +112,39 @@ variable "consul_release" {
}
}
+variable "distro_version" {
+ type = string
+ description = "The Linux distro version"
+ default = null
+}
+
variable "enable_audit_devices" {
description = "If true every audit device will be enabled"
type = bool
default = true
}
+variable "external_storage_port" {
+ type = number
+ description = "The port to connect to when using external storage"
+ default = 8500
+}
+
variable "force_unseal" {
type = bool
description = "Always unseal the Vault cluster even if we're not initializing it"
default = false
}
+variable "hosts" {
+ description = "The target machines host addresses to use for the Vault cluster"
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+}
+
variable "initialize_cluster" {
type = bool
description = "Initialize the Vault cluster"
@@ -120,10 +153,20 @@ variable "initialize_cluster" {
variable "install_dir" {
type = string
- description = "The directory where the vault binary will be installed"
+ description = "The directory where the Vault binary will be installed"
default = "/opt/vault/bin"
}
+variable "ip_version" {
+ type = number
+ description = "The IP version to use for the Vault TCP listeners"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
variable "license" {
type = string
sensitive = true
@@ -131,6 +174,12 @@ variable "license" {
default = null
}
+variable "listener_port" {
+ type = number
+ description = "The port for Vault to listen on"
+ default = 8200
+}
+
variable "local_artifact_path" {
type = string
description = "The path to a locally built vault artifact to install. It can be a zip archive, RPM, or Debian package"
@@ -171,7 +220,7 @@ variable "release" {
variable "root_token" {
type = string
- description = "The Vault root token that we can use to intialize and configure the cluster"
+ description = "The Vault root token that we can use to initialize and configure the cluster"
default = null
}
@@ -240,11 +289,3 @@ variable "storage_node_prefix" {
description = "A prefix to use for each node in the Vault storage configuration"
default = "node"
}
-
-variable "target_hosts" {
- description = "The target machines host addresses to use for the Vault cluster"
- type = map(object({
- private_ip = string
- public_ip = string
- }))
-}
diff --git a/enos/modules/vault_get_cluster_ips/main.tf b/enos/modules/vault_get_cluster_ips/main.tf
index 984d00cbea..ef3101896f 100644
--- a/enos/modules/vault_get_cluster_ips/main.tf
+++ b/enos/modules/vault_get_cluster_ips/main.tf
@@ -1,6 +1,13 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
+/*
+
+Given our expected hosts, determine which is currently the leader and verify that all expected
+nodes are either the leader or a follower.
+
+*/
+
terraform {
required_providers {
enos = {
@@ -9,6 +16,30 @@ terraform {
}
}
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The Vault cluster hosts that are expected to be in the cluster"
+}
+
+variable "ip_version" {
+ type = number
+ description = "The IP version used for the Vault TCP listener"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
@@ -19,73 +50,100 @@ variable "vault_root_token" {
description = "The vault root token"
}
-variable "vault_instance_count" {
- type = number
- description = "The number of instances in the vault cluster"
-}
-
-variable "vault_hosts" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster hosts. These are required to map private ip addresses to public addresses."
-}
-
locals {
- follower_hosts_list = [for idx in range(var.vault_instance_count - 1) : {
- private_ip = local.follower_private_ips[idx]
- public_ip = local.follower_public_ips[idx]
- }
+ follower_hosts_list = [
+ for idx in range(length(var.hosts)) : var.hosts[idx] if var.ip_version == 6 ?
+ contains(tolist(local.follower_ipv6s), var.hosts[idx].ipv6) :
+ contains(tolist(local.follower_private_ips), var.hosts[idx].private_ip)
]
follower_hosts = {
- for idx in range(var.vault_instance_count - 1) : idx => try(local.follower_hosts_list[idx], null)
+ for idx in range(local.host_count - 1) : idx => try(local.follower_hosts_list[idx], null)
}
- follower_private_ips = jsondecode(enos_remote_exec.get_follower_private_ips.stdout)
- follower_public_ips = [for idx in range(var.vault_instance_count) : var.vault_hosts[idx].public_ip if contains(
- local.follower_private_ips, var.vault_hosts[idx].private_ip)
+ follower_ipv6s = jsondecode(enos_remote_exec.follower_ipv6s.stdout)
+ follower_private_ips = jsondecode(enos_remote_exec.follower_private_ipv4s.stdout)
+ follower_public_ips = [for host in local.follower_hosts : host.public_ip]
+ host_count = length(var.hosts)
+ ipv6s = [for k, v in values(tomap(var.hosts)) : tostring(v["ipv6"])]
+ leader_host_list = [
+ for idx in range(length(var.hosts)) : var.hosts[idx] if var.ip_version == 6 ?
+ var.hosts[idx].ipv6 == local.leader_ipv6 :
+ var.hosts[idx].private_ip == local.leader_private_ip
]
- leader_host = {
- private_ip = local.leader_private_ip
- public_ip = local.leader_public_ip
- }
- leader_private_ip = trimspace(enos_remote_exec.get_leader_private_ip.stdout)
- leader_public_ip = element([
- for idx in range(var.vault_instance_count) : var.vault_hosts[idx].public_ip if var.vault_hosts[idx].private_ip == local.leader_private_ip
- ], 0)
- private_ips = [for k, v in values(tomap(var.vault_hosts)) : tostring(v["private_ip"])]
+ leader_host = try(local.leader_host_list[0], null)
+ leader_ipv6 = trimspace(enos_remote_exec.leader_ipv6.stdout)
+ leader_private_ip = trimspace(enos_remote_exec.leader_private_ipv4.stdout)
+ leader_public_ip = try(local.leader_host.public_ip, null)
+ private_ips = [for k, v in values(tomap(var.hosts)) : tostring(v["private_ip"])]
}
-resource "enos_remote_exec" "get_leader_private_ip" {
+resource "enos_remote_exec" "leader_private_ipv4" {
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
- VAULT_TOKEN = var.vault_root_token
+ IP_VERSION = var.ip_version
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
+ VAULT_TOKEN = var.vault_root_token
}
- scripts = [abspath("${path.module}/scripts/get-leader-private-ip.sh")]
+ scripts = [abspath("${path.module}/scripts/get-leader-ipv4.sh")]
transport = {
ssh = {
- host = var.vault_hosts[0].public_ip
+ host = var.hosts[0].public_ip
}
}
}
-resource "enos_remote_exec" "get_follower_private_ips" {
+resource "enos_remote_exec" "leader_ipv6" {
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
- VAULT_TOKEN = var.vault_root_token
- VAULT_LEADER_PRIVATE_IP = local.leader_private_ip
- VAULT_INSTANCE_PRIVATE_IPS = jsonencode(local.private_ips)
- VAULT_INSTALL_DIR = var.vault_install_dir
+ IP_VERSION = var.ip_version
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
+ VAULT_TOKEN = var.vault_root_token
}
- scripts = [abspath("${path.module}/scripts/get-follower-private-ips.sh")]
+ scripts = [abspath("${path.module}/scripts/get-leader-ipv6.sh")]
transport = {
ssh = {
- host = var.vault_hosts[0].public_ip
+ host = var.hosts[0].public_ip
+ }
+ }
+}
+
+resource "enos_remote_exec" "follower_private_ipv4s" {
+ environment = {
+ IP_VERSION = var.ip_version
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
+ VAULT_LEADER_PRIVATE_IP = local.leader_private_ip
+ VAULT_PRIVATE_IPS = jsonencode(local.private_ips)
+ VAULT_TOKEN = var.vault_root_token
+ }
+
+ scripts = [abspath("${path.module}/scripts/get-follower-ipv4s.sh")]
+
+ transport = {
+ ssh = {
+ host = var.hosts[0].public_ip
+ }
+ }
+}
+
+resource "enos_remote_exec" "follower_ipv6s" {
+ environment = {
+ IP_VERSION = var.ip_version
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
+ VAULT_IPV6S = jsonencode(local.ipv6s)
+ VAULT_LEADER_IPV6 = local.leader_ipv6
+ VAULT_TOKEN = var.vault_root_token
+ }
+
+ scripts = [abspath("${path.module}/scripts/get-follower-ipv6s.sh")]
+
+ transport = {
+ ssh = {
+ host = var.hosts[0].public_ip
}
}
}
@@ -94,6 +152,10 @@ output "follower_hosts" {
value = local.follower_hosts
}
+output "follower_ipv6s" {
+ value = local.follower_ipv6s
+}
+
output "follower_private_ips" {
value = local.follower_private_ips
}
@@ -106,6 +168,14 @@ output "leader_host" {
value = local.leader_host
}
+output "leader_hosts" {
+ value = { 0 : local.leader_host }
+}
+
+output "leader_ipv6" {
+ value = local.leader_ipv6
+}
+
output "leader_private_ip" {
value = local.leader_private_ip
}
diff --git a/enos/modules/vault_get_cluster_ips/scripts/get-follower-ipv4s.sh b/enos/modules/vault_get_cluster_ips/scripts/get-follower-ipv4s.sh
new file mode 100644
index 0000000000..7264f60745
--- /dev/null
+++ b/enos/modules/vault_get_cluster_ips/scripts/get-follower-ipv4s.sh
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+
+set -e
+
+function fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+[[ -z "$IP_VERSION" ]] && fail "IP_VERSION env variable has not been set"
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
+[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
+
+binpath=${VAULT_INSTALL_DIR}/vault
+test -x "$binpath" || fail "Unable to locate vault binary at $binpath"
+
+getFollowerPrivateIPsFromOperatorMembers() {
+ if members=$($binpath operator members -format json); then
+ if followers=$(echo "$members" | jq -e --argjson expected "$VAULT_PRIVATE_IPS" -c '.Nodes | map(select(any(.; .active_node==false)) | .api_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")) as $followers | $expected - ($expected - $followers)'); then
+ # Make sure that we got all the followers
+ if jq -e --argjson expected "$VAULT_PRIVATE_IPS" --argjson followers "$followers" -ne '$expected | length as $el | $followers | length as $fl | $fl == $el-1' > /dev/null; then
+ echo "$followers"
+ return 0
+ fi
+ fi
+ fi
+
+ return 1
+}
+
+removeIP() {
+ local needle
+ local haystack
+ needle=$1
+ haystack=$2
+ if remain=$(jq -e --arg ip "$needle" -c '. | map(select(.!=$ip))' <<< "$haystack"); then
+ if [[ -n "$remain" ]]; then
+ echo "$remain"
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+count=0
+retries=10
+while :; do
+ case $IP_VERSION in
+ 4)
+ [[ -z "$VAULT_PRIVATE_IPS" ]] && fail "VAULT_PRIVATE_IPS env variable has not been set"
+ [[ -z "$VAULT_LEADER_PRIVATE_IP" ]] && fail "VAULT_LEADER_PRIVATE_IP env variable has not been set"
+
+ # Vault >= 1.10.x has the operator members. If we have that then we'll use it.
+ if $binpath operator -h 2>&1 | grep members &> /dev/null; then
+ if followers=$(getFollowerPrivateIPsFromOperatorMembers); then
+ echo "$followers"
+ exit 0
+ fi
+ else
+ removeIP "$VAULT_LEADER_PRIVATE_IP" "$VAULT_PRIVATE_IPS"
+
+ return $?
+ fi
+ ;;
+ 6)
+ echo '[]'
+ exit 0
+ ;;
+ *)
+ fail "unknown IP_VERSION: $IP_VERSION"
+ ;;
+ esac
+
+ wait=$((2 ** count))
+ count=$((count + 1))
+ if [ "$count" -lt "$retries" ]; then
+ sleep "$wait"
+ else
+ fail "Timed out trying to obtain the cluster followers"
+ fi
+done
diff --git a/enos/modules/vault_get_cluster_ips/scripts/get-follower-ipv6s.sh b/enos/modules/vault_get_cluster_ips/scripts/get-follower-ipv6s.sh
new file mode 100644
index 0000000000..a919061935
--- /dev/null
+++ b/enos/modules/vault_get_cluster_ips/scripts/get-follower-ipv6s.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+
+set -e
+
+function fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+[[ -z "$IP_VERSION" ]] && fail "IP_VERSION env variable has not been set"
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
+[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
+
+echo "$VAULT_IPV6S" > /tmp/vaultipv6s
+
+binpath=${VAULT_INSTALL_DIR}/vault
+test -x "$binpath" || fail "Unable to locate vault binary at $binpath"
+
+getFollowerIPV6sFromOperatorMembers() {
+ if members=$($binpath operator members -format json); then
+ if followers=$(echo "$members" | jq -e --argjson expected "$VAULT_IPV6S" -c '.Nodes | map(select(any(.; .active_node==false)) | .api_address | scan("\\[(.+)\\]") | .[0]) as $followers | $expected - ($expected - $followers)'); then
+ # Make sure that we got all the followers
+ if jq -e --argjson expected "$VAULT_IPV6S" --argjson followers "$followers" -ne '$expected | length as $el | $followers | length as $fl | $fl == $el-1' > /dev/null; then
+ echo "$followers"
+ return 0
+ fi
+ fi
+ fi
+
+ return 1
+}
+
+removeIP() {
+ local needle
+ local haystack
+ needle=$1
+ haystack=$2
+ if remain=$(jq -e --arg ip "$needle" -c '. | map(select(.!=$ip))' <<< "$haystack"); then
+ if [[ -n "$remain" ]]; then
+ echo "$remain"
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+count=0
+retries=10
+while :; do
+ case $IP_VERSION in
+ 4)
+ echo "[]"
+ exit 0
+ ;;
+ 6)
+ [[ -z "$VAULT_IPV6S" ]] && fail "VAULT_IPV6S env variable has not been set"
+ [[ -z "$VAULT_LEADER_IPV6" ]] && fail "VAULT_LEADER_IPV6 env variable has not been set"
+
+ # Vault >= 1.10.x has the operator members. If we have that then we'll use it.
+ if $binpath operator -h 2>&1 | grep members &> /dev/null; then
+ if followers=$(getFollowerIPV6sFromOperatorMembers); then
+ echo "$followers"
+ exit 0
+ fi
+ else
+ [[ -z "$VAULT_LEADER_IPV6" ]] && fail "VAULT_LEADER_IPV6 env variable has not been set"
+ removeIP "$VAULT_LEADER_IPV6" "$VAULT_IPV6S"
+ exit $?
+ fi
+ ;;
+ *)
+ fail "unknown IP_VERSION: $IP_VERSION"
+ ;;
+ esac
+
+ wait=$((2 ** count))
+ count=$((count + 1))
+ if [ "$count" -lt "$retries" ]; then
+ sleep "$wait"
+ else
+ fail "Timed out trying to obtain the cluster followers"
+ fi
+done
diff --git a/enos/modules/vault_get_cluster_ips/scripts/get-follower-private-ips.sh b/enos/modules/vault_get_cluster_ips/scripts/get-follower-private-ips.sh
deleted file mode 100644
index 084a11a35f..0000000000
--- a/enos/modules/vault_get_cluster_ips/scripts/get-follower-private-ips.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
-
-
-set -e
-
-function fail() {
- echo "$1" 1>&2
- exit 1
-}
-
-[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
-[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
-[[ -z "$VAULT_INSTANCE_PRIVATE_IPS" ]] && fail "VAULT_INSTANCE_PRIVATE_IPS env variable has not been set"
-[[ -z "$VAULT_LEADER_PRIVATE_IP" ]] && fail "VAULT_LEADER_PRIVATE_IP env variable has not been set"
-[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
-
-binpath=${VAULT_INSTALL_DIR}/vault
-test -x "$binpath" || fail "Unable to locate vault binary at $binpath"
-
-count=0
-retries=10
-while :; do
- # Vault >= 1.10.x has the operator members. If we have that then we'll use it.
- if $binpath operator -h 2>&1 | grep members &> /dev/null; then
- # Get the folllowers that are part of our private ips.
- if members=$($binpath operator members -format json); then
- if followers=$(echo "$members" | jq --argjson expected "$VAULT_INSTANCE_PRIVATE_IPS" -c '.Nodes | map(select(any(.; .active_node==false)) | .api_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")) as $followers | $expected - ($expected - $followers)'); then
- # Make sure that we got all the followers
- if jq --argjson expected "$VAULT_INSTANCE_PRIVATE_IPS" --argjson followers "$followers" -ne '$expected | length as $el | $followers | length as $fl | $fl == $el-1' > /dev/null; then
- echo "$followers"
- exit 0
- fi
- fi
- fi
- else
- # We're using an old version of vault so we'll just return ips that don't match the leader.
- # Get the public ip addresses of the followers
- if followers=$(jq --arg ip "$VAULT_LEADER_PRIVATE_IP" -c '. | map(select(.!=$ip))' <<< "$VAULT_INSTANCE_PRIVATE_IPS"); then
- if [[ -n "$followers" ]]; then
- echo "$followers"
- exit 0
- fi
- fi
- fi
-
- wait=$((2 ** count))
- count=$((count + 1))
- if [ "$count" -lt "$retries" ]; then
- sleep "$wait"
- else
- fail "Timed out trying to obtain the cluster followers"
- fi
-done
diff --git a/enos/modules/vault_get_cluster_ips/scripts/get-leader-private-ip.sh b/enos/modules/vault_get_cluster_ips/scripts/get-leader-ipv4.sh
similarity index 75%
rename from enos/modules/vault_get_cluster_ips/scripts/get-leader-private-ip.sh
rename to enos/modules/vault_get_cluster_ips/scripts/get-leader-ipv4.sh
index ffea30c462..65853b7e0e 100644
--- a/enos/modules/vault_get_cluster_ips/scripts/get-leader-private-ip.sh
+++ b/enos/modules/vault_get_cluster_ips/scripts/get-leader-ipv4.sh
@@ -10,6 +10,7 @@ function fail() {
exit 1
}
+[[ -z "$IP_VERSION" ]] && fail "IP_VERSION env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
@@ -17,14 +18,12 @@ function fail() {
binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "Unable to locate vault binary at $binpath"
-count=0
-retries=5
-while :; do
+findLeaderPrivateIP() {
# Find the leader private IP address
if ip=$($binpath read sys/leader -format=json | jq -r '.data.leader_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")'); then
if [[ -n "$ip" ]]; then
echo "$ip"
- exit 0
+ return 0
fi
fi
@@ -32,10 +31,32 @@ while :; do
if ip=$($binpath status -format json | jq -r '.leader_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")'); then
if [[ -n "$ip" ]]; then
echo "$ip"
- exit 0
+ return 0
fi
fi
+ return 1
+}
+
+count=0
+retries=5
+while :; do
+ case $IP_VERSION in
+ 4)
+ # Find the leader private IP address
+ if ip=$(findLeaderPrivateIP); then
+ echo "$ip"
+ exit 0
+ fi
+ ;;
+ 6)
+ exit 0
+ ;;
+ *)
+ fail "unknown IP_VERSION: $IP_VERSION"
+ ;;
+ esac
+
wait=$((2 ** count))
count=$((count + 1))
if [ "$count" -lt "$retries" ]; then
diff --git a/enos/modules/vault_get_cluster_ips/scripts/get-leader-ipv6.sh b/enos/modules/vault_get_cluster_ips/scripts/get-leader-ipv6.sh
new file mode 100644
index 0000000000..b8cd859596
--- /dev/null
+++ b/enos/modules/vault_get_cluster_ips/scripts/get-leader-ipv6.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+
+set -e
+
+function fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+[[ -z "$IP_VERSION" ]] && fail "IP_VERSION env variable has not been set"
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
+[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
+
+binpath=${VAULT_INSTALL_DIR}/vault
+test -x "$binpath" || fail "Unable to locate vault binary at $binpath"
+
+findLeaderIPV6() {
+ # Find the leader private IP address
+ if ip=$($binpath read sys/leader -format=json | jq -r '.data.leader_address | scan("\\[(.+)\\]") | .[0]'); then
+ if [[ -n "$ip" ]]; then
+ echo "$ip"
+ return 0
+ fi
+ fi
+
+ # Some older versions of vault don't support reading sys/leader. Try falling back to the cli status.
+ if ip=$($binpath status -format json | jq -r '.leader_address | scan("\\[(.+)\\]") | .[0]'); then
+ if [[ -n "$ip" ]]; then
+ echo "$ip"
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+count=0
+retries=5
+while :; do
+ # Find the leader private IP address
+ case $IP_VERSION in
+ 4)
+ exit 0
+ ;;
+ 6)
+ if ip=$(findLeaderIPV6); then
+ echo "$ip"
+ exit 0
+ fi
+ ;;
+ *)
+ fail "unknown IP_VERSION: $IP_VERSION"
+ ;;
+ esac
+
+ wait=$((2 ** count))
+ count=$((count + 1))
+ if [ "$count" -lt "$retries" ]; then
+ sleep "$wait"
+ else
+ fail "Timed out trying to obtain the cluster leader"
+ fi
+done
diff --git a/enos/modules/vault_proxy/main.tf b/enos/modules/vault_proxy/main.tf
index d71232294a..b69b052c4b 100644
--- a/enos/modules/vault_proxy/main.tf
+++ b/enos/modules/vault_proxy/main.tf
@@ -12,22 +12,28 @@ terraform {
}
}
-variable "vault_root_token" {
- type = string
- description = "The Vault root token"
-}
-
-variable "vault_instances" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
description = "The Vault cluster instances that were created"
}
-variable "vault_instance_count" {
+variable "ip_version" {
type = number
- description = "How many vault instances are in the cluster"
+ description = "The IP version to use for the Vault TCP listeners"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
}
variable "vault_install_dir" {
@@ -41,29 +47,34 @@ variable "vault_proxy_pidfile" {
default = "/tmp/pidfile"
}
+variable "vault_proxy_port" {
+ type = number
+ description = "The Vault Proxy listener port"
+}
+
+variable "vault_root_token" {
+ type = string
+ description = "The Vault root token"
+}
+
locals {
- vault_instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
- vault_proxy_address = "127.0.0.1:8100"
+ vault_proxy_address = "${var.ip_version == 4 ? "127.0.0.1" : "[::1]"}:${var.vault_proxy_port}"
}
resource "enos_remote_exec" "set_up_approle_auth_and_proxy" {
environment = {
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
- VAULT_TOKEN = var.vault_root_token
- VAULT_PROXY_PIDFILE = var.vault_proxy_pidfile
VAULT_PROXY_ADDRESS = local.vault_proxy_address
+ VAULT_PROXY_PIDFILE = var.vault_proxy_pidfile
+ VAULT_TOKEN = var.vault_root_token
}
scripts = [abspath("${path.module}/scripts/set-up-approle-and-proxy.sh")]
transport = {
ssh = {
- host = local.vault_instances[0].public_ip
+ host = var.hosts[0].public_ip
}
}
}
@@ -79,7 +90,7 @@ resource "enos_remote_exec" "use_proxy" {
transport = {
ssh = {
- host = local.vault_instances[0].public_ip
+ host = var.hosts[0].public_ip
}
}
diff --git a/enos/modules/vault_proxy/scripts/set-up-approle-and-proxy.sh b/enos/modules/vault_proxy/scripts/set-up-approle-and-proxy.sh
index 556cb82248..a396b8d5e8 100644
--- a/enos/modules/vault_proxy/scripts/set-up-approle-and-proxy.sh
+++ b/enos/modules/vault_proxy/scripts/set-up-approle-and-proxy.sh
@@ -14,7 +14,7 @@ fail() {
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
-export VAULT_ADDR='http://127.0.0.1:8200'
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
# If approle was already enabled, disable it as we're about to re-enable it (the || true is so we don't fail if it doesn't already exist)
@@ -33,20 +33,20 @@ fi
SECRETID=$($binpath write -f --format=json auth/approle/role/proxy-role/secret-id | jq -r '.data.secret_id')
if [[ "$SECRETID" == '' ]]; then
- fail "expected SECRETID to be nonempty, but it is empty"
+ fail "vault write -f --format=json auth/approle/role/proxy-role/secret-id did not return a .data.secret_id"
fi
echo "$ROLEID" > /tmp/role-id
echo "$SECRETID" > /tmp/secret-id
# Write the Vault Proxy's configuration to /tmp/vault-proxy.hcl
-# The Proxy references the fixed Vault server address of http://127.0.0.1:8200
-# The Proxy itself listens at the address http://127.0.0.1:8100
+# The Proxy references the Vault server address passed in as $VAULT_ADDR
+# The Proxy itself listens at the address passed in as $VAULT_PROXY_ADDRESS
cat > /tmp/vault-proxy.hcl <<- EOM
pid_file = "${VAULT_PROXY_PIDFILE}"
vault {
- address = "http://127.0.0.1:8200"
+ address = "${VAULT_ADDR}"
tls_skip_verify = true
retry {
num_retries = 10
diff --git a/enos/modules/vault_proxy/scripts/use-proxy.sh b/enos/modules/vault_proxy/scripts/use-proxy.sh
index 3e7e543e7a..da3a3867a0 100644
--- a/enos/modules/vault_proxy/scripts/use-proxy.sh
+++ b/enos/modules/vault_proxy/scripts/use-proxy.sh
@@ -5,13 +5,18 @@
set -e
-binpath=${VAULT_INSTALL_DIR}/vault
fail() {
echo "$1" 1>&2
return 1
}
+
+[[ -z "$VAULT_PROXY_ADDRESS" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_PROXY_PIDFILE" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
+
+binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
# Will cause the Vault CLI to communicate with the Vault Proxy, since it
@@ -26,7 +31,9 @@ unset VAULT_TOKEN
# var) to lookup the details of the Proxy's token and make sure that the
# .data.path field contains 'auth/approle/login', thus confirming that the Proxy
# automatically authenticated itself.
-$binpath token lookup -format=json | jq -r '.data.path' | grep -q 'auth/approle/login'
+if ! $binpath token lookup -format=json | jq -Mer --arg expected "auth/approle/login" '.data.path == $expected'; then
+ fail "expected proxy to automatically authenticate using 'auth/approle/login', got: '$($binpath token lookup -format=json | jq -r '.data.path')'"
+fi
# Now that we're done, kill the proxy
pkill -F "${VAULT_PROXY_PIDFILE}" || true
diff --git a/enos/modules/vault_raft_remove_peer/main.tf b/enos/modules/vault_raft_remove_peer/main.tf
index 7035fe4063..8bfef46375 100644
--- a/enos/modules/vault_raft_remove_peer/main.tf
+++ b/enos/modules/vault_raft_remove_peer/main.tf
@@ -9,20 +9,23 @@ terraform {
}
}
-variable "vault_cluster_addr_port" {
- description = "The Raft cluster address port"
- type = string
- default = "8201"
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The old vault nodes to be removed"
}
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_instance_count" {
+variable "ip_version" {
type = number
- description = "How many vault instances are in the cluster"
+ description = "The IP version used for the Vault TCP listener"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
}
variable "operator_instance" {
@@ -30,12 +33,19 @@ variable "operator_instance" {
description = "The ip address of the operator (Voter) node"
}
-variable "remove_vault_instances" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The old vault nodes to be removed"
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_cluster_addr_port" {
+ description = "The Raft cluster address port"
+ type = string
+}
+
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
}
variable "vault_root_token" {
@@ -43,22 +53,13 @@ variable "vault_root_token" {
description = "The vault root token"
}
-locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.remove_vault_instances)[idx].public_ip
- private_ip = values(var.remove_vault_instances)[idx].private_ip
- }
- }
-}
-
resource "enos_remote_exec" "vault_raft_remove_peer" {
- for_each = local.instances
+ for_each = var.hosts
environment = {
- REMOVE_VAULT_CLUSTER_ADDR = "${each.value.private_ip}:${var.vault_cluster_addr_port}"
+ REMOVE_VAULT_CLUSTER_ADDR = "${var.ip_version == 4 ? "${each.value.private_ip}" : "[${each.value.ipv6}]"}:${var.vault_cluster_addr_port}"
VAULT_TOKEN = var.vault_root_token
- VAULT_ADDR = "http://localhost:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
}
diff --git a/enos/modules/vault_setup_perf_primary/main.tf b/enos/modules/vault_setup_perf_primary/main.tf
index e9779d11af..d85f7ef6ec 100644
--- a/enos/modules/vault_setup_perf_primary/main.tf
+++ b/enos/modules/vault_setup_perf_primary/main.tf
@@ -9,25 +9,19 @@ terraform {
}
}
-variable "vault_cluster_addr_port" {
- description = "The Raft cluster address port"
- type = string
- default = "8201"
-}
-
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
variable "primary_leader_public_ip" {
type = string
description = "Vault primary cluster leader Public IP address"
}
-variable "primary_leader_private_ip" {
+variable "vault_addr" {
type = string
- description = "Vault primary cluster leader Private IP address"
+ description = "The local vault API listen address"
+}
+
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
}
variable "vault_root_token" {
@@ -37,7 +31,7 @@ variable "vault_root_token" {
resource "enos_remote_exec" "configure_pr_primary" {
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
VAULT_INSTALL_DIR = var.vault_install_dir
}
diff --git a/enos/modules/vault_setup_perf_secondary/main.tf b/enos/modules/vault_setup_perf_secondary/main.tf
index 7b0032a43d..fe2f75511d 100644
--- a/enos/modules/vault_setup_perf_secondary/main.tf
+++ b/enos/modules/vault_setup_perf_secondary/main.tf
@@ -9,25 +9,19 @@ terraform {
}
}
-variable "vault_cluster_addr_port" {
- description = "The Raft cluster address port"
- type = string
- default = "8201"
-}
-
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
variable "secondary_leader_public_ip" {
type = string
description = "Vault secondary cluster leader Public IP address"
}
-variable "secondary_leader_private_ip" {
+variable "vault_addr" {
type = string
- description = "Vault secondary cluster leader Private IP address"
+ description = "The local vault API listen address"
+}
+
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
}
variable "vault_root_token" {
@@ -40,17 +34,13 @@ variable "wrapping_token" {
description = "The wrapping token created on primary cluster"
}
-locals {
- wrapping_token = var.wrapping_token
-}
-
resource "enos_remote_exec" "configure_pr_secondary" {
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
}
- inline = ["${var.vault_install_dir}/vault write sys/replication/performance/secondary/enable token=${local.wrapping_token}"]
+ inline = ["${var.vault_install_dir}/vault write sys/replication/performance/secondary/enable token=${var.wrapping_token}"]
transport = {
ssh = {
diff --git a/enos/modules/vault_step_down/main.tf b/enos/modules/vault_step_down/main.tf
index 5ef7b280e5..4074969dee 100644
--- a/enos/modules/vault_step_down/main.tf
+++ b/enos/modules/vault_step_down/main.tf
@@ -9,22 +9,6 @@ terraform {
}
}
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_addr" {
- type = string
- description = "The vault cluster listen address"
- default = "http://localhost:8200"
-}
-
-variable "vault_root_token" {
- type = string
- description = "The vault root token"
-}
-
variable "leader_host" {
type = object({
private_ip = string
@@ -34,6 +18,21 @@ variable "leader_host" {
description = "The vault cluster host that can be expected as a leader"
}
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_root_token" {
+ type = string
+ description = "The vault root token"
+}
+
resource "enos_remote_exec" "vault_operator_step_down" {
environment = {
VAULT_TOKEN = var.vault_root_token
diff --git a/enos/modules/vault_test_ui/variables.tf b/enos/modules/vault_test_ui/variables.tf
index 9dec392d09..99625b29ec 100644
--- a/enos/modules/vault_test_ui/variables.tf
+++ b/enos/modules/vault_test_ui/variables.tf
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: BUSL-1.1
variable "vault_addr" {
- description = "The host address for the vault instance to test"
+ description = "The local vault API listen address"
type = string
}
diff --git a/enos/modules/vault_unseal_nodes/main.tf b/enos/modules/vault_unseal_nodes/main.tf
index 472601807b..59d34a7d4c 100644
--- a/enos/modules/vault_unseal_nodes/main.tf
+++ b/enos/modules/vault_unseal_nodes/main.tf
@@ -10,21 +10,25 @@ terraform {
}
}
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The Vault cluster hosts to unseal"
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "follower_public_ips" {
- type = list(string)
- description = "Vault cluster follower Public IP addresses"
-}
-
variable "vault_seal_type" {
type = string
description = "The Vault seal type"
@@ -33,18 +37,15 @@ variable "vault_seal_type" {
variable "vault_unseal_keys" {}
locals {
- followers = toset([for idx in range(var.vault_instance_count - 1) : tostring(idx)])
vault_bin_path = "${var.vault_install_dir}/vault"
}
# After replication is enabled the secondary follower nodes are expected to be sealed,
# so we wait for the secondary follower nodes to update the seal status
resource "enos_remote_exec" "wait_until_sealed" {
- for_each = {
- for idx, follower in local.followers : idx => follower
- }
+ for_each = var.hosts
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
}
@@ -52,25 +53,26 @@ resource "enos_remote_exec" "wait_until_sealed" {
transport = {
ssh = {
- host = element(var.follower_public_ips, each.key)
+ host = each.value.public_ip
}
}
}
# The follower nodes on secondary replication cluster incorrectly report
# unseal progress 2/3 (Issue: https://hashicorp.atlassian.net/browse/VAULT-12309),
-# so we restart the followers to clear the status and to autounseal incase of awskms seal type
+# so we restart the followers to allow them to auto-unseal
resource "enos_remote_exec" "restart_followers" {
depends_on = [enos_remote_exec.wait_until_sealed]
for_each = {
- for idx, follower in local.followers : idx => follower
+ for idx, host in var.hosts : idx => host
+ if var.vault_seal_type != "shamir"
}
inline = ["sudo systemctl restart vault"]
transport = {
ssh = {
- host = element(var.follower_public_ips, each.key)
+ host = each.value.public_ip
}
}
}
@@ -82,12 +84,12 @@ resource "enos_remote_exec" "unseal_followers" {
depends_on = [enos_remote_exec.restart_followers]
# The unseal keys are required only for seal_type shamir
for_each = {
- for idx, follower in local.followers : idx => follower
+ for idx, host in var.hosts : idx => host
if var.vault_seal_type == "shamir"
}
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
UNSEAL_KEYS = join(",", var.vault_unseal_keys)
}
@@ -96,7 +98,7 @@ resource "enos_remote_exec" "unseal_followers" {
transport = {
ssh = {
- host = element(var.follower_public_ips, each.key)
+ host = each.value.public_ip
}
}
}
@@ -107,12 +109,12 @@ resource "enos_remote_exec" "unseal_followers" {
resource "enos_remote_exec" "unseal_followers_again" {
depends_on = [enos_remote_exec.unseal_followers]
for_each = {
- for idx, follower in local.followers : idx => follower
+ for idx, host in var.hosts : idx => host
if var.vault_seal_type == "shamir"
}
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
UNSEAL_KEYS = join(",", var.vault_unseal_keys)
}
@@ -121,7 +123,7 @@ resource "enos_remote_exec" "unseal_followers_again" {
transport = {
ssh = {
- host = element(var.follower_public_ips, each.key)
+ host = each.value.public_ip
}
}
}
diff --git a/enos/modules/vault_upgrade/main.tf b/enos/modules/vault_upgrade/main.tf
index c92ffbacfd..6e8b0deeee 100644
--- a/enos/modules/vault_upgrade/main.tf
+++ b/enos/modules/vault_upgrade/main.tf
@@ -7,38 +7,35 @@ terraform {
source = "hashicorp/aws"
}
enos = {
- source = "registry.terraform.io/hashicorp-forge/enos"
+ source = "registry.terraform.io/hashicorp-forge/enos"
+ version = ">= 0.5.4"
}
}
}
-variable "vault_api_addr" {
- type = string
- description = "The API address of the Vault cluster"
-}
-
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
description = "The vault cluster instances that were created"
}
-variable "vault_local_artifact_path" {
+
+variable "ip_version" {
+ type = number
+ description = "The IP version used for the Vault TCP listener"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "vault_addr" {
type = string
- description = "The path to a locally built vault artifact to install"
- default = null
+ description = "The local vault API listen address"
}
variable "vault_artifactory_release" {
@@ -52,6 +49,22 @@ variable "vault_artifactory_release" {
default = null
}
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
+}
+
+variable "vault_local_artifact_path" {
+ type = string
+ description = "The path to a locally built vault artifact to install"
+ default = null
+}
+
+variable "vault_root_token" {
+ type = string
+ description = "The vault root token"
+}
+
variable "vault_seal_type" {
type = string
description = "The Vault seal type"
@@ -64,19 +77,15 @@ variable "vault_unseal_keys" {
}
locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
- followers = toset([for idx in range(var.vault_instance_count - 1) : tostring(idx)])
- follower_ips = compact(split(" ", enos_remote_exec.get_follower_public_ips.stdout))
vault_bin_path = "${var.vault_install_dir}/vault"
}
+// Upgrade the Vault artifact in-place. With zip bundles we must use the same path of the original
+// installation so that we can re-use the systemd unit that enos_vault_start created at
+// /etc/systemd/system/vault.service. The path does not matter for package types as the systemd
+// unit for the bianry is included and will be installed.
resource "enos_bundle_install" "upgrade_vault_binary" {
- for_each = local.instances
+ for_each = var.hosts
destination = var.vault_install_dir
artifactory = var.vault_artifactory_release
@@ -89,79 +98,101 @@ resource "enos_bundle_install" "upgrade_vault_binary" {
}
}
-resource "enos_remote_exec" "get_leader_public_ip" {
+// We assume that our original Vault cluster used a zip bundle from releases.hashicorp.com and as
+// such enos_vault_start will have created a systemd unit for it at /etc/systemd/systemd/vault.service.
+// If we're upgrading to a package that contains its own systemd unit we'll need to remove the
+// old unit file so that when we restart vault we pick up the new unit that points to the updated
+// binary.
+resource "enos_remote_exec" "maybe_remove_old_unit_file" {
+ for_each = var.hosts
depends_on = [enos_bundle_install.upgrade_vault_binary]
- scripts = [abspath("${path.module}/scripts/get-leader-public-ip.sh")]
-
environment = {
- VAULT_INSTALL_DIR = var.vault_install_dir,
- VAULT_INSTANCES = jsonencode(local.instances)
+ ARTIFACT_NAME = enos_bundle_install.upgrade_vault_binary[each.key].name
}
+ scripts = [abspath("${path.module}/scripts/maybe-remove-old-unit-file.sh")]
+
transport = {
ssh = {
- host = local.instances[0].public_ip
+ host = each.value.public_ip
}
}
}
-resource "enos_remote_exec" "get_follower_public_ips" {
- depends_on = [enos_bundle_install.upgrade_vault_binary]
+module "get_ip_addresses" {
+ source = "../vault_get_cluster_ips"
- environment = {
- VAULT_INSTALL_DIR = var.vault_install_dir,
- VAULT_INSTANCES = jsonencode(local.instances)
- }
+ depends_on = [enos_remote_exec.maybe_remove_old_unit_file]
- scripts = [abspath("${path.module}/scripts/get-follower-public-ips.sh")]
-
- transport = {
- ssh = {
- host = local.instances[0].public_ip
- }
- }
+ hosts = var.hosts
+ ip_version = var.ip_version
+ vault_addr = var.vault_addr
+ vault_install_dir = var.vault_install_dir
+ vault_root_token = var.vault_root_token
}
resource "enos_remote_exec" "restart_followers" {
- for_each = local.followers
- depends_on = [enos_remote_exec.get_follower_public_ips]
+ for_each = module.get_ip_addresses.follower_hosts
+
+ environment = {
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
+ }
scripts = [abspath("${path.module}/scripts/restart-vault.sh")]
transport = {
ssh = {
- host = trimspace(local.follower_ips[tonumber(each.key)])
+ host = each.value.public_ip
}
}
}
resource "enos_vault_unseal" "followers" {
- depends_on = [enos_remote_exec.restart_followers]
for_each = {
- for idx, follower in local.followers : idx => follower
+ for idx, host in module.get_ip_addresses.follower_hosts : idx => host
if var.vault_seal_type == "shamir"
}
+ depends_on = [enos_remote_exec.restart_followers]
+
bin_path = local.vault_bin_path
- vault_addr = var.vault_api_addr
+ vault_addr = var.vault_addr
seal_type = var.vault_seal_type
unseal_keys = var.vault_unseal_keys
transport = {
ssh = {
- host = trimspace(local.follower_ips[each.key])
+ host = each.value.public_ip
}
}
}
+module "wait_for_followers_unsealed" {
+ source = "../vault_verify_unsealed"
+ depends_on = [
+ enos_remote_exec.restart_followers,
+ enos_vault_unseal.followers,
+ ]
+
+ hosts = module.get_ip_addresses.follower_hosts
+ vault_addr = var.vault_addr
+ vault_install_dir = var.vault_install_dir
+}
+
resource "enos_remote_exec" "restart_leader" {
- depends_on = [enos_vault_unseal.followers]
+ depends_on = [module.wait_for_followers_unsealed]
+
+ environment = {
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
+ }
scripts = [abspath("${path.module}/scripts/restart-vault.sh")]
transport = {
ssh = {
- host = trimspace(enos_remote_exec.get_leader_public_ip.stdout)
+ host = module.get_ip_addresses.leader_public_ip
}
}
}
@@ -171,13 +202,13 @@ resource "enos_vault_unseal" "leader" {
depends_on = [enos_remote_exec.restart_leader]
bin_path = local.vault_bin_path
- vault_addr = var.vault_api_addr
+ vault_addr = var.vault_addr
seal_type = var.vault_seal_type
unseal_keys = var.vault_unseal_keys
transport = {
ssh = {
- host = trimspace(enos_remote_exec.get_leader_public_ip.stdout)
+ host = module.get_ip_addresses.leader_public_ip
}
}
}
diff --git a/enos/modules/vault_upgrade/scripts/get-follower-public-ips.sh b/enos/modules/vault_upgrade/scripts/get-follower-public-ips.sh
deleted file mode 100644
index 8cfa1b2fa6..0000000000
--- a/enos/modules/vault_upgrade/scripts/get-follower-public-ips.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
-
-
-set -e
-
-binpath=${VAULT_INSTALL_DIR}/vault
-export VAULT_ADDR="http://localhost:8200"
-
-instances=${VAULT_INSTANCES}
-
-# Find the leader
-leader_address=$($binpath status -format json | jq '.leader_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")')
-
-# Get the public ip addresses of the followers
-follower_ips=$(jq ".[] | select(.private_ip!=$leader_address) | .public_ip" <<< "$instances")
-
-echo "$follower_ips" | sed 's/\"//g' | tr '\n' ' '
diff --git a/enos/modules/vault_upgrade/scripts/get-leader-public-ip.sh b/enos/modules/vault_upgrade/scripts/get-leader-public-ip.sh
deleted file mode 100644
index 40444db774..0000000000
--- a/enos/modules/vault_upgrade/scripts/get-leader-public-ip.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
-
-
-set -e
-
-binpath=${VAULT_INSTALL_DIR}/vault
-export VAULT_ADDR="http://localhost:8200"
-
-instances=${VAULT_INSTANCES}
-
-# Find the leader
-leader_address=$($binpath status -format json | jq '.leader_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")')
-
-# Get the public ip address of the leader
-leader_public=$(jq ".[] | select(.private_ip==$leader_address) | .public_ip" <<< "$instances")
-#shellcheck disable=SC2001
-echo "$leader_public" | sed 's/\"//g'
diff --git a/enos/modules/vault_upgrade/scripts/maybe-remove-old-unit-file.sh b/enos/modules/vault_upgrade/scripts/maybe-remove-old-unit-file.sh
new file mode 100644
index 0000000000..d6872df9d2
--- /dev/null
+++ b/enos/modules/vault_upgrade/scripts/maybe-remove-old-unit-file.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+set -e
+
+fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+[[ -z "$ARTIFACT_NAME" ]] && fail "ARTIFACT_NAME env variable has not been set"
+
+if [ "${ARTIFACT_NAME##*.}" == "zip" ]; then
+ echo "Skipped removing unit file because new artifact is a zip bundle"
+ exit 0
+fi
+
+# Get the unit file for the vault.service that is running. If it's not in /etc/systemd then it
+# should be a package provided unit file so we don't need to delete anything.
+#
+# Note that we use -p instead of -P so that we support ancient amzn 2 systemctl.
+if ! unit_path=$(systemctl show -p FragmentPath vault | cut -d = -f2 2>&1); then
+ echo "Skipped removing unit file because and existing path could not be found: $unit_path"
+ exit 0
+fi
+
+if [[ "$unit_path" == *"/etc/systemd"* ]]; then
+ if [ -f "$unit_path" ]; then
+ echo "Removing old systemd unit file: $unit_path"
+ if ! out=$(sudo rm "$unit_path" 2>&1); then
+ fail "Failed to remove old unit file: $unit_path: $out"
+ fi
+ else
+ echo "Skipped removing old systemd unit file because it no longer exists: $unit_path"
+ fi
+else
+ echo "Skipped removing old systemd unit file because it was not created in /etc/systemd/: $unit_path"
+fi
diff --git a/enos/modules/vault_upgrade/scripts/restart-vault.sh b/enos/modules/vault_upgrade/scripts/restart-vault.sh
index 981ceadcde..ba067fc88c 100644
--- a/enos/modules/vault_upgrade/scripts/restart-vault.sh
+++ b/enos/modules/vault_upgrade/scripts/restart-vault.sh
@@ -2,7 +2,47 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
+fail() {
+ echo "$1" 1>&2
+ exit 1
+}
-set -eux
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+binpath=${VAULT_INSTALL_DIR}/vault
+test -x "$binpath" || fail "unable to locate vault binary at $binpath"
-sudo systemctl restart vault
+if ! out=$(sudo systemctl stop vault 2>&1); then
+ fail "failed to stop vault: $out: $(sudo systemctl status vault)"
+fi
+
+if ! out=$(sudo systemctl daemon-reload 2>&1); then
+ fail "failed to daemon-reload systemd: $out" 1>&2
+fi
+
+if ! out=$(sudo systemctl start vault 2>&1); then
+ fail "failed to start vault: $out: $(sudo systemctl status vault)"
+fi
+
+count=0
+retries=5
+while :; do
+ # Check the Vault seal status
+ status=$($binpath status)
+ code=$?
+
+ if [ $code == 0 ] || [ $code == 2 ]; then
+ # 0 is unsealed and 2 is running but sealed
+ echo "$status"
+ exit 0
+ fi
+
+ printf "Waiting for Vault cluster to be ready: status code: %s, status:\n%s\n" "$code" "$status" 2>&1
+
+ wait=$((3 ** count))
+ count=$((count + 1))
+ if [ "$count" -lt "$retries" ]; then
+ sleep "$wait"
+ else
+ fail "Timed out waiting for Vault node to be ready after restart"
+ fi
+done
diff --git a/enos/modules/vault_verify_agent_output/main.tf b/enos/modules/vault_verify_agent_output/main.tf
index 70e25516df..68e0484f2e 100644
--- a/enos/modules/vault_verify_agent_output/main.tf
+++ b/enos/modules/vault_verify_agent_output/main.tf
@@ -9,9 +9,13 @@ terraform {
}
}
-variable "vault_agent_template_destination" {
- type = string
- description = "The destination of the template rendered by Agent"
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The vault cluster instances that were created"
}
variable "vault_agent_expected_output" {
@@ -19,40 +23,22 @@ variable "vault_agent_expected_output" {
description = "The output that's expected in the rendered template at vault_agent_template_destination"
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster instances that were created"
-}
-
-locals {
- vault_instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
+variable "vault_agent_template_destination" {
+ type = string
+ description = "The destination of the template rendered by Agent"
}
resource "enos_remote_exec" "verify_vault_agent_output" {
environment = {
VAULT_AGENT_TEMPLATE_DESTINATION = var.vault_agent_template_destination
VAULT_AGENT_EXPECTED_OUTPUT = var.vault_agent_expected_output
- VAULT_INSTANCES = jsonencode(local.vault_instances)
}
scripts = [abspath("${path.module}/scripts/verify-vault-agent-output.sh")]
transport = {
ssh = {
- host = local.vault_instances[0].public_ip
+ host = var.hosts[0].public_ip
}
}
}
diff --git a/enos/modules/vault_verify_autopilot/main.tf b/enos/modules/vault_verify_autopilot/main.tf
index 8421ef72ac..236acf7564 100644
--- a/enos/modules/vault_verify_autopilot/main.tf
+++ b/enos/modules/vault_verify_autopilot/main.tf
@@ -9,32 +9,18 @@ terraform {
}
}
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
description = "The vault cluster instances that were created"
}
-variable "vault_root_token" {
+variable "vault_addr" {
type = string
- description = "The vault root token"
-}
-
-variable "vault_autopilot_upgrade_version" {
- type = string
- description = "The Vault upgraded version"
+ description = "The local vault API listen address"
}
variable "vault_autopilot_upgrade_status" {
@@ -42,19 +28,26 @@ variable "vault_autopilot_upgrade_status" {
description = "The autopilot upgrade expected status"
}
-locals {
- public_ips = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
+variable "vault_autopilot_upgrade_version" {
+ type = string
+ description = "The Vault upgraded version"
+}
+
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
+}
+
+variable "vault_root_token" {
+ type = string
+ description = "The vault root token"
}
resource "enos_remote_exec" "smoke-verify-autopilot" {
- for_each = local.public_ips
+ for_each = var.hosts
environment = {
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir,
VAULT_TOKEN = var.vault_root_token,
VAULT_AUTOPILOT_UPGRADE_STATUS = var.vault_autopilot_upgrade_status,
diff --git a/enos/modules/vault_verify_autopilot/scripts/smoke-verify-autopilot.sh b/enos/modules/vault_verify_autopilot/scripts/smoke-verify-autopilot.sh
index d19f453a07..eb0a1a1baf 100755
--- a/enos/modules/vault_verify_autopilot/scripts/smoke-verify-autopilot.sh
+++ b/enos/modules/vault_verify_autopilot/scripts/smoke-verify-autopilot.sh
@@ -7,8 +7,7 @@ fail() {
exit 1
}
-export VAULT_ADDR="http://localhost:8200"
-
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_AUTOPILOT_UPGRADE_STATUS" ]] && fail "VAULT_AUTOPILOT_UPGRADE_STATUS env variable has not been set"
[[ -z "$VAULT_AUTOPILOT_UPGRADE_VERSION" ]] && fail "VAULT_AUTOPILOT_UPGRADE_VERSION env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
diff --git a/enos/modules/vault_verify_default_lcq/main.tf b/enos/modules/vault_verify_default_lcq/main.tf
index f8dd999e24..bb05726c47 100644
--- a/enos/modules/vault_verify_default_lcq/main.tf
+++ b/enos/modules/vault_verify_default_lcq/main.tf
@@ -9,57 +9,49 @@ terraform {
}
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
description = "The vault cluster instances that were created"
}
-variable "vault_root_token" {
- type = string
- description = "The vault root token"
-}
-
-variable "vault_autopilot_default_max_leases" {
- type = string
- description = "The autopilot upgrade expected max_leases"
-}
-
-variable "timeout" {
- type = number
- description = "The max number of seconds to wait before timing out"
- default = 60
-}
-
variable "retry_interval" {
type = number
description = "How many seconds to wait between each retry"
default = 2
}
-locals {
- public_ips = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
+variable "timeout" {
+ type = number
+ description = "The max number of seconds to wait before timing out"
+ default = 60
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_autopilot_default_max_leases" {
+ type = string
+ description = "The autopilot upgrade expected max_leases"
+}
+
+variable "vault_root_token" {
+ type = string
+ description = "The vault root token"
}
resource "enos_remote_exec" "smoke_verify_default_lcq" {
- for_each = local.public_ips
+ for_each = var.hosts
environment = {
RETRY_INTERVAL = var.retry_interval
TIMEOUT_SECONDS = var.timeout
- VAULT_ADDR = "http://localhost:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
DEFAULT_LCQ = var.vault_autopilot_default_max_leases
}
diff --git a/enos/modules/vault_verify_default_lcq/scripts/smoke-verify-default-lcq.sh b/enos/modules/vault_verify_default_lcq/scripts/smoke-verify-default-lcq.sh
index 493d8b8ba9..57a9436541 100755
--- a/enos/modules/vault_verify_default_lcq/scripts/smoke-verify-default-lcq.sh
+++ b/enos/modules/vault_verify_default_lcq/scripts/smoke-verify-default-lcq.sh
@@ -7,6 +7,9 @@ function fail() {
exit 1
}
+# Exit early if we haven't been given an expected DEFAULT_LCQ
+[[ -z "$DEFAULT_LCQ" ]] && exit 0
+
[[ -z "$RETRY_INTERVAL" ]] && fail "RETRY_INTERVAL env variable has not been set"
[[ -z "$TIMEOUT_SECONDS" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
@@ -43,4 +46,4 @@ while [ "$(date +%s)" -lt "$end_time" ]; do
sleep "$RETRY_INTERVAL"
done
-fail "Timed out waiting for Default LCQ verification to complete. Data:\n\t$(getMaxLeases)"
\ No newline at end of file
+fail "Timed out waiting for Default LCQ verification to complete. Data:\n\t$(getMaxLeases)"
diff --git a/enos/modules/vault_verify_performance_replication/main.tf b/enos/modules/vault_verify_performance_replication/main.tf
index 84b39322a4..f7f99fdede 100644
--- a/enos/modules/vault_verify_performance_replication/main.tf
+++ b/enos/modules/vault_verify_performance_replication/main.tf
@@ -9,10 +9,37 @@ terraform {
}
}
-variable "vault_cluster_addr_port" {
- description = "The Raft cluster address port"
+variable "ip_version" {
+ type = number
+ description = "The IP version used for the Vault TCP listener"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "primary_leader_host" {
+ type = object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ })
+ description = "The primary cluster leader host"
+}
+
+variable "secondary_leader_host" {
+ type = object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ })
+ description = "The secondary cluster leader host"
+}
+
+variable "vault_addr" {
type = string
- default = "8201"
+ description = "The local vault API listen address"
}
variable "vault_install_dir" {
@@ -20,26 +47,6 @@ variable "vault_install_dir" {
description = "The directory where the Vault binary will be installed"
}
-variable "primary_leader_public_ip" {
- type = string
- description = "Vault primary cluster leader Public IP address"
-}
-
-variable "primary_leader_private_ip" {
- type = string
- description = "Vault primary cluster leader Private IP address"
-}
-
-variable "secondary_leader_public_ip" {
- type = string
- description = "Vault secondary cluster leader Public IP address"
-}
-
-variable "secondary_leader_private_ip" {
- type = string
- description = "Vault secondary cluster leader Private IP address"
-}
-
variable "wrapping_token" {
type = string
description = "The wrapping token created on primary cluster"
@@ -47,40 +54,44 @@ variable "wrapping_token" {
}
locals {
+ primary_leader_addr = var.ip_version == 6 ? var.primary_leader_host.ipv6 : var.primary_leader_host.private_ip
+ secondary_leader_addr = var.ip_version == 6 ? var.secondary_leader_host.ipv6 : var.secondary_leader_host.private_ip
primary_replication_status = jsondecode(enos_remote_exec.verify_replication_status_on_primary.stdout)
secondary_replication_status = jsondecode(enos_remote_exec.verify_replication_status_on_secondary.stdout)
}
resource "enos_remote_exec" "verify_replication_status_on_primary" {
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
- VAULT_INSTALL_DIR = var.vault_install_dir
- PRIMARY_LEADER_PRIV_IP = var.primary_leader_private_ip
- SECONDARY_LEADER_PRIV_IP = var.secondary_leader_private_ip
+ IP_VERSION = var.ip_version
+ PRIMARY_LEADER_ADDR = local.primary_leader_addr
+ SECONDARY_LEADER_ADDR = local.secondary_leader_addr
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
}
scripts = [abspath("${path.module}/scripts/verify-replication-status.sh")]
transport = {
ssh = {
- host = var.primary_leader_public_ip
+ host = var.primary_leader_host.public_ip
}
}
}
resource "enos_remote_exec" "verify_replication_status_on_secondary" {
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
- VAULT_INSTALL_DIR = var.vault_install_dir
- PRIMARY_LEADER_PRIV_IP = var.primary_leader_private_ip
- SECONDARY_LEADER_PRIV_IP = var.secondary_leader_private_ip
+ IP_VERSION = var.ip_version
+ PRIMARY_LEADER_ADDR = local.primary_leader_addr
+ SECONDARY_LEADER_ADDR = local.secondary_leader_addr
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
}
scripts = [abspath("${path.module}/scripts/verify-replication-status.sh")]
transport = {
ssh = {
- host = var.secondary_leader_public_ip
+ host = var.secondary_leader_host.public_ip
}
}
}
diff --git a/enos/modules/vault_verify_performance_replication/scripts/verify-replication-status.sh b/enos/modules/vault_verify_performance_replication/scripts/verify-replication-status.sh
index 687ac3eb56..623f38921f 100644
--- a/enos/modules/vault_verify_performance_replication/scripts/verify-replication-status.sh
+++ b/enos/modules/vault_verify_performance_replication/scripts/verify-replication-status.sh
@@ -14,8 +14,9 @@ fail() {
exit 1
}
-[[ -z "$PRIMARY_LEADER_PRIV_IP" ]] && fail "PRIMARY_LEADER_PRIV_IP env variable has not been set"
-[[ -z "$SECONDARY_LEADER_PRIV_IP" ]] && fail "SECONDARY_LEADER_PRIV_IP env variable has not been set"
+[[ -z "$IP_VERSION" ]] && fail "IP_VERSION env variable has not been set"
+[[ -z "$PRIMARY_LEADER_ADDR" ]] && fail "PRIMARY_LEADER_ADDR env variable has not been set"
+[[ -z "$SECONDARY_LEADER_ADDR" ]] && fail "SECONDARY_LEADER_ADDR env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
@@ -40,8 +41,8 @@ retry() {
check_pr_status() {
pr_status=$($binpath read -format=json sys/replication/performance/status)
- cluster_state=$(echo "$pr_status" | jq -r '.data.state')
- connection_mode=$(echo "$pr_status" | jq -r '.data.mode')
+ cluster_state=$(jq -r '.data.state' <<< "$pr_status")
+ connection_mode=$(jq -r '.data.mode' <<< "$pr_status")
if [[ "$cluster_state" == 'idle' ]]; then
echo "replication cluster state is idle" 1>&2
@@ -49,30 +50,38 @@ check_pr_status() {
fi
if [[ "$connection_mode" == "primary" ]]; then
- connection_status=$(echo "$pr_status" | jq -r '.data.secondaries[0].connection_status')
+ connection_status=$(jq -r '.data.secondaries[0].connection_status' <<< "$pr_status")
if [[ "$connection_status" == 'disconnected' ]]; then
echo ".data.secondaries[0].connection_status from primary node is 'disconnected'" 1>&2
return 1
fi
- secondary_cluster_addr=$(echo "$pr_status" | jq -r '.data.secondaries[0].cluster_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")')
- if [[ "$secondary_cluster_addr" != "$SECONDARY_LEADER_PRIV_IP" ]]; then
- echo ".data.secondaries[0].cluster_address should have an IP address of $SECONDARY_LEADER_PRIV_IP, got: $secondary_cluster_addr" 1>&2
+ if [ "$IP_VERSION" == 4 ]; then
+ secondary_cluster_addr=$(jq -r '.data.secondaries[0].cluster_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")' <<< "$pr_status")
+ else
+ secondary_cluster_addr=$(jq -r '.data.secondaries[0].cluster_address | scan("\\[(.+)\\]") | .[0]' <<< "$pr_status")
+ fi
+ if [[ "$secondary_cluster_addr" != "$SECONDARY_LEADER_ADDR" ]]; then
+ echo ".data.secondaries[0].cluster_address should have an IP address of $SECONDARY_LEADER_ADDR, got: $secondary_cluster_addr" 1>&2
return 1
fi
else
- connection_status=$(echo "$pr_status" | jq -r '.data.primaries[0].connection_status')
+ connection_status=$(jq -r '.data.primaries[0].connection_status' <<< "$pr_status")
if [[ "$connection_status" == 'disconnected' ]]; then
echo ".data.primaries[0].connection_status from secondary node is 'disconnected'" 1>&2
return 1
fi
- primary_cluster_addr=$(echo "$pr_status" | jq -r '.data.primaries[0].cluster_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")')
- if [[ "$primary_cluster_addr" != "$PRIMARY_LEADER_PRIV_IP" ]]; then
- echo ".data.primaries[0].cluster_address should have an IP address of $PRIMARY_LEADER_PRIV_IP, got: $primary_cluster_addr" 1>&2
+ if [ "$IP_VERSION" == 4 ]; then
+ primary_cluster_addr=$(jq -r '.data.primaries[0].cluster_address | scan("[0-9]+.[0-9]+.[0-9]+.[0-9]+")' <<< "$pr_status")
+ else
+ primary_cluster_addr=$(jq -r '.data.primaries[0].cluster_address | scan("\\[(.+)\\]") | .[0]' <<< "$pr_status")
+ fi
+ if [[ "$primary_cluster_addr" != "$PRIMARY_LEADER_ADDR" ]]; then
+ echo ".data.primaries[0].cluster_address should have an IP address of $PRIMARY_LEADER_ADDR, got: $primary_cluster_addr" 1>&2
return 1
fi
- known_primary_cluster_addrs=$(echo "$pr_status" | jq -r '.data.known_primary_cluster_addrs')
- if ! echo "$known_primary_cluster_addrs" | grep -q "$PRIMARY_LEADER_PRIV_IP"; then
- echo "$PRIMARY_LEADER_PRIV_IP is not in .data.known_primary_cluster_addrs: $known_primary_cluster_addrs" 1>&2
+ known_primary_cluster_addrs=$(jq -r '.data.known_primary_cluster_addrs' <<< "$pr_status")
+ if ! echo "$known_primary_cluster_addrs" | grep -q "$PRIMARY_LEADER_ADDR"; then
+ echo "$PRIMARY_LEADER_ADDR is not in .data.known_primary_cluster_addrs: $known_primary_cluster_addrs" 1>&2
return 1
fi
fi
@@ -81,5 +90,10 @@ check_pr_status() {
return 0
}
+
+if [ "$IP_VERSION" != 4 ] && [ "$IP_VERSION" != 6 ]; then
+ fail "unsupported IP_VERSION: $IP_VERSION"
+fi
+
# Retry for a while because it can take some time for replication to sync
retry 10 check_pr_status
diff --git a/enos/modules/vault_verify_raft_auto_join_voter/main.tf b/enos/modules/vault_verify_raft_auto_join_voter/main.tf
index 12f0eb4e4a..826b00b54c 100644
--- a/enos/modules/vault_verify_raft_auto_join_voter/main.tf
+++ b/enos/modules/vault_verify_raft_auto_join_voter/main.tf
@@ -9,10 +9,33 @@ terraform {
}
}
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The vault cluster instances that were created"
+}
+
+variable "ip_version" {
+ type = number
+ description = "The IP version to use for the Vault TCP listeners"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_cluster_addr_port" {
description = "The Raft cluster address port"
type = string
- default = "8201"
}
variable "vault_install_dir" {
@@ -20,38 +43,24 @@ variable "vault_install_dir" {
description = "The directory where the Vault binary will be installed"
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster instances that were created"
-}
-
variable "vault_root_token" {
type = string
description = "The vault root token"
}
locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
+ cluster_addrs = {
+ 4 : { for k, v in var.hosts : k => "${v.private_ip}:${var.vault_cluster_addr_port}" },
+ 6 : { for k, v in var.hosts : k => "[${v.ipv6}]:${var.vault_cluster_addr_port}" },
}
}
resource "enos_remote_exec" "verify_raft_auto_join_voter" {
- for_each = local.instances
+ for_each = var.hosts
environment = {
- VAULT_CLUSTER_ADDR = "${each.value.private_ip}:${var.vault_cluster_addr_port}"
+ VAULT_ADDR = var.vault_addr
+ VAULT_CLUSTER_ADDR = local.cluster_addrs[var.ip_version][each.key]
VAULT_INSTALL_DIR = var.vault_install_dir
VAULT_LOCAL_BINARY_PATH = "${var.vault_install_dir}/vault"
VAULT_TOKEN = var.vault_root_token
diff --git a/enos/modules/vault_verify_raft_auto_join_voter/scripts/verify-raft-auto-join-voter.sh b/enos/modules/vault_verify_raft_auto_join_voter/scripts/verify-raft-auto-join-voter.sh
index 6512d25876..79c5070fd8 100644
--- a/enos/modules/vault_verify_raft_auto_join_voter/scripts/verify-raft-auto-join-voter.sh
+++ b/enos/modules/vault_verify_raft_auto_join_voter/scripts/verify-raft-auto-join-voter.sh
@@ -42,9 +42,9 @@ check_voter_status() {
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
-export VAULT_ADDR='http://127.0.0.1:8200'
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
# Retry a few times because it can take some time for things to settle after
# all the nodes are unsealed
-retry 7 check_voter_status
+retry 10 check_voter_status
diff --git a/enos/modules/vault_verify_read_data/main.tf b/enos/modules/vault_verify_read_data/main.tf
index 4b794942f1..244dc38893 100644
--- a/enos/modules/vault_verify_read_data/main.tf
+++ b/enos/modules/vault_verify_read_data/main.tf
@@ -9,32 +9,34 @@ terraform {
}
}
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The Vault cluster instances that were created"
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "node_public_ips" {
- type = list(string)
- description = "Vault cluster node Public IP address"
-}
-
locals {
- followers = toset([for idx in range(var.vault_instance_count - 1) : tostring(idx)])
vault_bin_path = "${var.vault_install_dir}/vault"
}
resource "enos_remote_exec" "verify_kv_on_node" {
- for_each = {
- for idx, follower in local.followers : idx => follower
- }
+ for_each = var.hosts
+
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
}
@@ -42,7 +44,7 @@ resource "enos_remote_exec" "verify_kv_on_node" {
transport = {
ssh = {
- host = element(var.node_public_ips, each.key)
+ host = each.value.public_ip
}
}
}
diff --git a/enos/modules/vault_verify_replication/main.tf b/enos/modules/vault_verify_replication/main.tf
index 835bb776d3..f9377d87c1 100644
--- a/enos/modules/vault_verify_replication/main.tf
+++ b/enos/modules/vault_verify_replication/main.tf
@@ -10,19 +10,31 @@ terraform {
}
}
-locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The vault cluster instances that were created"
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_edition" {
+ type = string
+ description = "The vault product edition"
+ default = null
}
resource "enos_remote_exec" "smoke-verify-replication" {
- for_each = local.instances
+ for_each = var.hosts
environment = {
+ VAULT_ADDR = var.vault_addr
VAULT_EDITION = var.vault_edition
}
diff --git a/enos/modules/vault_verify_replication/scripts/smoke-verify-replication.sh b/enos/modules/vault_verify_replication/scripts/smoke-verify-replication.sh
index 5ef9afd8b1..72ecbd2521 100644
--- a/enos/modules/vault_verify_replication/scripts/smoke-verify-replication.sh
+++ b/enos/modules/vault_verify_replication/scripts/smoke-verify-replication.sh
@@ -2,10 +2,6 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
-
-# The Vault replication smoke test, documented in
-# https://docs.google.com/document/d/16sjIk3hzFDPyY5A9ncxTZV_9gnpYSF1_Vx6UA1iiwgI/edit#heading=h.kgrxf0f1et25
-
set -e
function fail() {
@@ -13,8 +9,11 @@ function fail() {
exit 1
}
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_EDITION" ]] && fail "VAULT_EDITION env variable has not been set"
+
# Replication status endpoint should have data.mode disabled for CE release
-status=$(curl -s http://localhost:8200/v1/sys/replication/status)
+status=$(curl "${VAULT_ADDR}/v1/sys/replication/status")
if [ "$VAULT_EDITION" == "ce" ]; then
if [ "$(jq -r '.data.mode' <<< "$status")" != "disabled" ]; then
fail "replication data mode is not disabled for CE release!"
diff --git a/enos/modules/vault_verify_replication/variables.tf b/enos/modules/vault_verify_replication/variables.tf
deleted file mode 100644
index 158b699bf4..0000000000
--- a/enos/modules/vault_verify_replication/variables.tf
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
-
-
-variable "vault_edition" {
- type = string
- description = "The vault product edition"
- default = null
-}
-
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster instances that were created"
-}
diff --git a/enos/modules/vault_verify_ui/main.tf b/enos/modules/vault_verify_ui/main.tf
index b6077c6ed2..61d7361efa 100644
--- a/enos/modules/vault_verify_ui/main.tf
+++ b/enos/modules/vault_verify_ui/main.tf
@@ -10,17 +10,22 @@ terraform {
}
}
-locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The vault cluster instances that were created"
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
}
resource "enos_remote_exec" "smoke-verify-ui" {
- for_each = local.instances
+ for_each = var.hosts
environment = {
VAULT_ADDR = var.vault_addr,
diff --git a/enos/modules/vault_verify_ui/variables.tf b/enos/modules/vault_verify_ui/variables.tf
deleted file mode 100644
index d06d60ac96..0000000000
--- a/enos/modules/vault_verify_ui/variables.tf
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) HashiCorp, Inc.
-# SPDX-License-Identifier: BUSL-1.1
-
-variable "vault_addr" {
- type = string
- description = "The vault cluster address"
- default = "http://localhost:8200"
-}
-
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster instances that were created"
-}
diff --git a/enos/modules/vault_verify_undo_logs/main.tf b/enos/modules/vault_verify_undo_logs/main.tf
index b4a251f111..5547321120 100644
--- a/enos/modules/vault_verify_undo_logs/main.tf
+++ b/enos/modules/vault_verify_undo_logs/main.tf
@@ -9,22 +9,45 @@ terraform {
}
}
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_instance_count" {
+variable "expected_state" {
type = number
- description = "How many vault instances are in the cluster"
+ description = "The expected state to have in vault.core.replication.write_undo_logs telemetry. Must be either 1 for enabled or 0 for disabled."
+
+ validation {
+ condition = contains([0, 1], var.expected_state)
+ error_message = "The expected_state must be either 0 or 1"
+ }
}
-variable "vault_instances" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
- description = "The vault cluster instances that were created"
+ description = "The vault cluster target hosts to check"
+}
+
+variable "retry_interval" {
+ type = number
+ description = "How many seconds to wait between each retry"
+ default = 2
+}
+
+variable "timeout" {
+ type = number
+ description = "The max number of seconds to wait before timing out"
+ default = 60
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
}
variable "vault_root_token" {
@@ -32,20 +55,14 @@ variable "vault_root_token" {
description = "The vault root token"
}
-locals {
- public_ips = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
-}
-
resource "enos_remote_exec" "smoke-verify-undo-logs" {
- for_each = local.public_ips
+ for_each = var.hosts
environment = {
- VAULT_ADDR = "http://localhost:8200"
+ EXPECTED_STATE = var.expected_state
+ RETRY_INTERVAL = var.retry_interval
+ TIMEOUT_SECONDS = var.timeout
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
VAULT_TOKEN = var.vault_root_token
}
diff --git a/enos/modules/vault_verify_undo_logs/scripts/smoke-verify-undo-logs.sh b/enos/modules/vault_verify_undo_logs/scripts/smoke-verify-undo-logs.sh
index 080ec079a8..99bc7018c7 100644
--- a/enos/modules/vault_verify_undo_logs/scripts/smoke-verify-undo-logs.sh
+++ b/enos/modules/vault_verify_undo_logs/scripts/smoke-verify-undo-logs.sh
@@ -7,6 +7,9 @@ function fail() {
exit 1
}
+[[ -z "$EXPECTED_STATE" ]] && fail "EXPECTED_STAE env variable has not been set"
+[[ -z "$RETRY_INTERVAL" ]] && fail "RETRY_INTERVAL env variable has not been set"
+[[ -z "$TIMEOUT_SECONDS" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
@@ -14,23 +17,19 @@ function fail() {
binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
-count=0
-retries=5
-while :; do
+begin_time=$(date +%s)
+end_time=$((begin_time + TIMEOUT_SECONDS))
+while [ "$(date +%s)" -lt "$end_time" ]; do
state=$($binpath read sys/metrics -format=json | jq -r '.data.Gauges[] | select(.Name == "vault.core.replication.write_undo_logs")')
target_undo_logs_status="$(jq -r '.Value' <<< "$state")"
- if [ "$target_undo_logs_status" == "1" ]; then
+ if [ "$target_undo_logs_status" == "$EXPECTED_STATE" ]; then
+ echo "vault.core.replication.write_undo_logs has expected Value: \"${EXPECTED_STATE}\""
exit 0
fi
- wait=$((2 ** count))
- count=$((count + 1))
- if [ "$count" -lt "$retries" ]; then
- echo "Waiting for vault.core.replication.write_undo_logs to have Value:1"
- echo "$state"
- sleep "$wait"
- else
- fail "Timed out waiting for vault.core.replication.write_undo_logs to have Value:1"
- fi
+ echo "Waiting for vault.core.replication.write_undo_logs to have Value: \"${EXPECTED_STATE}\""
+ sleep "$RETRY_INTERVAL"
done
+
+fail "Timed out waiting for vault.core.replication.write_undo_logs to have Value: \"${EXPECTED_STATE}\""
diff --git a/enos/modules/vault_verify_unsealed/main.tf b/enos/modules/vault_verify_unsealed/main.tf
index cc8e471063..86eb2b57f9 100644
--- a/enos/modules/vault_verify_unsealed/main.tf
+++ b/enos/modules/vault_verify_unsealed/main.tf
@@ -9,10 +9,18 @@ terraform {
}
}
-variable "vault_cluster_addr_port" {
- description = "The Raft cluster address port"
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The vault cluster instances that were created"
+}
+
+variable "vault_addr" {
type = string
- default = "8201"
+ description = "The local vault API listen address"
}
variable "vault_install_dir" {
@@ -20,36 +28,16 @@ variable "vault_install_dir" {
description = "The directory where the Vault binary will be installed"
}
-variable "vault_instance_count" {
- type = number
- description = "How many vault instances are in the cluster"
-}
-
-variable "vault_instances" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster instances that were created"
-}
-
-locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
-}
-
resource "enos_remote_exec" "verify_node_unsealed" {
- for_each = local.instances
+ for_each = var.hosts
scripts = [abspath("${path.module}/scripts/verify-vault-node-unsealed.sh")]
environment = {
- VAULT_CLUSTER_ADDR = "${each.value.private_ip}:${var.vault_cluster_addr_port}"
- VAULT_INSTALL_DIR = var.vault_install_dir
+ HOST_IPV4 = each.value.public_ip
+ HOST_IPV6 = each.value.ipv6
+ VAULT_ADDR = var.vault_addr
+ VAULT_INSTALL_DIR = var.vault_install_dir
}
transport = {
diff --git a/enos/modules/vault_verify_unsealed/scripts/verify-vault-node-unsealed.sh b/enos/modules/vault_verify_unsealed/scripts/verify-vault-node-unsealed.sh
index 44523f2fd7..4d14725ed5 100644
--- a/enos/modules/vault_verify_unsealed/scripts/verify-vault-node-unsealed.sh
+++ b/enos/modules/vault_verify_unsealed/scripts/verify-vault-node-unsealed.sh
@@ -4,23 +4,23 @@
set -e
-binpath=${VAULT_INSTALL_DIR}/vault
fail() {
echo "$1" 1>&2
exit 1
}
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
+
+binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
-export VAULT_ADDR=http://localhost:8200
-
count=0
-retries=4
+retries=5
while :; do
- health_status=$(curl -s "${VAULT_CLUSTER_ADDR}/v1/sys/health" |jq '.')
- unseal_status=$($binpath status -format json | jq -Mr --argjson expected "false" '.sealed == $expected')
- if [[ "$unseal_status" == 'true' ]]; then
+ health_status=$(curl -s "${VAULT_ADDR}/v1/sys/health" | jq '.')
+ if unseal_status=$($binpath status -format json | jq -Mre --argjson expected "false" '.sealed == $expected'); then
echo "$health_status"
exit 0
fi
@@ -30,6 +30,14 @@ while :; do
if [ "$count" -lt "$retries" ]; then
sleep "$wait"
else
- fail "expected ${VAULT_CLUSTER_ADDR} to be unsealed, got unseal status: $unseal_status"
+ if [ -n "$HOST_IPV6" ]; then
+ fail "expected ${HOST_IPV6} to be unsealed, got unseal status: $unseal_status"
+ else
+ if [ -n "$HOST_IPV4" ]; then
+ fail "expected ${HOST_IPV4} to be unsealed, got unseal status: $unseal_status"
+ else
+ fail "expected ${VAULT_ADDR} to be unsealed, got unseal status: $unseal_status"
+ fi
+ fi
fi
done
diff --git a/enos/modules/vault_verify_version/main.tf b/enos/modules/vault_verify_version/main.tf
index 8a1d722e50..9c992bb0a0 100644
--- a/enos/modules/vault_verify_version/main.tf
+++ b/enos/modules/vault_verify_version/main.tf
@@ -9,42 +9,43 @@ terraform {
}
}
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The Vault cluster instances that were created"
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_build_date" {
type = string
description = "The Vault artifact build date"
default = null
}
+variable "vault_edition" {
+ type = string
+ description = "The Vault product edition"
+ default = null
+}
+
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
}
-variable "vault_instance_count" {
- type = number
- description = "How many Vault instances are in the cluster"
-}
-
-variable "vault_instances" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The Vault cluster instances that were created"
-}
-
variable "vault_product_version" {
type = string
description = "The Vault product version"
default = null
}
-variable "vault_edition" {
- type = string
- description = "The Vault product edition"
- default = null
-}
-
variable "vault_revision" {
type = string
description = "The Vault product revision"
@@ -57,25 +58,36 @@ variable "vault_root_token" {
default = null
}
-locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
+resource "enos_remote_exec" "verify_cli_version" {
+ for_each = var.hosts
+
+ environment = {
+ VAULT_ADDR = var.vault_addr,
+ VAULT_BUILD_DATE = var.vault_build_date,
+ VAULT_EDITION = var.vault_edition,
+ VAULT_INSTALL_DIR = var.vault_install_dir,
+ VAULT_REVISION = var.vault_revision,
+ VAULT_TOKEN = var.vault_root_token,
+ VAULT_VERSION = var.vault_product_version,
+ }
+
+ scripts = [abspath("${path.module}/scripts/verify-cli-version.sh")]
+
+ transport = {
+ ssh = {
+ host = each.value.public_ip
}
}
}
-resource "enos_remote_exec" "verify_all_nodes_have_updated_version" {
- for_each = local.instances
+resource "enos_remote_exec" "verify_cluster_version" {
+ for_each = var.hosts
environment = {
- VAULT_INSTALL_DIR = var.vault_install_dir,
- VAULT_BUILD_DATE = var.vault_build_date,
- VAULT_VERSION = var.vault_product_version,
- VAULT_EDITION = var.vault_edition,
- VAULT_REVISION = var.vault_revision,
- VAULT_TOKEN = var.vault_root_token,
+ VAULT_ADDR = var.vault_addr,
+ VAULT_BUILD_DATE = var.vault_build_date,
+ VAULT_TOKEN = var.vault_root_token,
+ VAULT_VERSION = var.vault_product_version,
}
scripts = [abspath("${path.module}/scripts/verify-cluster-version.sh")]
diff --git a/enos/modules/vault_verify_version/scripts/verify-cli-version.sh b/enos/modules/vault_verify_version/scripts/verify-cli-version.sh
new file mode 100644
index 0000000000..58fd4c7891
--- /dev/null
+++ b/enos/modules/vault_verify_version/scripts/verify-cli-version.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: BUSL-1.1
+
+# Verify the Vault "version" includes the correct base version, build date,
+# revision SHA, and edition metadata.
+set -e
+
+fail() {
+ echo "$1" 1>&2
+ exit 1
+}
+
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_BUILD_DATE" ]] && fail "VAULT_BUILD_DATE env variable has not been set"
+[[ -z "$VAULT_EDITION" ]] && fail "VAULT_EDITION env variable has not been set"
+[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
+[[ -z "$VAULT_REVISION" ]] && fail "VAULT_REVISION env variable has not been set"
+[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
+[[ -z "$VAULT_VERSION" ]] && fail "VAULT_VERSION env variable has not been set"
+
+binpath=${VAULT_INSTALL_DIR}/vault
+edition=${VAULT_EDITION}
+version=${VAULT_VERSION}
+sha=${VAULT_REVISION}
+build_date=${VAULT_BUILD_DATE}
+
+test -x "$binpath" || fail "unable to locate vault binary at $binpath"
+version_expected="Vault v$version ($sha), built $build_date"
+
+case "$edition" in
+ *ce) ;;
+ *ent) ;;
+ *ent.hsm) version_expected="$version_expected (cgo)";;
+ *ent.fips1402) version_expected="$version_expected (cgo)" ;;
+ *ent.hsm.fips1402) version_expected="$version_expected (cgo)" ;;
+ *) fail "Unknown Vault edition: ($edition)" ;;
+esac
+
+version_expected_nosha=$(echo "$version_expected" | awk '!($3="")' | sed 's/ / /' | sed -e 's/[[:space:]]*$//')
+version_output=$("$binpath" version)
+
+if [[ "$version_output" == "$version_expected_nosha" ]] || [[ "$version_output" == "$version_expected" ]]; then
+ echo "Version verification succeeded!"
+else
+ msg="$(printf "\nThe Vault cluster did not match the expected version, expected:\n%s\nor\n%s\ngot:\n%s" "$version_expected" "$version_expected_nosha" "$version_output")"
+ if type diff &> /dev/null; then
+ # Diff exits non-zero if we have a diff, which we want, so we'll guard against failing early.
+ if ! version_diff=$(diff <(echo "$version_expected" ) <(echo "$version_output") -u -L expected -L got); then
+ msg="$(printf "\nThe Vault cluster did not match the expected version:\n%s" "$version_diff")"
+ fi
+ fi
+
+ fail "$msg"
+fi
diff --git a/enos/modules/vault_verify_version/scripts/verify-cluster-version.sh b/enos/modules/vault_verify_version/scripts/verify-cluster-version.sh
index 9ec43876af..f0afee6451 100644
--- a/enos/modules/vault_verify_version/scripts/verify-cluster-version.sh
+++ b/enos/modules/vault_verify_version/scripts/verify-cluster-version.sh
@@ -2,44 +2,36 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
-
# Verify the Vault "version" includes the correct base version, build date,
# revision SHA, and edition metadata.
set -e
-binpath=${VAULT_INSTALL_DIR}/vault
-edition=${VAULT_EDITION}
-version=${VAULT_VERSION}
-sha=${VAULT_REVISION}
-build_date=${VAULT_BUILD_DATE}
-# VAULT_TOKEN must also be set
-
fail() {
echo "$1" 1>&2
exit 1
}
-test -x "$binpath" || fail "unable to locate vault binary at $binpath"
-
-export VAULT_ADDR='http://127.0.0.1:8200'
+[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
+[[ -z "$VAULT_BUILD_DATE" ]] && fail "VAULT_BUILD_DATE env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
+[[ -z "$VAULT_VERSION" ]] && fail "VAULT_VERSION env variable has not been set"
-version_expected="Vault v$version ($sha), built $build_date"
-
-case "$edition" in
- *ce) ;;
- *ent) ;;
- *ent.hsm) version_expected="$version_expected (cgo)";;
- *ent.fips1402) version_expected="$version_expected (cgo)" ;;
- *ent.hsm.fips1402) version_expected="$version_expected (cgo)" ;;
- *) fail "Unknown Vault edition: ($edition)" ;;
-esac
-
-version_expected_nosha=$(echo "$version_expected" | awk '!($3="")' | sed 's/ / /' | sed -e 's/[[:space:]]*$//')
-version_output=$("$binpath" version)
-
-if [[ "$version_output" == "$version_expected_nosha" ]] || [[ "$version_output" == "$version_expected" ]]; then
- echo "Version verification succeeded!"
-else
- fail "expected Version=$version_expected or $version_expected_nosha, got: $version_output"
+# The sys/version-history endpoint only includes major.minor.patch, any other semver fields need to
+# be stripped out.
+if ! version=$(cut -d + -f1 <<< "$VAULT_VERSION" | cut -d - -f1); then
+ fail "failed to parse the expected version: $version"
fi
+
+if ! vh=$(curl -s -X LIST -H "X-Vault-Token: $VAULT_TOKEN" http://127.0.0.1:8200/v1/sys/version-history | jq -eMc '.data'); then
+ fail "failed to Vault cluster version history: $vh"
+fi
+
+if ! out=$(jq -eMc --arg version "$version" '.keys | contains([$version])' <<< "$vh"); then
+ fail "cluster version history does not include our expected version: expected: $version, versions: $(jq -eMc '.keys' <<< "$vh"): output: $out"
+fi
+
+if ! out=$(jq -eMc --arg version "$version" --arg bd "$VAULT_BUILD_DATE" '.key_info[$version].build_date == $bd' <<< "$vh"); then
+ fail "cluster version history build date is not the expected date: expected: true, expected date: $VAULT_BUILD_DATE, key_info: $(jq -eMc '.key_info' <<< "$vh"), output: $out"
+fi
+
+printf "Cluster version information is valid!: %s\n" "$vh"
diff --git a/enos/modules/vault_verify_write_data/main.tf b/enos/modules/vault_verify_write_data/main.tf
index c0baa9f51d..4f4401981e 100644
--- a/enos/modules/vault_verify_write_data/main.tf
+++ b/enos/modules/vault_verify_write_data/main.tf
@@ -9,56 +9,48 @@ terraform {
}
}
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_instance_count" {
- type = number
- description = "How many Vault instances are in the cluster"
-}
-
-variable "leader_public_ip" {
- type = string
- description = "Vault cluster leader Public IP address"
-}
-
-variable "leader_private_ip" {
- type = string
- description = "Vault cluster leader Private IP address"
-}
-
-variable "vault_instances" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
description = "The Vault cluster instances that were created"
}
+variable "leader_host" {
+ type = object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ })
+
+ description = "Vault cluster leader host"
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
+}
+
variable "vault_root_token" {
type = string
description = "The Vault root token"
default = null
}
-locals {
- instances = {
- for idx in range(var.vault_instance_count) : idx => {
- public_ip = values(var.vault_instances)[idx].public_ip
- private_ip = values(var.vault_instances)[idx].private_ip
- }
- }
-}
-
# We use this module to verify write data in all Enos scenarios. Since we cannot use
# Vault token to authenticate to secondary clusters in replication scenario we add a regular user
# here to keep the authentication method and module verification consistent between all scenarios
resource "enos_remote_exec" "smoke-enable-secrets-kv" {
# Only enable the secrets engine on the leader node
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
VAULT_INSTALL_DIR = var.vault_install_dir
}
@@ -67,7 +59,7 @@ resource "enos_remote_exec" "smoke-enable-secrets-kv" {
transport = {
ssh = {
- host = var.leader_public_ip
+ host = var.leader_host.public_ip
}
}
}
@@ -75,10 +67,10 @@ resource "enos_remote_exec" "smoke-enable-secrets-kv" {
# Verify that we can enable the k/v secrets engine and write data to it.
resource "enos_remote_exec" "smoke-write-test-data" {
depends_on = [enos_remote_exec.smoke-enable-secrets-kv]
- for_each = local.instances
+ for_each = var.hosts
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
VAULT_INSTALL_DIR = var.vault_install_dir
TEST_KEY = "smoke${each.key}"
diff --git a/enos/modules/vault_wait_for_leader/main.tf b/enos/modules/vault_wait_for_leader/main.tf
index 0cd1c82a8c..7c29280c91 100644
--- a/enos/modules/vault_wait_for_leader/main.tf
+++ b/enos/modules/vault_wait_for_leader/main.tf
@@ -9,6 +9,30 @@ terraform {
}
}
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The vault cluster hosts that can be expected as a leader"
+}
+
+variable "ip_version" {
+ type = number
+ description = "The IP version used for the Vault TCP listener"
+
+ validation {
+ condition = contains([4, 6], var.ip_version)
+ error_message = "The ip_version must be either 4 or 6"
+ }
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
@@ -19,14 +43,6 @@ variable "vault_root_token" {
description = "The vault root token"
}
-variable "vault_hosts" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster hosts that can be expected as a leader"
-}
-
variable "timeout" {
type = number
description = "The max number of seconds to wait before timing out"
@@ -40,15 +56,18 @@ variable "retry_interval" {
}
locals {
- private_ips = [for k, v in values(tomap(var.vault_hosts)) : tostring(v["private_ip"])]
+ ipv6s = [for k, v in values(tomap(var.hosts)) : tostring(v["ipv6"])]
+ private_ips = [for k, v in values(tomap(var.hosts)) : tostring(v["private_ip"])]
}
-resource "enos_remote_exec" "wait_for_leader_in_vault_hosts" {
+resource "enos_remote_exec" "wait_for_leader_in_hosts" {
environment = {
- RETRY_INTERVAL = var.retry_interval
+ IP_VERSION = var.ip_version
TIMEOUT_SECONDS = var.timeout
- VAULT_ADDR = "http://127.0.0.1:8200"
+ RETRY_INTERVAL = var.retry_interval
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
+ VAULT_INSTANCE_IPV6S = jsonencode(local.ipv6s)
VAULT_INSTANCE_PRIVATE_IPS = jsonencode(local.private_ips)
VAULT_INSTALL_DIR = var.vault_install_dir
}
@@ -57,7 +76,7 @@ resource "enos_remote_exec" "wait_for_leader_in_vault_hosts" {
transport = {
ssh = {
- host = var.vault_hosts[0].public_ip
+ host = var.hosts[0].public_ip
}
}
}
diff --git a/enos/modules/vault_wait_for_leader/scripts/wait-for-leader.sh b/enos/modules/vault_wait_for_leader/scripts/wait-for-leader.sh
index f993ae8b62..4194cd8ad2 100644
--- a/enos/modules/vault_wait_for_leader/scripts/wait-for-leader.sh
+++ b/enos/modules/vault_wait_for_leader/scripts/wait-for-leader.sh
@@ -14,7 +14,6 @@ fail() {
[[ -z "$TIMEOUT_SECONDS" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
-[[ -z "$VAULT_INSTANCE_PRIVATE_IPS" ]] && fail "VAULT_INSTANCE_PRIVATE_IPS env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
binpath=${VAULT_INSTALL_DIR}/vault
@@ -40,14 +39,59 @@ findLeaderInPrivateIPs() {
return 1
}
+findLeaderInIPV6s() {
+ # Find the leader private IP address
+ local leader_ipv6
+ if ! leader_ipv6=$($binpath read sys/leader -format=json | jq -er '.data.leader_address | scan("\\[(.+)\\]") | .[0]') ; then
+ # Some older versions of vault don't support reading sys/leader. Fallback to the cli status.
+ if ! leader_ipv6=$($binpath status -format json | jq -er '.leader_address | scan("\\[(.+)\\]") | .[0]'); then
+ return 1
+ fi
+ fi
+
+ if isIn=$(jq -er --arg ip "$leader_ipv6" 'map(select(. == $ip)) | length == 1' <<< "$VAULT_INSTANCE_IPV6S"); then
+ if [[ "$isIn" == "true" ]]; then
+ echo "$leader_ipv6"
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
begin_time=$(date +%s)
end_time=$((begin_time + TIMEOUT_SECONDS))
while [ "$(date +%s)" -lt "$end_time" ]; do
- if findLeaderInPrivateIPs; then
- exit 0
- fi
+ # Use the default package manager of the current Linux distro to install packages
+ case $IP_VERSION in
+ 4)
+ [[ -z "$VAULT_INSTANCE_PRIVATE_IPS" ]] && fail "VAULT_INSTANCE_PRIVATE_IPS env variable has not been set"
+ if findLeaderInPrivateIPs; then
+ exit 0
+ fi
+ ;;
+ 6)
+ [[ -z "$VAULT_INSTANCE_IPV6S" ]] && fail "VAULT_INSTANCE_IPV6S env variable has not been set"
+ if findLeaderInIPV6s; then
+ exit 0
+ fi
+ ;;
+ *)
+ fail "No matching package manager provided."
+ ;;
+ esac
sleep "$RETRY_INTERVAL"
done
-fail "Timed out waiting for one of $VAULT_INSTANCE_PRIVATE_IPS to be leader."
+case $IP_VERSION in
+ 4)
+ fail "Timed out waiting for one of $VAULT_INSTANCE_PRIVATE_IPS to be leader."
+ ;;
+ 6)
+ fail "Timed out waiting for one of $VAULT_INSTANCE_IPV6S to be leader."
+ ;;
+ *)
+ fail "Timed out waiting for leader"
+ ;;
+esac
diff --git a/enos/modules/vault_wait_for_seal_rewrap/main.tf b/enos/modules/vault_wait_for_seal_rewrap/main.tf
index 2a234d0deb..920672a71d 100644
--- a/enos/modules/vault_wait_for_seal_rewrap/main.tf
+++ b/enos/modules/vault_wait_for_seal_rewrap/main.tf
@@ -9,6 +9,32 @@ terraform {
}
}
+variable "hosts" {
+ type = map(object({
+ ipv6 = string
+ private_ip = string
+ public_ip = string
+ }))
+ description = "The vault cluster hosts that can be expected as a leader"
+}
+
+variable "retry_interval" {
+ type = number
+ description = "How many seconds to wait between each retry"
+ default = 2
+}
+
+variable "timeout" {
+ type = number
+ description = "The max number of seconds to wait before timing out"
+ default = 60
+}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
variable "vault_install_dir" {
type = string
description = "The directory where the Vault binary will be installed"
@@ -19,37 +45,17 @@ variable "vault_root_token" {
description = "The vault root token"
}
-variable "vault_hosts" {
- type = map(object({
- private_ip = string
- public_ip = string
- }))
- description = "The vault cluster hosts that can be expected as a leader"
-}
-
-variable "timeout" {
- type = number
- description = "The max number of seconds to wait before timing out"
- default = 60
-}
-
-variable "retry_interval" {
- type = number
- description = "How many seconds to wait between each retry"
- default = 2
-}
-
locals {
- private_ips = [for k, v in values(tomap(var.vault_hosts)) : tostring(v["private_ip"])]
+ private_ips = [for k, v in values(tomap(var.hosts)) : tostring(v["private_ip"])]
first_key = element(keys(enos_remote_exec.wait_for_seal_rewrap_to_be_completed), 0)
}
resource "enos_remote_exec" "wait_for_seal_rewrap_to_be_completed" {
- for_each = var.vault_hosts
+ for_each = var.hosts
environment = {
RETRY_INTERVAL = var.retry_interval
TIMEOUT_SECONDS = var.timeout
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_TOKEN = var.vault_root_token
VAULT_INSTALL_DIR = var.vault_install_dir
}
diff --git a/enos/modules/verify_seal_type/main.tf b/enos/modules/verify_seal_type/main.tf
index 7f8fb20b33..e8d81890dd 100644
--- a/enos/modules/verify_seal_type/main.tf
+++ b/enos/modules/verify_seal_type/main.tf
@@ -9,13 +9,9 @@ terraform {
}
}
-variable "vault_install_dir" {
- type = string
- description = "The directory where the Vault binary will be installed"
-}
-
-variable "vault_hosts" {
+variable "hosts" {
type = map(object({
+ ipv6 = string
private_ip = string
public_ip = string
}))
@@ -28,13 +24,24 @@ variable "seal_type" {
default = "shamir"
}
+
+variable "vault_addr" {
+ type = string
+ description = "The local vault API listen address"
+}
+
+variable "vault_install_dir" {
+ type = string
+ description = "The directory where the Vault binary will be installed"
+}
+
resource "enos_remote_exec" "verify_seal_type" {
- for_each = var.vault_hosts
+ for_each = var.hosts
scripts = [abspath("${path.module}/scripts/verify-seal-type.sh")]
environment = {
- VAULT_ADDR = "http://127.0.0.1:8200"
+ VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
EXPECTED_SEAL_TYPE = var.seal_type
}
diff --git a/go.mod b/go.mod
index e6770805e1..693490e180 100644
--- a/go.mod
+++ b/go.mod
@@ -10,9 +10,7 @@ module github.com/hashicorp/vault
// semantic related to Go module handling), this comment should be updated to explain that.
//
// Whenever this value gets updated, sdk/go.mod should be updated to the same value.
-go 1.21
-
-toolchain go1.22.2
+go 1.22.5
replace github.com/hashicorp/vault/api => ./api
@@ -26,25 +24,25 @@ replace github.com/hashicorp/vault/sdk => ./sdk
require (
cloud.google.com/go/cloudsqlconn v1.4.3
- cloud.google.com/go/monitoring v1.17.0
- cloud.google.com/go/spanner v1.55.0
- cloud.google.com/go/storage v1.36.0
- github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
- github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
+ cloud.google.com/go/monitoring v1.19.0
+ cloud.google.com/go/spanner v1.62.0
+ cloud.google.com/go/storage v1.41.0
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
+ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0
github.com/Azure/azure-storage-blob-go v0.15.0
github.com/Azure/go-autorest/autorest v0.11.29
github.com/Azure/go-autorest/autorest/adal v0.9.23
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371
- github.com/SAP/go-hdb v0.14.1
+ github.com/SAP/go-hdb v1.10.1
github.com/Sectorbob/mlab-ns2 v0.0.0-20171030222938-d3aa0c295a8a
github.com/aerospike/aerospike-client-go/v5 v5.6.0
- github.com/aliyun/alibaba-cloud-sdk-go v1.62.676
+ github.com/aliyun/alibaba-cloud-sdk-go v1.62.737
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5
github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2
github.com/armon/go-metrics v0.4.1
github.com/armon/go-radix v1.0.0
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
- github.com/aws/aws-sdk-go v1.50.13
+ github.com/aws/aws-sdk-go v1.53.5
github.com/aws/aws-sdk-go-v2/config v1.18.19
github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a
github.com/cenkalti/backoff/v3 v3.2.2
@@ -52,19 +50,19 @@ require (
github.com/cockroachdb/cockroach-go/v2 v2.3.8
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/denisenkom/go-mssqldb v0.12.3
- github.com/docker/docker v25.0.5+incompatible
+ github.com/docker/docker v25.0.6+incompatible
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74
github.com/dustin/go-humanize v1.0.1
- github.com/fatih/color v1.16.0
+ github.com/fatih/color v1.17.0
github.com/fatih/structs v1.1.0
github.com/gammazero/workerpool v1.1.3
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/go-errors/errors v1.5.1
github.com/go-git/go-git/v5 v5.11.0
github.com/go-jose/go-jose/v3 v3.0.3
- github.com/go-ldap/ldap/v3 v3.4.6
+ github.com/go-ldap/ldap/v3 v3.4.8
github.com/go-sql-driver/mysql v1.7.1
- github.com/go-test/deep v1.1.0
+ github.com/go-test/deep v1.1.1
github.com/go-zookeeper/zk v1.0.3
github.com/gocql/gocql v1.0.0
github.com/golang-jwt/jwt/v4 v4.5.0
@@ -74,17 +72,17 @@ require (
github.com/google/go-metrics-stackdriver v0.2.0
github.com/google/tink/go v1.7.0
github.com/hashicorp-forge/bbolt v1.3.8-hc3
- github.com/hashicorp/cap v0.6.0
- github.com/hashicorp/cap/ldap v0.0.0-20240328153749-fcfe271d0227
+ github.com/hashicorp/cap v0.7.0
+ github.com/hashicorp/cap/ldap v0.0.0-20240403125925-c0418810d10e
github.com/hashicorp/cli v1.1.6
- github.com/hashicorp/consul-template v0.37.6
- github.com/hashicorp/consul/api v1.27.0
+ github.com/hashicorp/consul-template v0.39.1
+ github.com/hashicorp/consul/api v1.29.1
github.com/hashicorp/errwrap v1.1.0
- github.com/hashicorp/eventlogger v0.2.8
+ github.com/hashicorp/eventlogger v0.2.10
github.com/hashicorp/go-bexpr v0.1.12
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-discover v0.0.0-20210818145131-c573d69da192
- github.com/hashicorp/go-gcp-common v0.8.0
+ github.com/hashicorp/go-gcp-common v0.9.0
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.1
github.com/hashicorp/go-kms-wrapping/v2 v2.0.16
@@ -99,7 +97,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-plugin v1.6.0
github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a
- github.com/hashicorp/go-retryablehttp v0.7.5
+ github.com/hashicorp/go-retryablehttp v0.7.7
github.com/hashicorp/go-rootcerts v1.0.2
github.com/hashicorp/go-secure-stdlib/awsutil v0.3.0
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2
@@ -122,63 +120,60 @@ require (
github.com/hashicorp/hcl/v2 v2.16.2
github.com/hashicorp/hcp-link v0.2.1
github.com/hashicorp/hcp-scada-provider v0.2.2
- github.com/hashicorp/hcp-sdk-go v0.75.0
+ github.com/hashicorp/hcp-sdk-go v0.101.0
github.com/hashicorp/nomad/api v0.0.0-20240213164230-c364cb57298d
- github.com/hashicorp/raft v1.6.1
+ github.com/hashicorp/raft v1.7.0
github.com/hashicorp/raft-autopilot v0.2.0
github.com/hashicorp/raft-boltdb/v2 v2.3.0
github.com/hashicorp/raft-snapshot v1.0.4
github.com/hashicorp/raft-wal v0.4.0
- github.com/hashicorp/vault-hcp-lib v0.0.0-20240402205111-2312b38227ab
- github.com/hashicorp/vault-plugin-auth-alicloud v0.17.0
- github.com/hashicorp/vault-plugin-auth-azure v0.17.0
- github.com/hashicorp/vault-plugin-auth-centrify v0.15.1
- github.com/hashicorp/vault-plugin-auth-cf v0.16.0
- github.com/hashicorp/vault-plugin-auth-gcp v0.16.2
- github.com/hashicorp/vault-plugin-auth-jwt v0.20.3
- github.com/hashicorp/vault-plugin-auth-kerberos v0.11.0
- github.com/hashicorp/vault-plugin-auth-kubernetes v0.18.0
- github.com/hashicorp/vault-plugin-auth-oci v0.15.1
- github.com/hashicorp/vault-plugin-database-couchbase v0.10.1
- github.com/hashicorp/vault-plugin-database-elasticsearch v0.14.0
- github.com/hashicorp/vault-plugin-database-mongodbatlas v0.11.0
+ github.com/hashicorp/vault-hcp-lib v0.0.0-20240704151836-a5c058ac604c
+ github.com/hashicorp/vault-plugin-auth-alicloud v0.18.0
+ github.com/hashicorp/vault-plugin-auth-azure v0.18.0
+ github.com/hashicorp/vault-plugin-auth-cf v0.18.0
+ github.com/hashicorp/vault-plugin-auth-gcp v0.18.0
+ github.com/hashicorp/vault-plugin-auth-jwt v0.21.1
+ github.com/hashicorp/vault-plugin-auth-kerberos v0.12.0
+ github.com/hashicorp/vault-plugin-auth-kubernetes v0.19.0
+ github.com/hashicorp/vault-plugin-auth-oci v0.16.0
+ github.com/hashicorp/vault-plugin-database-couchbase v0.11.0
+ github.com/hashicorp/vault-plugin-database-elasticsearch v0.15.0
+ github.com/hashicorp/vault-plugin-database-mongodbatlas v0.12.0
github.com/hashicorp/vault-plugin-database-redis v0.3.0
- github.com/hashicorp/vault-plugin-database-redis-elasticache v0.3.0
- github.com/hashicorp/vault-plugin-database-snowflake v0.10.0
+ github.com/hashicorp/vault-plugin-database-redis-elasticache v0.4.0
+ github.com/hashicorp/vault-plugin-database-snowflake v0.11.0
github.com/hashicorp/vault-plugin-mock v0.16.1
- github.com/hashicorp/vault-plugin-secrets-ad v0.17.0
- github.com/hashicorp/vault-plugin-secrets-alicloud v0.16.0
- github.com/hashicorp/vault-plugin-secrets-azure v0.17.2
- github.com/hashicorp/vault-plugin-secrets-gcp v0.18.0
- github.com/hashicorp/vault-plugin-secrets-gcpkms v0.16.0
- github.com/hashicorp/vault-plugin-secrets-kubernetes v0.7.0
- github.com/hashicorp/vault-plugin-secrets-kv v0.18.0
- github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.11.0
- github.com/hashicorp/vault-plugin-secrets-openldap v0.12.1
- github.com/hashicorp/vault-plugin-secrets-terraform v0.7.5
+ github.com/hashicorp/vault-plugin-secrets-ad v0.18.0
+ github.com/hashicorp/vault-plugin-secrets-alicloud v0.17.0
+ github.com/hashicorp/vault-plugin-secrets-azure v0.19.2
+ github.com/hashicorp/vault-plugin-secrets-gcp v0.19.0
+ github.com/hashicorp/vault-plugin-secrets-gcpkms v0.17.0
+ github.com/hashicorp/vault-plugin-secrets-kubernetes v0.8.0
+ github.com/hashicorp/vault-plugin-secrets-kv v0.19.0
+ github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.12.0
+ github.com/hashicorp/vault-plugin-secrets-openldap v0.13.0
+ github.com/hashicorp/vault-plugin-secrets-terraform v0.9.0
github.com/hashicorp/vault-testing-stepwise v0.1.4
- github.com/hashicorp/vault/api v1.12.0
+ github.com/hashicorp/vault/api v1.14.0
github.com/hashicorp/vault/api/auth/approle v0.1.0
github.com/hashicorp/vault/api/auth/userpass v0.1.0
- github.com/hashicorp/vault/sdk v0.12.0
+ github.com/hashicorp/vault/sdk v0.13.0
github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab
github.com/jackc/pgx/v4 v4.18.3
github.com/jcmturner/gokrb5/v8 v8.4.4
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f
- github.com/jefferai/jsonx v1.0.0
+ github.com/jefferai/jsonx v1.0.1
github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f
- github.com/klauspost/compress v1.16.7
+ github.com/klauspost/compress v1.17.8
github.com/kr/pretty v0.3.1
github.com/kr/text v0.2.0
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.20
- github.com/mholt/archiver/v3 v3.5.1
github.com/michaelklishin/rabbit-hole/v2 v2.12.0
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a
github.com/mitchellh/copystructure v1.2.0
github.com/mitchellh/go-homedir v1.1.0
- github.com/mitchellh/go-testing-interface v1.14.1
github.com/mitchellh/go-wordwrap v1.0.1
github.com/mitchellh/mapstructure v1.5.0
github.com/mitchellh/reflectwalk v1.0.2
@@ -189,12 +184,12 @@ require (
github.com/ory/dockertest v3.3.5+incompatible
github.com/ory/dockertest/v3 v3.10.0
github.com/patrickmn/go-cache v2.1.0+incompatible
- github.com/pires/go-proxyproto v0.6.1
+ github.com/pires/go-proxyproto v1.0.0
github.com/pkg/errors v0.9.1
github.com/posener/complete v1.2.3
github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d
- github.com/prometheus/client_golang v1.19.0
- github.com/prometheus/common v0.49.0
+ github.com/prometheus/client_golang v1.19.1
+ github.com/prometheus/common v0.55.0
github.com/rboyer/safeio v0.2.1
github.com/robfig/cron/v3 v3.0.1
github.com/ryanuber/columnize v2.1.2+incompatible
@@ -204,47 +199,58 @@ require (
github.com/shirou/gopsutil/v3 v3.22.6
github.com/stretchr/testify v1.9.0
go.etcd.io/bbolt v1.3.7
- go.etcd.io/etcd/client/pkg/v3 v3.5.7
+ go.etcd.io/etcd/client/pkg/v3 v3.5.13
go.etcd.io/etcd/client/v2 v2.305.5
- go.etcd.io/etcd/client/v3 v3.5.7
+ go.etcd.io/etcd/client/v3 v3.5.13
go.mongodb.org/atlas v0.36.0
- go.mongodb.org/mongo-driver v1.13.1
- go.opentelemetry.io/otel v1.24.0
- go.opentelemetry.io/otel/sdk v1.23.1
- go.opentelemetry.io/otel/trace v1.24.0
+ go.mongodb.org/mongo-driver v1.16.0
+ go.opentelemetry.io/otel v1.28.0
+ go.opentelemetry.io/otel/sdk v1.28.0
+ go.opentelemetry.io/otel/trace v1.28.0
go.uber.org/atomic v1.11.0
- go.uber.org/goleak v1.2.1
- golang.org/x/crypto v0.23.0
- golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
- golang.org/x/net v0.25.0
- golang.org/x/oauth2 v0.18.0
- golang.org/x/sync v0.7.0
- golang.org/x/sys v0.20.0
- golang.org/x/term v0.20.0
- golang.org/x/text v0.15.0
- golang.org/x/tools v0.18.0
- google.golang.org/api v0.163.0
- google.golang.org/grpc v1.61.1
- google.golang.org/protobuf v1.34.1
+ go.uber.org/goleak v1.3.0
+ golang.org/x/crypto v0.26.0
+ golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
+ golang.org/x/net v0.28.0
+ golang.org/x/oauth2 v0.21.0
+ golang.org/x/sync v0.8.0
+ golang.org/x/sys v0.24.0
+ golang.org/x/term v0.23.0
+ golang.org/x/text v0.17.0
+ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
+ google.golang.org/api v0.181.0
+ google.golang.org/grpc v1.65.0
+ google.golang.org/protobuf v1.34.2
gopkg.in/ory-am/dockertest.v3 v3.3.4
- k8s.io/apimachinery v0.29.1
+ k8s.io/apimachinery v0.29.3
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
layeh.com/radius v0.0.0-20231213012653-1006025d24f8
- nhooyr.io/websocket v1.8.7
+ nhooyr.io/websocket v1.8.11
)
require (
- cloud.google.com/go v0.112.0 // indirect
- cloud.google.com/go/compute v1.23.3 // indirect
- cloud.google.com/go/compute/metadata v0.2.3 // indirect
- cloud.google.com/go/iam v1.1.5 // indirect
- cloud.google.com/go/kms v1.15.6 // indirect
+ cel.dev/expr v0.15.0 // indirect
+ cloud.google.com/go/longrunning v0.5.7 // indirect
+ github.com/containerd/containerd v1.7.12 // indirect
+ github.com/hashicorp/go-secure-stdlib/httputil v0.1.0 // indirect
+ github.com/mitchellh/go-testing-interface v1.14.1 // indirect
+ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
+ gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
+)
+
+require (
+ cloud.google.com/go v0.113.0 // indirect
+ cloud.google.com/go/auth v0.4.1 // indirect
+ cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
+ cloud.google.com/go/compute/metadata v0.3.0 // indirect
+ cloud.google.com/go/iam v1.1.8 // indirect
+ cloud.google.com/go/kms v1.17.0 // indirect; indirect\
dario.cat/mergo v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.2 // indirect
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 // indirect
@@ -262,10 +268,11 @@ require (
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
- github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
+ github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
- github.com/Jeffail/gabs v1.1.1 // indirect
+ github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 // indirect
+ github.com/Jeffail/gabs/v2 v2.1.0 // indirect
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
@@ -274,8 +281,7 @@ require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
- github.com/andybalholm/brotli v1.0.5 // indirect
- github.com/apache/arrow/go/v14 v14.0.2 // indirect
+ github.com/apache/arrow/go/v15 v15.0.0 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.23.4 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
@@ -298,32 +304,31 @@ require (
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/benbjohnson/immutable v0.4.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
- github.com/bgentry/speakeasy v0.1.0 // indirect
+ github.com/bgentry/speakeasy v0.2.0 // indirect
github.com/boltdb/bolt v1.3.1 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.2.1 // indirect
+ github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
- github.com/centrify/cloud-golang-sdk v0.0.0-20210923165758-a8c48d049166 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect
github.com/circonus-labs/circonusllhist v0.1.3 // indirect
github.com/cjlapao/common-go v0.0.39 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cloudfoundry-community/go-cfclient v0.0.0-20220930021109-9c4e6c59ccf1 // indirect
- github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
- github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 // indirect
- github.com/containerd/containerd v1.7.12 // indirect
+ github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect
github.com/containerd/continuity v0.4.2 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/coreos/etcd v3.3.27+incompatible // indirect
- github.com/coreos/go-oidc v2.2.1+incompatible // indirect
- github.com/coreos/go-oidc/v3 v3.10.0 // indirect
+ github.com/coreos/go-oidc/v3 v3.11.0 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect
- github.com/couchbase/gocb/v2 v2.6.5 // indirect
- github.com/couchbase/gocbcore/v10 v10.3.1 // indirect
+ github.com/couchbase/gocb/v2 v2.8.1 // indirect
+ github.com/couchbase/gocbcore/v10 v10.4.1 // indirect
+ github.com/couchbase/gocbcoreps v0.1.2 // indirect
+ github.com/couchbase/goprotostellar v1.0.2 // indirect
+ github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@@ -332,44 +337,42 @@ require (
github.com/digitalocean/godo v1.7.5 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
- github.com/docker/cli v25.0.1+incompatible // indirect
+ github.com/docker/cli v25.0.5+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
- github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
- github.com/envoyproxy/go-control-plane v0.11.1 // indirect
- github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect
+ github.com/envoyproxy/go-control-plane v0.12.0 // indirect
+ github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
- github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gammazero/deque v0.2.1 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
- github.com/go-jose/go-jose/v4 v4.0.1 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.4 // indirect
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3 // indirect
- github.com/go-logr/logr v1.4.1 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
- github.com/go-openapi/analysis v0.21.4 // indirect
- github.com/go-openapi/errors v0.20.4 // indirect
- github.com/go-openapi/jsonpointer v0.20.0 // indirect
- github.com/go-openapi/jsonreference v0.20.2 // indirect
- github.com/go-openapi/loads v0.21.2 // indirect
- github.com/go-openapi/runtime v0.26.0 // indirect
- github.com/go-openapi/spec v0.20.9 // indirect
- github.com/go-openapi/strfmt v0.21.7 // indirect
- github.com/go-openapi/swag v0.22.4 // indirect
- github.com/go-openapi/validate v0.22.2 // indirect
+ github.com/go-openapi/analysis v0.23.0 // indirect
+ github.com/go-openapi/errors v0.22.0 // indirect
+ github.com/go-openapi/jsonpointer v0.21.0 // indirect
+ github.com/go-openapi/jsonreference v0.21.0 // indirect
+ github.com/go-openapi/loads v0.22.0 // indirect
+ github.com/go-openapi/runtime v0.28.0 // indirect
+ github.com/go-openapi/spec v0.21.0 // indirect
+ github.com/go-openapi/strfmt v0.23.0 // indirect
+ github.com/go-openapi/swag v0.23.0 // indirect
+ github.com/go-openapi/validate v0.24.0 // indirect
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gofrs/uuid v4.3.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
+ github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@@ -382,18 +385,19 @@ require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
- github.com/googleapis/gax-go/v2 v2.12.0 // indirect
+ github.com/googleapis/gax-go/v2 v2.12.4 // indirect
github.com/gophercloud/gophercloud v0.1.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
+ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/hashicorp/cronexpr v1.1.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
- github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect
+ github.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect
github.com/hashicorp/go-secure-stdlib/fileutil v0.1.0 // indirect
github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 // indirect
- github.com/hashicorp/go-slug v0.13.4 // indirect
- github.com/hashicorp/go-tfe v1.44.0 // indirect
+ github.com/hashicorp/go-slug v0.15.0 // indirect
+ github.com/hashicorp/go-tfe v1.61.0 // indirect
github.com/hashicorp/jsonapi v1.3.1 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/mdns v1.0.4 // indirect
@@ -402,7 +406,7 @@ require (
github.com/hashicorp/vault/api/auth/kubernetes v0.6.0 // indirect
github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
- github.com/huandu/xstrings v1.4.0 // indirect
+ github.com/huandu/xstrings v1.5.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.3 // indirect
@@ -425,7 +429,6 @@ require (
github.com/kelseyhightower/envconfig v1.4.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
- github.com/klauspost/pgzip v1.2.5 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/linode/linodego v0.7.1 // indirect
@@ -433,15 +436,15 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-ieproxy v0.0.1 // indirect
github.com/mediocregopher/radix/v4 v4.1.4 // indirect
- github.com/microsoft/kiota-abstractions-go v1.5.6 // indirect
- github.com/microsoft/kiota-authentication-azure-go v1.0.1 // indirect
- github.com/microsoft/kiota-http-go v1.1.1 // indirect
+ github.com/microsoft/kiota-abstractions-go v1.6.0 // indirect
+ github.com/microsoft/kiota-authentication-azure-go v1.0.2 // indirect
+ github.com/microsoft/kiota-http-go v1.3.1 // indirect
github.com/microsoft/kiota-serialization-form-go v1.0.0 // indirect
- github.com/microsoft/kiota-serialization-json-go v1.0.5 // indirect
+ github.com/microsoft/kiota-serialization-json-go v1.0.7 // indirect
github.com/microsoft/kiota-serialization-multipart-go v1.0.0 // indirect
github.com/microsoft/kiota-serialization-text-go v1.0.0 // indirect
- github.com/microsoftgraph/msgraph-sdk-go v1.32.0 // indirect
- github.com/microsoftgraph/msgraph-sdk-go-core v1.0.1 // indirect
+ github.com/microsoftgraph/msgraph-sdk-go v1.42.0 // indirect
+ github.com/microsoftgraph/msgraph-sdk-go-core v1.1.0 // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/mitchellh/hashstructure v1.1.0 // indirect
@@ -452,13 +455,12 @@ require (
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
- github.com/mongodb-forks/digest v1.0.5 // indirect
- github.com/montanaflynn/stats v0.7.0 // indirect
+ github.com/mongodb-forks/digest v1.1.0 // indirect
+ github.com/montanaflynn/stats v0.7.1 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/natefinch/atomic v1.0.1 // indirect
github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 // indirect
- github.com/nwaples/rardecode v1.1.2 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
@@ -474,30 +476,28 @@ require (
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
- github.com/pquerna/cachecontrol v0.1.0 // indirect
- github.com/prometheus/client_model v0.6.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
+ github.com/prometheus/client_model v0.6.1 // indirect
+ github.com/prometheus/procfs v0.15.1 // indirect
github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 // indirect
- github.com/rogpeppe/go-internal v1.11.0 // indirect
+ github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
- github.com/shopspring/decimal v1.3.1 // indirect
+ github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
- github.com/snowflakedb/gosnowflake v1.7.2 // indirect
+ github.com/snowflakedb/gosnowflake v1.10.0 // indirect
github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
- github.com/std-uritemplate/std-uritemplate/go v0.0.50 // indirect
+ github.com/std-uritemplate/std-uritemplate/go v0.0.55 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/tencentcloud/tencentcloud-sdk-go v1.0.162 // indirect
github.com/tilinna/clock v1.1.0 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c // indirect
- github.com/ulikunitz/xz v0.5.10 // indirect
github.com/vmware/govmomi v0.18.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
@@ -506,36 +506,33 @@ require (
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
- github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
github.com/zclconf/go-cty v1.12.1 // indirect
github.com/zeebo/xxh3 v1.0.2 // indirect
- go.etcd.io/etcd/api/v3 v3.5.7 // indirect
+ go.etcd.io/etcd/api/v3 v3.5.13 // indirect
go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
- go.opentelemetry.io/otel/metric v1.24.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
+ go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.26.0 // indirect
- golang.org/x/mod v0.15.0 // indirect
+ go.uber.org/zap v1.27.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
golang.org/x/time v0.5.0 // indirect
- golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
- google.golang.org/appengine v1.6.8 // indirect
- google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect
+ google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 // indirect; indirect\
gopkg.in/inf.v0 v0.9.1 // indirect
- gopkg.in/ini.v1 v1.66.2 // indirect
+ gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect
gopkg.in/resty.v1 v1.12.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.29.1 // indirect
- k8s.io/client-go v0.29.1 // indirect
+ k8s.io/api v0.29.3 // indirect
+ k8s.io/client-go v0.29.3 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
@@ -544,3 +541,7 @@ require (
)
replace github.com/ma314smith/signedxml v1.1.1 => github.com/moov-io/signedxml v1.1.1
+
+// Support using the forked repository until https://github.com/pires/go-proxyproto/pull/110 merges
+// and is released.
+replace github.com/pires/go-proxyproto v1.0.0 => github.com/peteski22/go-proxyproto v1.0.0
diff --git a/go.sum b/go.sum
index 99b44c96ae..33394f6567 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
-bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
-bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
+cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w=
+cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -39,75 +39,35 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
-cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw=
-cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
-cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
-cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
-cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk=
-cloud.google.com/go v0.110.9/go.mod h1:rpxevX/0Lqvlbc88b7Sc1SPNdyK1riNBTUU6JXhYNpM=
-cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic=
-cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM=
-cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4=
+cloud.google.com/go v0.113.0 h1:g3C70mn3lWfckKBiCVsAshabrDg01pQ0pnX1MNtnMkA=
+cloud.google.com/go v0.113.0/go.mod h1:glEqlogERKYeePz6ZdkcLJ28Q2I6aERgDDErBg9GzO8=
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
-cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68=
-cloud.google.com/go/accessapproval v1.7.2/go.mod h1:/gShiq9/kK/h8T/eEn1BTzalDvk0mZxJlhfw0p+Xuc0=
-cloud.google.com/go/accessapproval v1.7.3/go.mod h1:4l8+pwIxGTNqSf4T3ds8nLO94NQf0W/KnMNuQ9PbnP8=
-cloud.google.com/go/accessapproval v1.7.4/go.mod h1:/aTEh45LzplQgFYdQdwPMR9YdX0UlhBmvB84uAmQKUc=
cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o=
cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE=
cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM=
cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ=
-cloud.google.com/go/accesscontextmanager v1.8.0/go.mod h1:uI+AI/r1oyWK99NN8cQ3UK76AMelMzgZCvJfsi2c+ps=
-cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo=
-cloud.google.com/go/accesscontextmanager v1.8.2/go.mod h1:E6/SCRM30elQJ2PKtFMs2YhfJpZSNcJyejhuzoId4Zk=
-cloud.google.com/go/accesscontextmanager v1.8.3/go.mod h1:4i/JkF2JiFbhLnnpnfoTX5vRXfhf9ukhU1ANOTALTOQ=
-cloud.google.com/go/accesscontextmanager v1.8.4/go.mod h1:ParU+WbMpD34s5JFEnGAnPBYAgUHozaTmDJU7aCU9+M=
cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg=
cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ=
cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k=
cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw=
-cloud.google.com/go/aiplatform v1.45.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA=
-cloud.google.com/go/aiplatform v1.48.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA=
-cloud.google.com/go/aiplatform v1.50.0/go.mod h1:IRc2b8XAMTa9ZmfJV1BCCQbieWWvDnP1A8znyz5N7y4=
-cloud.google.com/go/aiplatform v1.51.0/go.mod h1:IRc2b8XAMTa9ZmfJV1BCCQbieWWvDnP1A8znyz5N7y4=
-cloud.google.com/go/aiplatform v1.51.1/go.mod h1:kY3nIMAVQOK2XDqDPHaOuD9e+FdMA6OOpfBjsvaFSOo=
-cloud.google.com/go/aiplatform v1.51.2/go.mod h1:hCqVYB3mY45w99TmetEoe8eCQEwZEp9WHxeZdcv9phw=
-cloud.google.com/go/aiplatform v1.52.0/go.mod h1:pwZMGvqe0JRkI1GWSZCtnAfrR4K1bv65IHILGA//VEU=
cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4=
cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M=
cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE=
cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE=
-cloud.google.com/go/analytics v0.21.2/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo=
-cloud.google.com/go/analytics v0.21.3/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo=
-cloud.google.com/go/analytics v0.21.4/go.mod h1:zZgNCxLCy8b2rKKVfC1YkC2vTrpfZmeRCySM3aUbskA=
-cloud.google.com/go/analytics v0.21.5/go.mod h1:BQtOBHWTlJ96axpPPnw5CvGJ6i3Ve/qX2fTxR8qWyr8=
-cloud.google.com/go/analytics v0.21.6/go.mod h1:eiROFQKosh4hMaNhF85Oc9WO97Cpa7RggD40e/RBy8w=
cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk=
cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc=
cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8=
-cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA=
-cloud.google.com/go/apigateway v1.6.2/go.mod h1:CwMC90nnZElorCW63P2pAYm25AtQrHfuOkbRSHj0bT8=
-cloud.google.com/go/apigateway v1.6.3/go.mod h1:k68PXWpEs6BVDTtnLQAyG606Q3mz8pshItwPXjgv44Y=
-cloud.google.com/go/apigateway v1.6.4/go.mod h1:0EpJlVGH5HwAN4VF4Iec8TAzGN1aQgbxAWGJsnPCGGY=
cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc=
cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04=
cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8=
-cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs=
-cloud.google.com/go/apigeeconnect v1.6.2/go.mod h1:s6O0CgXT9RgAxlq3DLXvG8riw8PYYbU/v25jqP3Dy18=
-cloud.google.com/go/apigeeconnect v1.6.3/go.mod h1:peG0HFQ0si2bN15M6QSjEW/W7Gy3NYkWGz7pFz13cbo=
-cloud.google.com/go/apigeeconnect v1.6.4/go.mod h1:CapQCWZ8TCjnU0d7PobxhpOdVz/OVJ2Hr/Zcuu1xFx0=
cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY=
cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM=
cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc=
-cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw=
-cloud.google.com/go/apigeeregistry v0.7.2/go.mod h1:9CA2B2+TGsPKtfi3F7/1ncCCsL62NXBRfM6iPoGSM+8=
-cloud.google.com/go/apigeeregistry v0.8.1/go.mod h1:MW4ig1N4JZQsXmBSwH4rwpgDonocz7FPBSw6XPGHmYw=
-cloud.google.com/go/apigeeregistry v0.8.2/go.mod h1:h4v11TDGdeXJDJvImtgK2AFVvMIgGWjSb0HRnBSjcX8=
cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU=
cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI=
cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8=
@@ -116,18 +76,10 @@ cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodC
cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84=
cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A=
cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E=
-cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY=
-cloud.google.com/go/appengine v1.8.2/go.mod h1:WMeJV9oZ51pvclqFN2PqHoGnys7rK0rz6s3Mp6yMvDo=
-cloud.google.com/go/appengine v1.8.3/go.mod h1:2oUPZ1LVZ5EXi+AF1ihNAF+S8JrzQ3till5m9VQkrsk=
-cloud.google.com/go/appengine v1.8.4/go.mod h1:TZ24v+wXBujtkK77CXCpjZbnuTvsFNT41MUaZ28D6vg=
cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4=
cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0=
cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY=
cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k=
-cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg=
-cloud.google.com/go/area120 v0.8.2/go.mod h1:a5qfo+x77SRLXnCynFWPUZhnZGeSgvQ+Y0v1kSItkh4=
-cloud.google.com/go/area120 v0.8.3/go.mod h1:5zj6pMzVTH+SVHljdSKC35sriR/CVvQZzG/Icdyriw0=
-cloud.google.com/go/area120 v0.8.4/go.mod h1:jfawXjxf29wyBXr48+W+GyX/f8fflxp642D/bb9v68M=
cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ=
cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk=
cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0=
@@ -136,11 +88,6 @@ cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1
cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ=
cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI=
cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08=
-cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E=
-cloud.google.com/go/artifactregistry v1.14.2/go.mod h1:Xk+QbsKEb0ElmyeMfdHAey41B+qBq3q5R5f5xD4XT3U=
-cloud.google.com/go/artifactregistry v1.14.3/go.mod h1:A2/E9GXnsyXl7GUvQ/2CjHA+mVRoWAXC0brg2os+kNI=
-cloud.google.com/go/artifactregistry v1.14.4/go.mod h1:SJJcZTMv6ce0LDMUnihCN7WSrI+kBSFV0KIKo8S8aYU=
-cloud.google.com/go/artifactregistry v1.14.6/go.mod h1:np9LSFotNWHcjnOgh8UVK0RFPCTUGbO0ve3384xyHfE=
cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o=
cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s=
cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0=
@@ -149,56 +96,31 @@ cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAt
cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo=
cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg=
cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw=
-cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ=
-cloud.google.com/go/asset v1.15.0/go.mod h1:tpKafV6mEut3+vN9ScGvCHXHj7FALFVta+okxFECHcg=
-cloud.google.com/go/asset v1.15.1/go.mod h1:yX/amTvFWRpp5rcFq6XbCxzKT8RJUam1UoboE179jU4=
-cloud.google.com/go/asset v1.15.2/go.mod h1:B6H5tclkXvXz7PD22qCA2TDxSVQfasa3iDlM89O2NXs=
-cloud.google.com/go/asset v1.15.3/go.mod h1:yYLfUD4wL4X589A9tYrv4rFrba0QlDeag0CMcM5ggXU=
cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY=
cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw=
cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI=
cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo=
cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0=
cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E=
-cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0=
-cloud.google.com/go/assuredworkloads v1.11.2/go.mod h1:O1dfr+oZJMlE6mw0Bp0P1KZSlj5SghMBvTpZqIcUAW4=
-cloud.google.com/go/assuredworkloads v1.11.3/go.mod h1:vEjfTKYyRUaIeA0bsGJceFV2JKpVRgyG2op3jfa59Zs=
-cloud.google.com/go/assuredworkloads v1.11.4/go.mod h1:4pwwGNwy1RP0m+y12ef3Q/8PaiWrIDQ6nD2E8kvWI9U=
+cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg=
+cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro=
+cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4=
+cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0=
cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8=
cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8=
cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM=
cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU=
-cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE=
-cloud.google.com/go/automl v1.13.2/go.mod h1:gNY/fUmDEN40sP8amAX3MaXkxcqPIn7F1UIIPZpy4Mg=
-cloud.google.com/go/automl v1.13.3/go.mod h1:Y8KwvyAZFOsMAPqUCfNu1AyclbC6ivCUF/MTwORymyY=
-cloud.google.com/go/automl v1.13.4/go.mod h1:ULqwX/OLZ4hBVfKQaMtxMSTlPx0GqGbWN8uA/1EqCP8=
cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc=
cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI=
cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss=
-cloud.google.com/go/baremetalsolution v1.1.1/go.mod h1:D1AV6xwOksJMV4OSlWHtWuFNZZYujJknMAP4Qa27QIA=
-cloud.google.com/go/baremetalsolution v1.2.0/go.mod h1:68wi9AwPYkEWIUT4SvSGS9UJwKzNpshjHsH4lzk8iOw=
-cloud.google.com/go/baremetalsolution v1.2.1/go.mod h1:3qKpKIw12RPXStwQXcbhfxVj1dqQGEvcmA+SX/mUR88=
-cloud.google.com/go/baremetalsolution v1.2.2/go.mod h1:O5V6Uu1vzVelYahKfwEWRMaS3AbCkeYHy3145s1FkhM=
-cloud.google.com/go/baremetalsolution v1.2.3/go.mod h1:/UAQ5xG3faDdy180rCUv47e0jvpp3BFxT+Cl0PFjw5g=
cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE=
cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE=
cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g=
-cloud.google.com/go/batch v1.3.1/go.mod h1:VguXeQKXIYaeeIYbuozUmBR13AfL4SJP7IltNPS+A4A=
-cloud.google.com/go/batch v1.4.1/go.mod h1:KdBmDD61K0ovcxoRHGrN6GmOBWeAOyCgKD0Mugx4Fkk=
-cloud.google.com/go/batch v1.5.0/go.mod h1:KdBmDD61K0ovcxoRHGrN6GmOBWeAOyCgKD0Mugx4Fkk=
-cloud.google.com/go/batch v1.5.1/go.mod h1:RpBuIYLkQu8+CWDk3dFD/t/jOCGuUpkpX+Y0n1Xccs8=
-cloud.google.com/go/batch v1.6.1/go.mod h1:urdpD13zPe6YOK+6iZs/8/x2VBRofvblLpx0t57vM98=
-cloud.google.com/go/batch v1.6.3/go.mod h1:J64gD4vsNSA2O5TtDB5AAux3nJ9iV8U3ilg3JDBYejU=
cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4=
cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8=
cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM=
cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU=
-cloud.google.com/go/beyondcorp v0.6.1/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4=
-cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4=
-cloud.google.com/go/beyondcorp v1.0.1/go.mod h1:zl/rWWAFVeV+kx+X2Javly7o1EIQThU4WlkynffL/lk=
-cloud.google.com/go/beyondcorp v1.0.2/go.mod h1:m8cpG7caD+5su+1eZr+TSvF6r21NdLJk4f9u4SP2Ntc=
-cloud.google.com/go/beyondcorp v1.0.3/go.mod h1:HcBvnEd7eYr+HGDd5ZbuVmBYX019C6CEXBonXbCVwJo=
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=
@@ -212,68 +134,32 @@ cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/Zur
cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac=
cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q=
cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU=
-cloud.google.com/go/bigquery v1.52.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4=
-cloud.google.com/go/bigquery v1.53.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4=
-cloud.google.com/go/bigquery v1.55.0/go.mod h1:9Y5I3PN9kQWuid6183JFhOGOW3GcirA5LpsKCUn+2ec=
-cloud.google.com/go/bigquery v1.56.0/go.mod h1:KDcsploXTEY7XT3fDQzMUZlpQLHzE4itubHrnmhUrZA=
-cloud.google.com/go/bigquery v1.57.1/go.mod h1:iYzC0tGVWt1jqSzBHqCr3lrRn0u13E8e+AqowBsDgug=
cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY=
cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s=
cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI=
cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y=
cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss=
cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc=
-cloud.google.com/go/billing v1.16.0/go.mod h1:y8vx09JSSJG02k5QxbycNRrN7FGZB6F3CAcgum7jvGA=
-cloud.google.com/go/billing v1.17.0/go.mod h1:Z9+vZXEq+HwH7bhJkyI4OQcR6TSbeMrjlpEjO2vzY64=
-cloud.google.com/go/billing v1.17.1/go.mod h1:Z9+vZXEq+HwH7bhJkyI4OQcR6TSbeMrjlpEjO2vzY64=
-cloud.google.com/go/billing v1.17.2/go.mod h1:u/AdV/3wr3xoRBk5xvUzYMS1IawOAPwQMuHgHMdljDg=
-cloud.google.com/go/billing v1.17.3/go.mod h1:z83AkoZ7mZwBGT3yTnt6rSGI1OOsHSIi6a5M3mJ8NaU=
-cloud.google.com/go/billing v1.17.4/go.mod h1:5DOYQStCxquGprqfuid/7haD7th74kyMBHkjO/OvDtk=
cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM=
cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI=
cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0=
cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk=
cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q=
-cloud.google.com/go/binaryauthorization v1.6.1/go.mod h1:TKt4pa8xhowwffiBmbrbcxijJRZED4zrqnwZ1lKH51U=
-cloud.google.com/go/binaryauthorization v1.7.0/go.mod h1:Zn+S6QqTMn6odcMU1zDZCJxPjU2tZPV1oDl45lWY154=
-cloud.google.com/go/binaryauthorization v1.7.1/go.mod h1:GTAyfRWYgcbsP3NJogpV3yeunbUIjx2T9xVeYovtURE=
-cloud.google.com/go/binaryauthorization v1.7.2/go.mod h1:kFK5fQtxEp97m92ziy+hbu+uKocka1qRRL8MVJIgjv0=
-cloud.google.com/go/binaryauthorization v1.7.3/go.mod h1:VQ/nUGRKhrStlGr+8GMS8f6/vznYLkdK5vaKfdCIpvU=
cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg=
cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590=
cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8=
-cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI=
-cloud.google.com/go/certificatemanager v1.7.2/go.mod h1:15SYTDQMd00kdoW0+XY5d9e+JbOPjp24AvF48D8BbcQ=
-cloud.google.com/go/certificatemanager v1.7.3/go.mod h1:T/sZYuC30PTag0TLo28VedIRIj1KPGcOQzjWAptHa00=
-cloud.google.com/go/certificatemanager v1.7.4/go.mod h1:FHAylPe/6IIKuaRmHbjbdLhGhVQ+CWHSD5Jq0k4+cCE=
cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk=
cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk=
cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE=
cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU=
-cloud.google.com/go/channel v1.16.0/go.mod h1:eN/q1PFSl5gyu0dYdmxNXscY/4Fi7ABmeHCJNf/oHmc=
-cloud.google.com/go/channel v1.17.0/go.mod h1:RpbhJsGi/lXWAUM1eF4IbQGbsfVlg2o8Iiy2/YLfVT0=
-cloud.google.com/go/channel v1.17.1/go.mod h1:xqfzcOZAcP4b/hUDH0GkGg1Sd5to6di1HOJn/pi5uBQ=
-cloud.google.com/go/channel v1.17.2/go.mod h1:aT2LhnftnyfQceFql5I/mP8mIbiiJS4lWqgXA815zMk=
-cloud.google.com/go/channel v1.17.3/go.mod h1:QcEBuZLGGrUMm7kNj9IbU1ZfmJq2apotsV83hbxX7eE=
cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U=
cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA=
cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M=
cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg=
cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s=
-cloud.google.com/go/cloudbuild v1.10.1/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU=
-cloud.google.com/go/cloudbuild v1.13.0/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU=
-cloud.google.com/go/cloudbuild v1.14.0/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU=
-cloud.google.com/go/cloudbuild v1.14.1/go.mod h1:K7wGc/3zfvmYWOWwYTgF/d/UVJhS4pu+HAy7PL7mCsU=
-cloud.google.com/go/cloudbuild v1.14.2/go.mod h1:Bn6RO0mBYk8Vlrt+8NLrru7WXlQ9/RDWz2uo5KG1/sg=
-cloud.google.com/go/cloudbuild v1.14.3/go.mod h1:eIXYWmRt3UtggLnFGx4JvXcMj4kShhVzGndL1LwleEM=
cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM=
cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk=
cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA=
-cloud.google.com/go/clouddms v1.6.1/go.mod h1:Ygo1vL52Ov4TBZQquhz5fiw2CQ58gvu+PlS6PVXCpZI=
-cloud.google.com/go/clouddms v1.7.0/go.mod h1:MW1dC6SOtI/tPNCciTsXtsGNEM0i0OccykPvv3hiYeM=
-cloud.google.com/go/clouddms v1.7.1/go.mod h1:o4SR8U95+P7gZ/TX+YbJxehOCsM+fe6/brlrFquiszk=
-cloud.google.com/go/clouddms v1.7.2/go.mod h1:Rk32TmWmHo64XqDvW7jgkFQet1tUKNVzs7oajtJT3jU=
-cloud.google.com/go/clouddms v1.7.3/go.mod h1:fkN2HQQNUYInAU3NQ3vRLkV2iWs8lIdmBKOx4nrL6Hc=
cloud.google.com/go/cloudsqlconn v1.4.3 h1:/WYFbB1NtMtoMxCbqpzzTFPDkxxlLTPme390KEGaEPc=
cloud.google.com/go/cloudsqlconn v1.4.3/go.mod h1:QL3tuStVOO70txb3rs4G8j5uMfo5ztZii8K3oGD3VYA=
cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY=
@@ -282,11 +168,6 @@ cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/
cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI=
cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y=
cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs=
-cloud.google.com/go/cloudtasks v1.11.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM=
-cloud.google.com/go/cloudtasks v1.12.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM=
-cloud.google.com/go/cloudtasks v1.12.2/go.mod h1:A7nYkjNlW2gUoROg1kvJrQGhJP/38UaWwsnuBDOBVUk=
-cloud.google.com/go/cloudtasks v1.12.3/go.mod h1:GPVXhIOSGEaR+3xT4Fp72ScI+HjHffSS4B8+BaBB5Ys=
-cloud.google.com/go/cloudtasks v1.12.4/go.mod h1:BEPu0Gtt2dU6FxZHNqqNdGqIG86qyWKBPGnsb7udGY0=
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
@@ -302,48 +183,24 @@ cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
-cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI=
-cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
-cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
-cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
-cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78=
-cloud.google.com/go/compute v1.23.2/go.mod h1:JJ0atRC0J/oWYiiVBmsSsrRnh92DhZPG4hFDcR04Rns=
-cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
-cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
-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/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
+cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
-cloud.google.com/go/contactcenterinsights v1.9.1/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM=
-cloud.google.com/go/contactcenterinsights v1.10.0/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM=
-cloud.google.com/go/contactcenterinsights v1.11.0/go.mod h1:hutBdImE4XNZ1NV4vbPJKSFOnQruhC5Lj9bZqWMTKiU=
-cloud.google.com/go/contactcenterinsights v1.11.1/go.mod h1:FeNP3Kg8iteKM80lMwSk3zZZKVxr+PGnAId6soKuXwE=
-cloud.google.com/go/contactcenterinsights v1.11.2/go.mod h1:A9PIR5ov5cRcd28KlDbmmXE8Aay+Gccer2h4wzkYFso=
-cloud.google.com/go/contactcenterinsights v1.11.3/go.mod h1:HHX5wrz5LHVAwfI2smIotQG9x8Qd6gYilaHcLLLmNis=
cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg=
cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo=
cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4=
cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM=
cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA=
-cloud.google.com/go/container v1.22.1/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4=
-cloud.google.com/go/container v1.24.0/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4=
-cloud.google.com/go/container v1.26.0/go.mod h1:YJCmRet6+6jnYYRS000T6k0D0xUXQgBSaJ7VwI8FBj4=
-cloud.google.com/go/container v1.26.1/go.mod h1:5smONjPRUxeEpDG7bMKWfDL4sauswqEtnBK1/KKpR04=
-cloud.google.com/go/container v1.26.2/go.mod h1:YlO84xCt5xupVbLaMY4s3XNE79MUJ+49VmkInr6HvF4=
-cloud.google.com/go/container v1.27.1/go.mod h1:b1A1gJeTBXVLQ6GGw9/9M4FG94BEGsqJ5+t4d/3N7O4=
cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4=
cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI=
cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s=
-cloud.google.com/go/containeranalysis v0.10.1/go.mod h1:Ya2jiILITMY68ZLPaogjmOMNkwsDrWBSTyBubGXO7j0=
-cloud.google.com/go/containeranalysis v0.11.0/go.mod h1:4n2e99ZwpGxpNcz+YsFT1dfOHPQFGcAC8FN2M2/ne/U=
-cloud.google.com/go/containeranalysis v0.11.1/go.mod h1:rYlUOM7nem1OJMKwE1SadufX0JP3wnXj844EtZAwWLY=
-cloud.google.com/go/containeranalysis v0.11.2/go.mod h1:xibioGBC1MD2j4reTyV1xY1/MvKaz+fyM9ENWhmIeP8=
-cloud.google.com/go/containeranalysis v0.11.3/go.mod h1:kMeST7yWFQMGjiG9K7Eov+fPNQcGhb8mXj/UcTiWw9U=
cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0=
cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs=
cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc=
@@ -352,98 +209,44 @@ cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOX
cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M=
cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0=
cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8=
-cloud.google.com/go/datacatalog v1.14.0/go.mod h1:h0PrGtlihoutNMp/uvwhawLQ9+c63Kz65UFqh49Yo+E=
-cloud.google.com/go/datacatalog v1.14.1/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4=
-cloud.google.com/go/datacatalog v1.16.0/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4=
-cloud.google.com/go/datacatalog v1.17.1/go.mod h1:nCSYFHgtxh2MiEktWIz71s/X+7ds/UT9kp0PC7waCzE=
-cloud.google.com/go/datacatalog v1.18.0/go.mod h1:nCSYFHgtxh2MiEktWIz71s/X+7ds/UT9kp0PC7waCzE=
-cloud.google.com/go/datacatalog v1.18.1/go.mod h1:TzAWaz+ON1tkNr4MOcak8EBHX7wIRX/gZKM+yTVsv+A=
-cloud.google.com/go/datacatalog v1.18.2/go.mod h1:SPVgWW2WEMuWHA+fHodYjmxPiMqcOiWfhc9OD5msigk=
-cloud.google.com/go/datacatalog v1.18.3/go.mod h1:5FR6ZIF8RZrtml0VUao22FxhdjkoG+a0866rEnObryM=
cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM=
cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ=
cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE=
-cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw=
-cloud.google.com/go/dataflow v0.9.2/go.mod h1:vBfdBZ/ejlTaYIGB3zB4T08UshH70vbtZeMD+urnUSo=
-cloud.google.com/go/dataflow v0.9.3/go.mod h1:HI4kMVjcHGTs3jTHW/kv3501YW+eloiJSLxkJa/vqFE=
-cloud.google.com/go/dataflow v0.9.4/go.mod h1:4G8vAkHYCSzU8b/kmsoR2lWyHJD85oMJPHMtan40K8w=
cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo=
cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE=
cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0=
cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA=
cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE=
-cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M=
-cloud.google.com/go/dataform v0.8.2/go.mod h1:X9RIqDs6NbGPLR80tnYoPNiO1w0wenKTb8PxxlhTMKM=
-cloud.google.com/go/dataform v0.8.3/go.mod h1:8nI/tvv5Fso0drO3pEjtowz58lodx8MVkdV2q0aPlqg=
-cloud.google.com/go/dataform v0.9.1/go.mod h1:pWTg+zGQ7i16pyn0bS1ruqIE91SdL2FDMvEYu/8oQxs=
cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38=
cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w=
cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8=
-cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI=
-cloud.google.com/go/datafusion v1.7.2/go.mod h1:62K2NEC6DRlpNmI43WHMWf9Vg/YvN6QVi8EVwifElI0=
-cloud.google.com/go/datafusion v1.7.3/go.mod h1:eoLt1uFXKGBq48jy9LZ+Is8EAVLnmn50lNncLzwYokE=
-cloud.google.com/go/datafusion v1.7.4/go.mod h1:BBs78WTOLYkT4GVZIXQCZT3GFpkpDN4aBY4NDX/jVlM=
cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I=
cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ=
cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM=
-cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY=
-cloud.google.com/go/datalabeling v0.8.2/go.mod h1:cyDvGHuJWu9U/cLDA7d8sb9a0tWLEletStu2sTmg3BE=
-cloud.google.com/go/datalabeling v0.8.3/go.mod h1:tvPhpGyS/V7lqjmb3V0TaDdGvhzgR1JoW7G2bpi2UTI=
-cloud.google.com/go/datalabeling v0.8.4/go.mod h1:Z1z3E6LHtffBGrNUkKwbwbDxTiXEApLzIgmymj8A3S8=
cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA=
cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A=
cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ=
cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs=
-cloud.google.com/go/dataplex v1.8.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE=
-cloud.google.com/go/dataplex v1.9.0/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE=
-cloud.google.com/go/dataplex v1.9.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE=
-cloud.google.com/go/dataplex v1.10.1/go.mod h1:1MzmBv8FvjYfc7vDdxhnLFNskikkB+3vl475/XdCDhs=
-cloud.google.com/go/dataplex v1.10.2/go.mod h1:xdC8URdTrCrZMW6keY779ZT1cTOfV8KEPNsw+LTRT1Y=
-cloud.google.com/go/dataplex v1.11.1/go.mod h1:mHJYQQ2VEJHsyoC0OdNyy988DvEbPhqFs5OOLffLX0c=
cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s=
cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI=
cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4=
-cloud.google.com/go/dataproc/v2 v2.0.1/go.mod h1:7Ez3KRHdFGcfY7GcevBbvozX+zyWGcwLJvvAMwCaoZ4=
-cloud.google.com/go/dataproc/v2 v2.2.0/go.mod h1:lZR7AQtwZPvmINx5J87DSOOpTfof9LVZju6/Qo4lmcY=
-cloud.google.com/go/dataproc/v2 v2.2.1/go.mod h1:QdAJLaBjh+l4PVlVZcmrmhGccosY/omC1qwfQ61Zv/o=
-cloud.google.com/go/dataproc/v2 v2.2.2/go.mod h1:aocQywVmQVF4i8CL740rNI/ZRpsaaC1Wh2++BJ7HEJ4=
-cloud.google.com/go/dataproc/v2 v2.2.3/go.mod h1:G5R6GBc9r36SXv/RtZIVfB8SipI+xVn0bX5SxUzVYbY=
cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo=
cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA=
cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c=
-cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8=
-cloud.google.com/go/dataqna v0.8.2/go.mod h1:KNEqgx8TTmUipnQsScOoDpq/VlXVptUqVMZnt30WAPs=
-cloud.google.com/go/dataqna v0.8.3/go.mod h1:wXNBW2uvc9e7Gl5k8adyAMnLush1KVV6lZUhB+rqNu4=
-cloud.google.com/go/dataqna v0.8.4/go.mod h1:mySRKjKg5Lz784P6sCov3p1QD+RZQONRMRjzGNcFd0c=
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/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM=
cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c=
-cloud.google.com/go/datastore v1.12.0/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70=
-cloud.google.com/go/datastore v1.12.1/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70=
-cloud.google.com/go/datastore v1.13.0/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70=
-cloud.google.com/go/datastore v1.14.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8=
-cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8=
cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo=
cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ=
cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g=
cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4=
cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs=
cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww=
-cloud.google.com/go/datastream v1.9.1/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q=
-cloud.google.com/go/datastream v1.10.0/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q=
-cloud.google.com/go/datastream v1.10.1/go.mod h1:7ngSYwnw95YFyTd5tOGBxHlOZiL+OtpjheqU7t2/s/c=
-cloud.google.com/go/datastream v1.10.2/go.mod h1:W42TFgKAs/om6x/CdXX5E4oiAsKlH+e8MTGy81zdYt0=
-cloud.google.com/go/datastream v1.10.3/go.mod h1:YR0USzgjhqA/Id0Ycu1VvZe8hEWwrkjuXrGbzeDOSEA=
cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c=
cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s=
cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI=
cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ=
-cloud.google.com/go/deploy v1.11.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g=
-cloud.google.com/go/deploy v1.13.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g=
-cloud.google.com/go/deploy v1.13.1/go.mod h1:8jeadyLkH9qu9xgO3hVWw8jVr29N1mnW42gRJT8GY6g=
-cloud.google.com/go/deploy v1.14.1/go.mod h1:N8S0b+aIHSEeSr5ORVoC0+/mOPUysVt8ae4QkZYolAw=
-cloud.google.com/go/deploy v1.14.2/go.mod h1:e5XOUI5D+YGldyLNZ21wbp9S8otJbBE4i88PtO9x/2g=
cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4=
cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0=
cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8=
@@ -452,79 +255,35 @@ cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFM
cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM=
cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4=
cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE=
-cloud.google.com/go/dialogflow v1.38.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4=
-cloud.google.com/go/dialogflow v1.40.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4=
-cloud.google.com/go/dialogflow v1.43.0/go.mod h1:pDUJdi4elL0MFmt1REMvFkdsUTYSHq+rTCS8wg0S3+M=
-cloud.google.com/go/dialogflow v1.44.0/go.mod h1:pDUJdi4elL0MFmt1REMvFkdsUTYSHq+rTCS8wg0S3+M=
-cloud.google.com/go/dialogflow v1.44.1/go.mod h1:n/h+/N2ouKOO+rbe/ZnI186xImpqvCVj2DdsWS/0EAk=
-cloud.google.com/go/dialogflow v1.44.2/go.mod h1:QzFYndeJhpVPElnFkUXxdlptx0wPnBWLCBT9BvtC3/c=
-cloud.google.com/go/dialogflow v1.44.3/go.mod h1:mHly4vU7cPXVweuB5R0zsYKPMzy240aQdAu06SqBbAQ=
cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM=
cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q=
cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4=
-cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI=
-cloud.google.com/go/dlp v1.10.2/go.mod h1:ZbdKIhcnyhILgccwVDzkwqybthh7+MplGC3kZVZsIOQ=
-cloud.google.com/go/dlp v1.10.3/go.mod h1:iUaTc/ln8I+QT6Ai5vmuwfw8fqTk2kaz0FvCwhLCom0=
-cloud.google.com/go/dlp v1.11.1/go.mod h1:/PA2EnioBeXTL/0hInwgj0rfsQb3lpE3R8XUJxqUNKI=
cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU=
cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU=
cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k=
cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4=
cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM=
cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs=
-cloud.google.com/go/documentai v1.20.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E=
-cloud.google.com/go/documentai v1.22.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E=
-cloud.google.com/go/documentai v1.22.1/go.mod h1:LKs22aDHbJv7ufXuPypzRO7rG3ALLJxzdCXDPutw4Qc=
-cloud.google.com/go/documentai v1.23.0/go.mod h1:LKs22aDHbJv7ufXuPypzRO7rG3ALLJxzdCXDPutw4Qc=
-cloud.google.com/go/documentai v1.23.2/go.mod h1:Q/wcRT+qnuXOpjAkvOV4A+IeQl04q2/ReT7SSbytLSo=
-cloud.google.com/go/documentai v1.23.4/go.mod h1:4MYAaEMnADPN1LPN5xboDR5QVB6AgsaxgFdJhitlE2Y=
-cloud.google.com/go/documentai v1.23.5/go.mod h1:ghzBsyVTiVdkfKaUCum/9bGBEyBjDO4GfooEcYKhN+g=
cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y=
cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg=
cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE=
-cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE=
-cloud.google.com/go/domains v0.9.2/go.mod h1:3YvXGYzZG1Temjbk7EyGCuGGiXHJwVNmwIf+E/cUp5I=
-cloud.google.com/go/domains v0.9.3/go.mod h1:29k66YNDLDY9LCFKpGFeh6Nj9r62ZKm5EsUJxAl84KU=
-cloud.google.com/go/domains v0.9.4/go.mod h1:27jmJGShuXYdUNjyDG0SodTfT5RwLi7xmH334Gvi3fY=
cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk=
cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w=
cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc=
cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY=
-cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk=
-cloud.google.com/go/edgecontainer v1.1.2/go.mod h1:wQRjIzqxEs9e9wrtle4hQPSR1Y51kqN75dgF7UllZZ4=
-cloud.google.com/go/edgecontainer v1.1.3/go.mod h1:Ll2DtIABzEfaxaVSbwj3QHFaOOovlDFiWVDu349jSsA=
-cloud.google.com/go/edgecontainer v1.1.4/go.mod h1:AvFdVuZuVGdgaE5YvlL1faAoa1ndRR/5XhXZvPBHbsE=
cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU=
cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI=
cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8=
cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M=
-cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4=
-cloud.google.com/go/essentialcontacts v1.6.3/go.mod h1:yiPCD7f2TkP82oJEFXFTou8Jl8L6LBRPeBEkTaO0Ggo=
-cloud.google.com/go/essentialcontacts v1.6.4/go.mod h1:iju5Vy3d9tJUg0PYMd1nHhjV7xoCXaOAVabrwLaPBEM=
-cloud.google.com/go/essentialcontacts v1.6.5/go.mod h1:jjYbPzw0x+yglXC890l6ECJWdYeZ5dlYACTFL0U/VuM=
cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc=
cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw=
cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw=
cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY=
-cloud.google.com/go/eventarc v1.12.1/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI=
-cloud.google.com/go/eventarc v1.13.0/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI=
-cloud.google.com/go/eventarc v1.13.1/go.mod h1:EqBxmGHFrruIara4FUQ3RHlgfCn7yo1HYsu2Hpt/C3Y=
-cloud.google.com/go/eventarc v1.13.2/go.mod h1:X9A80ShVu19fb4e5sc/OLV7mpFUKZMwfJFeeWhcIObM=
-cloud.google.com/go/eventarc v1.13.3/go.mod h1:RWH10IAZIRcj1s/vClXkBgMHwh59ts7hSWcqD3kaclg=
cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w=
cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI=
cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs=
cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg=
-cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4=
-cloud.google.com/go/filestore v1.7.2/go.mod h1:TYOlyJs25f/omgj+vY7/tIG/E7BX369triSPzE4LdgE=
-cloud.google.com/go/filestore v1.7.3/go.mod h1:Qp8WaEERR3cSkxToxFPHh/b8AACkSut+4qlCjAmKTV0=
-cloud.google.com/go/filestore v1.7.4/go.mod h1:S5JCxIbFjeBhWMTfIYH2Jx24J6BqjwpkkPl+nBA5DlI=
-cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE=
-cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4=
-cloud.google.com/go/firestore v1.12.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4=
-cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8=
-cloud.google.com/go/firestore v1.14.0/go.mod h1:96MVaHLsEhbvkBEdZgfN+AS/GIkco1LRpH9Xp9YZfzQ=
cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk=
cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg=
cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY=
@@ -532,56 +291,28 @@ cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5Uwt
cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw=
cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA=
cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c=
-cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE=
-cloud.google.com/go/functions v1.15.2/go.mod h1:CHAjtcR6OU4XF2HuiVeriEdELNcnvRZSk1Q8RMqy4lE=
-cloud.google.com/go/functions v1.15.3/go.mod h1:r/AMHwBheapkkySEhiZYLDBwVJCdlRwsm4ieJu35/Ug=
-cloud.google.com/go/functions v1.15.4/go.mod h1:CAsTc3VlRMVvx+XqXxKqVevguqJpnVip4DdonFsX28I=
cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM=
cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA=
cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w=
cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM=
cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0=
-cloud.google.com/go/gaming v1.10.1/go.mod h1:XQQvtfP8Rb9Rxnxm5wFVpAp9zCQkJi2bLIb7iHGwB3s=
cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60=
cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo=
cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg=
-cloud.google.com/go/gkebackup v1.3.0/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU=
-cloud.google.com/go/gkebackup v1.3.1/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU=
-cloud.google.com/go/gkebackup v1.3.2/go.mod h1:OMZbXzEJloyXMC7gqdSB+EOEQ1AKcpGYvO3s1ec5ixk=
-cloud.google.com/go/gkebackup v1.3.3/go.mod h1:eMk7/wVV5P22KBakhQnJxWSVftL1p4VBFLpv0kIft7I=
-cloud.google.com/go/gkebackup v1.3.4/go.mod h1:gLVlbM8h/nHIs09ns1qx3q3eaXcGSELgNu1DWXYz1HI=
cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o=
cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A=
cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw=
-cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw=
-cloud.google.com/go/gkeconnect v0.8.2/go.mod h1:6nAVhwchBJYgQCXD2pHBFQNiJNyAd/wyxljpaa6ZPrY=
-cloud.google.com/go/gkeconnect v0.8.3/go.mod h1:i9GDTrfzBSUZGCe98qSu1B8YB8qfapT57PenIb820Jo=
-cloud.google.com/go/gkeconnect v0.8.4/go.mod h1:84hZz4UMlDCKl8ifVW8layK4WHlMAFeq8vbzjU0yJkw=
cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0=
cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0=
cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E=
cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw=
-cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY=
-cloud.google.com/go/gkehub v0.14.2/go.mod h1:iyjYH23XzAxSdhrbmfoQdePnlMj2EWcvnR+tHdBQsCY=
-cloud.google.com/go/gkehub v0.14.3/go.mod h1:jAl6WafkHHW18qgq7kqcrXYzN08hXeK/Va3utN8VKg8=
-cloud.google.com/go/gkehub v0.14.4/go.mod h1:Xispfu2MqnnFt8rV/2/3o73SK1snL8s9dYJ9G2oQMfc=
cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA=
cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI=
cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y=
-cloud.google.com/go/gkemulticloud v0.6.1/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw=
-cloud.google.com/go/gkemulticloud v1.0.0/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw=
-cloud.google.com/go/gkemulticloud v1.0.1/go.mod h1:AcrGoin6VLKT/fwZEYuqvVominLriQBCKmbjtnbMjG8=
-cloud.google.com/go/gkemulticloud v1.0.2/go.mod h1:+ee5VXxKb3H1l4LZAcgWB/rvI16VTNTrInWxDjAGsGo=
-cloud.google.com/go/gkemulticloud v1.0.3/go.mod h1:7NpJBN94U6DY1xHIbsDqB2+TFZUfjLUKLjUX8NGLor0=
cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
-cloud.google.com/go/grafeas v0.3.0/go.mod h1:P7hgN24EyONOTMyeJH6DxG4zD7fwiYa5Q6GUgyFSOU8=
cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM=
cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o=
cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo=
-cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY=
-cloud.google.com/go/gsuiteaddons v1.6.2/go.mod h1:K65m9XSgs8hTF3X9nNTPi8IQueljSdYo9F+Mi+s4MyU=
-cloud.google.com/go/gsuiteaddons v1.6.3/go.mod h1:sCFJkZoMrLZT3JTb8uJqgKPNshH2tfXeCwTFRebTq48=
-cloud.google.com/go/gsuiteaddons v1.6.4/go.mod h1:rxtstw7Fx22uLOXBpsvb9DUbC+fiXs7rF4U29KHM/pE=
cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c=
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
@@ -591,39 +322,20 @@ cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGE
cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY=
cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY=
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
-cloud.google.com/go/iam v1.0.1/go.mod h1:yR3tmSL8BcZB4bxByRv2jkSIahVmCtfKZwLYGBalRE8=
-cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
-cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
-cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
-cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE=
-cloud.google.com/go/iam v1.1.4/go.mod h1:l/rg8l1AaA+VFMho/HYx2Vv6xinPSLMF8qfhRPIZ0L8=
-cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI=
-cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
+cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0=
+cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE=
cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk=
cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo=
cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74=
-cloud.google.com/go/iap v1.8.1/go.mod h1:sJCbeqg3mvWLqjZNsI6dfAtbbV1DL2Rl7e1mTyXYREQ=
-cloud.google.com/go/iap v1.9.0/go.mod h1:01OFxd1R+NFrg78S+hoPV5PxEzv22HXaNqUUlmNHFuY=
-cloud.google.com/go/iap v1.9.1/go.mod h1:SIAkY7cGMLohLSdBR25BuIxO+I4fXJiL06IBL7cy/5Q=
-cloud.google.com/go/iap v1.9.2/go.mod h1:GwDTOs047PPSnwRD0Us5FKf4WDRcVvHg1q9WVkKBhdI=
-cloud.google.com/go/iap v1.9.3/go.mod h1:DTdutSZBqkkOm2HEOTBzhZxh2mwwxshfD/h3yofAiCw=
cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM=
cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY=
cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4=
-cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw=
-cloud.google.com/go/ids v1.4.2/go.mod h1:3vw8DX6YddRu9BncxuzMyWn0g8+ooUjI2gslJ7FH3vk=
-cloud.google.com/go/ids v1.4.3/go.mod h1:9CXPqI3GedjmkjbMWCUhMZ2P2N7TUMzAkVXYEH2orYU=
-cloud.google.com/go/ids v1.4.4/go.mod h1:z+WUc2eEl6S/1aZWzwtVNWoSZslgzPxAboS0lZX0HjI=
cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs=
cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g=
cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o=
cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE=
-cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk=
-cloud.google.com/go/iot v1.7.2/go.mod h1:q+0P5zr1wRFpw7/MOgDXrG/HVA+l+cSwdObffkrpnSg=
-cloud.google.com/go/iot v1.7.3/go.mod h1:t8itFchkol4VgNbHnIq9lXoOOtHNR3uAACQMYbN9N4I=
-cloud.google.com/go/iot v1.7.4/go.mod h1:3TWqDVvsddYBG++nHSZmluoCAVGr1hAcabbWZNKEZLk=
cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA=
cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg=
cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0=
@@ -631,205 +343,97 @@ cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4
cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w=
cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24=
cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI=
-cloud.google.com/go/kms v1.11.0/go.mod h1:hwdiYC0xjnWsKQQCQQmIQnS9asjYVSK6jtXm+zFqXLM=
-cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM=
-cloud.google.com/go/kms v1.15.0/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM=
-cloud.google.com/go/kms v1.15.2/go.mod h1:3hopT4+7ooWRCjc2DxgnpESFxhIraaI2IpAVUEhbT/w=
-cloud.google.com/go/kms v1.15.3/go.mod h1:AJdXqHxS2GlPyduM99s9iGqi2nwbviBbhV/hdmt4iOQ=
-cloud.google.com/go/kms v1.15.4/go.mod h1:L3Sdj6QTHK8dfwK5D1JLsAyELsNMnd3tAIwGS4ltKpc=
-cloud.google.com/go/kms v1.15.5/go.mod h1:cU2H5jnp6G2TDpUGZyqTCoy1n16fbubHZjmVXSMtwDI=
-cloud.google.com/go/kms v1.15.6 h1:ktpEMQmsOAYj3VZwH020FcQlm23BVYg8T8O1woG2GcE=
-cloud.google.com/go/kms v1.15.6/go.mod h1:yF75jttnIdHfGBoE51AKsD/Yqf+/jICzB9v1s1acsms=
+cloud.google.com/go/kms v1.17.0 h1:5sFDtixjw5CivNoiiCbtWTQmi7bav3oMO6NeNg2IunQ=
+cloud.google.com/go/kms v1.17.0/go.mod h1:DCMnCF/apA6fZk5Cj4XsD979OyHAqFasPuA5Sd0kGlQ=
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE=
cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8=
cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY=
-cloud.google.com/go/language v1.10.1/go.mod h1:CPp94nsdVNiQEt1CNjF5WkTcisLiHPyIbMhvR8H2AW0=
-cloud.google.com/go/language v1.11.0/go.mod h1:uDx+pFDdAKTY8ehpWbiXyQdz8tDSYLJbQcXsCkjYyvQ=
-cloud.google.com/go/language v1.11.1/go.mod h1:Xyid9MG9WOX3utvDbpX7j3tXDmmDooMyMDqgUVpH17U=
-cloud.google.com/go/language v1.12.1/go.mod h1:zQhalE2QlQIxbKIZt54IASBzmZpN/aDASea5zl1l+J4=
-cloud.google.com/go/language v1.12.2/go.mod h1:9idWapzr/JKXBBQ4lWqVX/hcadxB194ry20m/bTrhWc=
cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08=
cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo=
-cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc=
-cloud.google.com/go/lifesciences v0.9.2/go.mod h1:QHEOO4tDzcSAzeJg7s2qwnLM2ji8IRpQl4p6m5Z9yTA=
-cloud.google.com/go/lifesciences v0.9.3/go.mod h1:gNGBOJV80IWZdkd+xz4GQj4mbqaz737SCLHn2aRhQKM=
-cloud.google.com/go/lifesciences v0.9.4/go.mod h1:bhm64duKhMi7s9jR9WYJYvjAFJwRqNj+Nia7hF0Z7JA=
cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw=
cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M=
-cloud.google.com/go/logging v1.8.1/go.mod h1:TJjR+SimHwuC8MZ9cjByQulAMgni+RkXeI3wwctHJEI=
cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE=
cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc=
cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo=
-cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ=
-cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc=
-cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
-cloud.google.com/go/longrunning v0.5.2/go.mod h1:nqo6DQbNV2pXhGDbDMoN2bWz68MjZUzqv2YttZiveCs=
-cloud.google.com/go/longrunning v0.5.3/go.mod h1:y/0ga59EYu58J6SHmmQOvekvND2qODbu8ywBBW7EK7Y=
-cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg=
-cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI=
+cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU=
+cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng=
cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE=
cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM=
cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA=
-cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak=
-cloud.google.com/go/managedidentities v1.6.2/go.mod h1:5c2VG66eCa0WIq6IylRk3TBW83l161zkFvCj28X7jn8=
-cloud.google.com/go/managedidentities v1.6.3/go.mod h1:tewiat9WLyFN0Fi7q1fDD5+0N4VUoL0SCX0OTCthZq4=
-cloud.google.com/go/managedidentities v1.6.4/go.mod h1:WgyaECfHmF00t/1Uk8Oun3CQ2PGUtjc3e9Alh79wyiM=
cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI=
cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw=
cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY=
-cloud.google.com/go/maps v1.3.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s=
-cloud.google.com/go/maps v1.4.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s=
-cloud.google.com/go/maps v1.4.1/go.mod h1:BxSa0BnW1g2U2gNdbq5zikLlHUuHW0GFWh7sgML2kIY=
-cloud.google.com/go/maps v1.5.1/go.mod h1:NPMZw1LJwQZYCfz4y+EIw+SI+24A4bpdFJqdKVr0lt4=
-cloud.google.com/go/maps v1.6.1/go.mod h1:4+buOHhYXFBp58Zj/K+Lc1rCmJssxxF4pJ5CJnhdz18=
cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4=
cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w=
cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I=
-cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig=
-cloud.google.com/go/mediatranslation v0.8.2/go.mod h1:c9pUaDRLkgHRx3irYE5ZC8tfXGrMYwNZdmDqKMSfFp8=
-cloud.google.com/go/mediatranslation v0.8.3/go.mod h1:F9OnXTy336rteOEywtY7FOqCk+J43o2RF638hkOQl4Y=
-cloud.google.com/go/mediatranslation v0.8.4/go.mod h1:9WstgtNVAdN53m6TQa5GjIjLqKQPXe74hwSCxUP6nj4=
cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE=
cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM=
cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA=
cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY=
cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM=
-cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA=
-cloud.google.com/go/memcache v1.10.2/go.mod h1:f9ZzJHLBrmd4BkguIAa/l/Vle6uTHzHokdnzSWOdQ6A=
-cloud.google.com/go/memcache v1.10.3/go.mod h1:6z89A41MT2DVAW0P4iIRdu5cmRTsbsFn4cyiIx8gbwo=
-cloud.google.com/go/memcache v1.10.4/go.mod h1:v/d8PuC8d1gD6Yn5+I3INzLR01IDn0N4Ym56RgikSI0=
cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY=
cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s=
cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8=
cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI=
cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo=
-cloud.google.com/go/metastore v1.11.1/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA=
-cloud.google.com/go/metastore v1.12.0/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA=
-cloud.google.com/go/metastore v1.13.0/go.mod h1:URDhpG6XLeh5K+Glq0NOt74OfrPKTwS62gEPZzb5SOk=
-cloud.google.com/go/metastore v1.13.1/go.mod h1:IbF62JLxuZmhItCppcIfzBBfUFq0DIB9HPDoLgWrVOU=
-cloud.google.com/go/metastore v1.13.2/go.mod h1:KS59dD+unBji/kFebVp8XU/quNSyo8b6N6tPGspKszA=
-cloud.google.com/go/metastore v1.13.3/go.mod h1:K+wdjXdtkdk7AQg4+sXS8bRrQa9gcOr+foOMF2tqINE=
cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk=
cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4=
cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w=
cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw=
-cloud.google.com/go/monitoring v1.15.1/go.mod h1:lADlSAlFdbqQuwwpaImhsJXu1QSdd3ojypXrFSMr2rM=
-cloud.google.com/go/monitoring v1.16.0/go.mod h1:Ptp15HgAyM1fNICAojDMoNc/wUmn67mLHQfyqbw+poY=
-cloud.google.com/go/monitoring v1.16.1/go.mod h1:6HsxddR+3y9j+o/cMJH6q/KJ/CBTvM/38L/1m7bTRJ4=
-cloud.google.com/go/monitoring v1.16.2/go.mod h1:B44KGwi4ZCF8Rk/5n+FWeispDXoKSk9oss2QNlXJBgc=
-cloud.google.com/go/monitoring v1.16.3/go.mod h1:KwSsX5+8PnXv5NJnICZzW2R8pWTis8ypC4zmdRD63Tw=
-cloud.google.com/go/monitoring v1.17.0 h1:blrdvF0MkPPivSO041ihul7rFMhXdVp8Uq7F59DKXTU=
-cloud.google.com/go/monitoring v1.17.0/go.mod h1:KwSsX5+8PnXv5NJnICZzW2R8pWTis8ypC4zmdRD63Tw=
+cloud.google.com/go/monitoring v1.19.0 h1:NCXf8hfQi+Kmr56QJezXRZ6GPb80ZI7El1XztyUuLQI=
+cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw=
cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA=
cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o=
cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM=
cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8=
cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E=
cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM=
-cloud.google.com/go/networkconnectivity v1.12.1/go.mod h1:PelxSWYM7Sh9/guf8CFhi6vIqf19Ir/sbfZRUwXh92E=
-cloud.google.com/go/networkconnectivity v1.13.0/go.mod h1:SAnGPes88pl7QRLUen2HmcBSE9AowVAcdug8c0RSBFk=
-cloud.google.com/go/networkconnectivity v1.14.0/go.mod h1:SAnGPes88pl7QRLUen2HmcBSE9AowVAcdug8c0RSBFk=
-cloud.google.com/go/networkconnectivity v1.14.1/go.mod h1:LyGPXR742uQcDxZ/wv4EI0Vu5N6NKJ77ZYVnDe69Zug=
-cloud.google.com/go/networkconnectivity v1.14.2/go.mod h1:5UFlwIisZylSkGG1AdwK/WZUaoz12PKu6wODwIbFzJo=
-cloud.google.com/go/networkconnectivity v1.14.3/go.mod h1:4aoeFdrJpYEXNvrnfyD5kIzs8YtHg945Og4koAjHQek=
cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8=
cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4=
cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY=
-cloud.google.com/go/networkmanagement v1.8.0/go.mod h1:Ho/BUGmtyEqrttTgWEe7m+8vDdK74ibQc+Be0q7Fof0=
-cloud.google.com/go/networkmanagement v1.9.0/go.mod h1:UTUaEU9YwbCAhhz3jEOHr+2/K/MrBk2XxOLS89LQzFw=
-cloud.google.com/go/networkmanagement v1.9.1/go.mod h1:CCSYgrQQvW73EJawO2QamemYcOb57LvrDdDU51F0mcI=
-cloud.google.com/go/networkmanagement v1.9.2/go.mod h1:iDGvGzAoYRghhp4j2Cji7sF899GnfGQcQRQwgVOWnDw=
-cloud.google.com/go/networkmanagement v1.9.3/go.mod h1:y7WMO1bRLaP5h3Obm4tey+NquUvB93Co1oh4wpL+XcU=
cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ=
cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU=
cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k=
cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU=
-cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ=
-cloud.google.com/go/networksecurity v0.9.2/go.mod h1:jG0SeAttWzPMUILEHDUvFYdQTl8L/E/KC8iZDj85lEI=
-cloud.google.com/go/networksecurity v0.9.3/go.mod h1:l+C0ynM6P+KV9YjOnx+kk5IZqMSLccdBqW6GUoF4p/0=
-cloud.google.com/go/networksecurity v0.9.4/go.mod h1:E9CeMZ2zDsNBkr8axKSYm8XyTqNhiCHf1JO/Vb8mD1w=
cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY=
cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34=
cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA=
cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0=
cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE=
cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ=
-cloud.google.com/go/notebooks v1.9.1/go.mod h1:zqG9/gk05JrzgBt4ghLzEepPHNwE5jgPcHZRKhlC1A8=
-cloud.google.com/go/notebooks v1.10.0/go.mod h1:SOPYMZnttHxqot0SGSFSkRrwE29eqnKPBJFqgWmiK2k=
-cloud.google.com/go/notebooks v1.10.1/go.mod h1:5PdJc2SgAybE76kFQCWrTfJolCOUQXF97e+gteUUA6A=
-cloud.google.com/go/notebooks v1.11.1/go.mod h1:V2Zkv8wX9kDCGRJqYoI+bQAaoVeE5kSiz4yYHd2yJwQ=
-cloud.google.com/go/notebooks v1.11.2/go.mod h1:z0tlHI/lREXC8BS2mIsUeR3agM1AkgLiS+Isov3SS70=
cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4=
cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs=
cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI=
-cloud.google.com/go/optimization v1.4.1/go.mod h1:j64vZQP7h9bO49m2rVaTVoNM0vEBEN5eKPUPbZyXOrk=
-cloud.google.com/go/optimization v1.5.0/go.mod h1:evo1OvTxeBRBu6ydPlrIRizKY/LJKo/drDMMRKqGEUU=
-cloud.google.com/go/optimization v1.5.1/go.mod h1:NC0gnUD5MWVAF7XLdoYVPmYYVth93Q6BUzqAq3ZwtV8=
-cloud.google.com/go/optimization v1.6.1/go.mod h1:hH2RYPTTM9e9zOiTaYPTiGPcGdNZVnBSBxjIAJzUkqo=
-cloud.google.com/go/optimization v1.6.2/go.mod h1:mWNZ7B9/EyMCcwNl1frUGEuY6CPijSkz88Fz2vwKPOY=
cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA=
cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk=
cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ=
-cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8=
-cloud.google.com/go/orchestration v1.8.2/go.mod h1:T1cP+6WyTmh6LSZzeUhvGf0uZVmJyTx7t8z7Vg87+A0=
-cloud.google.com/go/orchestration v1.8.3/go.mod h1:xhgWAYqlbYjlz2ftbFghdyqENYW+JXuhBx9KsjMoGHs=
-cloud.google.com/go/orchestration v1.8.4/go.mod h1:d0lywZSVYtIoSZXb0iFjv9SaL13PGyVOKDxqGxEf/qI=
cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE=
cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc=
cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc=
-cloud.google.com/go/orgpolicy v1.11.0/go.mod h1:2RK748+FtVvnfuynxBzdnyu7sygtoZa1za/0ZfpOs1M=
-cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE=
-cloud.google.com/go/orgpolicy v1.11.2/go.mod h1:biRDpNwfyytYnmCRWZWxrKF22Nkz9eNVj9zyaBdpm1o=
-cloud.google.com/go/orgpolicy v1.11.3/go.mod h1:oKAtJ/gkMjum5icv2aujkP4CxROxPXsBbYGCDbPO8MM=
-cloud.google.com/go/orgpolicy v1.11.4/go.mod h1:0+aNV/nrfoTQ4Mytv+Aw+stBDBjNf4d8fYRA9herfJI=
cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs=
cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg=
cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo=
cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw=
cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw=
-cloud.google.com/go/osconfig v1.12.0/go.mod h1:8f/PaYzoS3JMVfdfTubkowZYGmAhUCjjwnjqWI7NVBc=
-cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE=
-cloud.google.com/go/osconfig v1.12.2/go.mod h1:eh9GPaMZpI6mEJEuhEjUJmaxvQ3gav+fFEJon1Y8Iw0=
-cloud.google.com/go/osconfig v1.12.3/go.mod h1:L/fPS8LL6bEYUi1au832WtMnPeQNT94Zo3FwwV1/xGM=
-cloud.google.com/go/osconfig v1.12.4/go.mod h1:B1qEwJ/jzqSRslvdOCI8Kdnp0gSng0xW4LOnIebQomA=
cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E=
cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU=
cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70=
cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo=
cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs=
-cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs=
-cloud.google.com/go/oslogin v1.11.0/go.mod h1:8GMTJs4X2nOAUVJiPGqIWVcDaF0eniEto3xlOxaboXE=
-cloud.google.com/go/oslogin v1.11.1/go.mod h1:OhD2icArCVNUxKqtK0mcSmKL7lgr0LVlQz+v9s1ujTg=
-cloud.google.com/go/oslogin v1.12.1/go.mod h1:VfwTeFJGbnakxAY236eN8fsnglLiVXndlbcNomY4iZU=
-cloud.google.com/go/oslogin v1.12.2/go.mod h1:CQ3V8Jvw4Qo4WRhNPF0o+HAM4DiLuE27Ul9CX9g2QdY=
cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0=
cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA=
cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk=
-cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I=
-cloud.google.com/go/phishingprotection v0.8.2/go.mod h1:LhJ91uyVHEYKSKcMGhOa14zMMWfbEdxG032oT6ECbC8=
-cloud.google.com/go/phishingprotection v0.8.3/go.mod h1:3B01yO7T2Ra/TMojifn8EoGd4G9jts/6cIO0DgDY9J8=
-cloud.google.com/go/phishingprotection v0.8.4/go.mod h1:6b3kNPAc2AQ6jZfFHioZKg9MQNybDg4ixFd4RPZZ2nE=
cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg=
cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE=
cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw=
cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc=
-cloud.google.com/go/policytroubleshooter v1.7.1/go.mod h1:0NaT5v3Ag1M7U5r0GfDCpUFkWd9YqpubBWsQlhanRv0=
-cloud.google.com/go/policytroubleshooter v1.8.0/go.mod h1:tmn5Ir5EToWe384EuboTcVQT7nTag2+DuH3uHmKd1HU=
-cloud.google.com/go/policytroubleshooter v1.9.0/go.mod h1:+E2Lga7TycpeSTj2FsH4oXxTnrbHJGRlKhVZBLGgU64=
-cloud.google.com/go/policytroubleshooter v1.9.1/go.mod h1:MYI8i0bCrL8cW+VHN1PoiBTyNZTstCg2WUw2eVC4c4U=
-cloud.google.com/go/policytroubleshooter v1.10.1/go.mod h1:5C0rhT3TDZVxAu8813bwmTvd57Phbl8mr9F4ipOsxEs=
-cloud.google.com/go/policytroubleshooter v1.10.2/go.mod h1:m4uF3f6LseVEnMV6nknlN2vYGRb+75ylQwJdnOXfnv0=
cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0=
cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI=
cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg=
cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs=
-cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA=
-cloud.google.com/go/privatecatalog v0.9.2/go.mod h1:RMA4ATa8IXfzvjrhhK8J6H4wwcztab+oZph3c6WmtFc=
-cloud.google.com/go/privatecatalog v0.9.3/go.mod h1:K5pn2GrVmOPjXz3T26mzwXLcKivfIJ9R5N79AFCF9UE=
-cloud.google.com/go/privatecatalog v0.9.4/go.mod h1:SOjm93f+5hp/U3PqMZAHTtBtluqLygrDrVO8X8tYtG0=
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=
@@ -838,12 +442,9 @@ cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcd
cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0=
cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8=
cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4=
-cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc=
-cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc=
cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg=
cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k=
cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM=
-cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0=
cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4=
cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o=
cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk=
@@ -852,89 +453,46 @@ cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI
cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U=
cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA=
cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c=
-cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU=
-cloud.google.com/go/recaptchaenterprise/v2 v2.8.0/go.mod h1:QuE8EdU9dEnesG8/kG3XuJyNsjEqMlMzg3v3scCJ46c=
-cloud.google.com/go/recaptchaenterprise/v2 v2.8.1/go.mod h1:JZYZJOeZjgSSTGP4uz7NlQ4/d1w5hGmksVgM0lbEij0=
-cloud.google.com/go/recaptchaenterprise/v2 v2.8.2/go.mod h1:kpaDBOpkwD4G0GVMzG1W6Doy1tFFC97XAV3xy+Rd/pw=
-cloud.google.com/go/recaptchaenterprise/v2 v2.8.3/go.mod h1:Dak54rw6lC2gBY8FBznpOCAR58wKf+R+ZSJRoeJok4w=
cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg=
cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4=
cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac=
-cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE=
-cloud.google.com/go/recommendationengine v0.8.2/go.mod h1:QIybYHPK58qir9CV2ix/re/M//Ty10OxjnnhWdaKS1Y=
-cloud.google.com/go/recommendationengine v0.8.3/go.mod h1:m3b0RZV02BnODE9FeSvGv1qibFo8g0OnmB/RMwYy4V8=
-cloud.google.com/go/recommendationengine v0.8.4/go.mod h1:GEteCf1PATl5v5ZsQ60sTClUE0phbWmo3rQ1Js8louU=
cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg=
cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c=
cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs=
cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70=
cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ=
-cloud.google.com/go/recommender v1.10.1/go.mod h1:XFvrE4Suqn5Cq0Lf+mCP6oBHD/yRMA8XxP5sb7Q7gpA=
-cloud.google.com/go/recommender v1.11.0/go.mod h1:kPiRQhPyTJ9kyXPCG6u/dlPLbYfFlkwHNRwdzPVAoII=
-cloud.google.com/go/recommender v1.11.1/go.mod h1:sGwFFAyI57v2Hc5LbIj+lTwXipGu9NW015rkaEM5B18=
-cloud.google.com/go/recommender v1.11.2/go.mod h1:AeoJuzOvFR/emIcXdVFkspVXVTYpliRCmKNYDnyBv6Y=
-cloud.google.com/go/recommender v1.11.3/go.mod h1:+FJosKKJSId1MBFeJ/TTyoGQZiEelQQIZMKYYD8ruK4=
cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y=
cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A=
cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA=
cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM=
cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ=
-cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg=
-cloud.google.com/go/redis v1.13.2/go.mod h1:0Hg7pCMXS9uz02q+LoEVl5dNHUkIQv+C/3L76fandSA=
-cloud.google.com/go/redis v1.13.3/go.mod h1:vbUpCKUAZSYzFcWKmICnYgRAhTFg9r+djWqFxDYXi4U=
-cloud.google.com/go/redis v1.14.1/go.mod h1:MbmBxN8bEnQI4doZPC1BzADU4HGocHBk2de3SbgOkqs=
cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA=
cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0=
cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots=
cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo=
cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI=
-cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8=
-cloud.google.com/go/resourcemanager v1.9.2/go.mod h1:OujkBg1UZg5lX2yIyMo5Vz9O5hf7XQOSV7WxqxxMtQE=
-cloud.google.com/go/resourcemanager v1.9.3/go.mod h1:IqrY+g0ZgLsihcfcmqSe+RKp1hzjXwG904B92AwBz6U=
-cloud.google.com/go/resourcemanager v1.9.4/go.mod h1:N1dhP9RFvo3lUfwtfLWVxfUWq8+KUQ+XLlHLH3BoFJ0=
cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU=
cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg=
cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA=
-cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw=
-cloud.google.com/go/resourcesettings v1.6.2/go.mod h1:mJIEDd9MobzunWMeniaMp6tzg4I2GvD3TTmPkc8vBXk=
-cloud.google.com/go/resourcesettings v1.6.3/go.mod h1:pno5D+7oDYkMWZ5BpPsb4SO0ewg3IXcmmrUZaMJrFic=
-cloud.google.com/go/resourcesettings v1.6.4/go.mod h1:pYTTkWdv2lmQcjsthbZLNBP4QW140cs7wqA3DuqErVI=
cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4=
cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY=
cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc=
cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y=
cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14=
-cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE=
-cloud.google.com/go/retail v1.14.2/go.mod h1:W7rrNRChAEChX336QF7bnMxbsjugcOCPU44i5kbLiL8=
-cloud.google.com/go/retail v1.14.3/go.mod h1:Omz2akDHeSlfCq8ArPKiBxlnRpKEBjUH386JYFLUvXo=
-cloud.google.com/go/retail v1.14.4/go.mod h1:l/N7cMtY78yRnJqp5JW8emy7MB1nz8E4t2yfOmklYfg=
cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do=
cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo=
cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM=
cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg=
-cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo=
-cloud.google.com/go/run v1.3.0/go.mod h1:S/osX/4jIPZGg+ssuqh6GNgg7syixKe3YnprwehzHKU=
-cloud.google.com/go/run v1.3.1/go.mod h1:cymddtZOzdwLIAsmS6s+Asl4JoXIDm/K1cpZTxV4Q5s=
-cloud.google.com/go/run v1.3.2/go.mod h1:SIhmqArbjdU/D9M6JoHaAqnAMKLFtXaVdNeq04NjnVE=
-cloud.google.com/go/run v1.3.3/go.mod h1:WSM5pGyJ7cfYyYbONVQBN4buz42zFqwG67Q3ch07iK4=
cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s=
cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI=
cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk=
cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44=
cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc=
cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc=
-cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo=
-cloud.google.com/go/scheduler v1.10.2/go.mod h1:O3jX6HRH5eKCA3FutMw375XHZJudNIKVonSCHv7ropY=
-cloud.google.com/go/scheduler v1.10.3/go.mod h1:8ANskEM33+sIbpJ+R4xRfw/jzOG+ZFE8WVLy7/yGvbc=
-cloud.google.com/go/scheduler v1.10.4/go.mod h1:MTuXcrJC9tqOHhixdbHDFSIuh7xZF2IysiINDuiq6NI=
cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA=
cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4=
cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4=
cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU=
-cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw=
-cloud.google.com/go/secretmanager v1.11.2/go.mod h1:MQm4t3deoSub7+WNwiC4/tRYgDBHJgJPvswqQVB1Vss=
-cloud.google.com/go/secretmanager v1.11.3/go.mod h1:0bA2o6FabmShrEy328i67aV+65XoUFFSmVeLBn/51jI=
-cloud.google.com/go/secretmanager v1.11.4/go.mod h1:wreJlbS9Zdq21lMzWmJ0XhWW2ZxgPeahsqeV/vZoJ3w=
cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4=
cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0=
cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU=
@@ -942,20 +500,12 @@ cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq
cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA=
cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8=
cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0=
-cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA=
-cloud.google.com/go/security v1.15.2/go.mod h1:2GVE/v1oixIRHDaClVbHuPcZwAqFM28mXuAKCfMgYIg=
-cloud.google.com/go/security v1.15.3/go.mod h1:gQ/7Q2JYUZZgOzqKtw9McShH+MjNvtDpL40J1cT+vBs=
-cloud.google.com/go/security v1.15.4/go.mod h1:oN7C2uIZKhxCLiAAijKUCuHLZbIt/ghYEo8MqwD/Ty4=
cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU=
cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc=
cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk=
cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk=
cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0=
cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag=
-cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ=
-cloud.google.com/go/securitycenter v1.23.1/go.mod h1:w2HV3Mv/yKhbXKwOCu2i8bCuLtNP1IMHuiYQn4HJq5s=
-cloud.google.com/go/securitycenter v1.24.1/go.mod h1:3h9IdjjHhVMXdQnmqzVnM7b0wMn/1O/U20eWVpMpZjI=
-cloud.google.com/go/securitycenter v1.24.2/go.mod h1:l1XejOngggzqwr4Fa2Cn+iWZGf+aBLTXtB/vXjy5vXM=
cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU=
cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s=
cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA=
@@ -967,11 +517,6 @@ cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPj
cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U=
cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY=
cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s=
-cloud.google.com/go/servicedirectory v1.10.1/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ=
-cloud.google.com/go/servicedirectory v1.11.0/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ=
-cloud.google.com/go/servicedirectory v1.11.1/go.mod h1:tJywXimEWzNzw9FvtNjsQxxJ3/41jseeILgwU/QLrGI=
-cloud.google.com/go/servicedirectory v1.11.2/go.mod h1:KD9hCLhncWRV5jJphwIpugKwM5bn1x0GyVVD4NO8mGg=
-cloud.google.com/go/servicedirectory v1.11.3/go.mod h1:LV+cHkomRLr67YoQy3Xq2tUXBGOs5z5bPofdq7qtiAw=
cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco=
cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo=
cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc=
@@ -983,30 +528,17 @@ cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DR
cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4=
cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw=
cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A=
-cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g=
-cloud.google.com/go/shell v1.7.2/go.mod h1:KqRPKwBV0UyLickMn0+BY1qIyE98kKyI216sH/TuHmc=
-cloud.google.com/go/shell v1.7.3/go.mod h1:cTTEz/JdaBsQAeTQ3B6HHldZudFoYBOqjteev07FbIc=
-cloud.google.com/go/shell v1.7.4/go.mod h1:yLeXB8eKLxw0dpEmXQ/FjriYrBijNsONpwnWsdPqlKM=
cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos=
cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk=
cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M=
-cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI=
-cloud.google.com/go/spanner v1.49.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM=
-cloud.google.com/go/spanner v1.50.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM=
-cloud.google.com/go/spanner v1.51.0/go.mod h1:c5KNo5LQ1X5tJwma9rSQZsXNBDNvj4/n8BVc3LNahq0=
-cloud.google.com/go/spanner v1.55.0 h1:YF/A/k73EMYCjp8wcJTpkE+TcrWutHRlsCtlRSfWS64=
-cloud.google.com/go/spanner v1.55.0/go.mod h1:HXEznMUVhC+PC+HDyo9YFG2Ajj5BQDkcbqB9Z2Ffxi0=
+cloud.google.com/go/spanner v1.62.0 h1:AHjSLrsGYIEzVQLQkF/OBgObSbXlnMpdovai8x+owco=
+cloud.google.com/go/spanner v1.62.0/go.mod h1:ej/7etuxlyxOhfudKk9nUXBVyxr4kK39LMbmSjOeDEM=
cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0=
cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco=
cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0=
cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI=
-cloud.google.com/go/speech v1.17.1/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo=
-cloud.google.com/go/speech v1.19.0/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo=
-cloud.google.com/go/speech v1.19.1/go.mod h1:WcuaWz/3hOlzPFOVo9DUsblMIHwxP589y6ZMtaG+iAA=
-cloud.google.com/go/speech v1.19.2/go.mod h1:2OYFfj+Ch5LWjsaSINuCZsre/789zlcCI3SY4oAi2oI=
-cloud.google.com/go/speech v1.20.1/go.mod h1:wwolycgONvfz2EDU8rKuHRW3+wc9ILPsAWoikBEWavY=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
@@ -1018,80 +550,43 @@ cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeL
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4=
-cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
-cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8=
-cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
+cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RBx0=
+cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80=
cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w=
cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I=
cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4=
cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw=
-cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA=
-cloud.google.com/go/storagetransfer v1.10.1/go.mod h1:rS7Sy0BtPviWYTTJVWCSV4QrbBitgPeuK4/FKa4IdLs=
-cloud.google.com/go/storagetransfer v1.10.2/go.mod h1:meIhYQup5rg9juQJdyppnA/WLQCOguxtk1pr3/vBWzA=
-cloud.google.com/go/storagetransfer v1.10.3/go.mod h1:Up8LY2p6X68SZ+WToswpQbQHnJpOty/ACcMafuey8gc=
cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM=
cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA=
cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c=
-cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24=
-cloud.google.com/go/talent v1.6.3/go.mod h1:xoDO97Qd4AK43rGjJvyBHMskiEf3KulgYzcH6YWOVoo=
-cloud.google.com/go/talent v1.6.4/go.mod h1:QsWvi5eKeh6gG2DlBkpMaFYZYrYUnIpo34f6/V5QykY=
-cloud.google.com/go/talent v1.6.5/go.mod h1:Mf5cma696HmE+P2BWJ/ZwYqeJXEeU0UqjHFXVLadEDI=
cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8=
cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4=
cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc=
-cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk=
-cloud.google.com/go/texttospeech v1.7.2/go.mod h1:VYPT6aTOEl3herQjFHYErTlSZJ4vB00Q2ZTmuVgluD4=
-cloud.google.com/go/texttospeech v1.7.3/go.mod h1:Av/zpkcgWfXlDLRYob17lqMstGZ3GqlvJXqKMp2u8so=
-cloud.google.com/go/texttospeech v1.7.4/go.mod h1:vgv0002WvR4liGuSd5BJbWy4nDn5Ozco0uJymY5+U74=
cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ=
cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg=
cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM=
-cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E=
-cloud.google.com/go/tpu v1.6.2/go.mod h1:NXh3NDwt71TsPZdtGWgAG5ThDfGd32X1mJ2cMaRlVgU=
-cloud.google.com/go/tpu v1.6.3/go.mod h1:lxiueqfVMlSToZY1151IaZqp89ELPSrk+3HIQ5HRkbY=
-cloud.google.com/go/tpu v1.6.4/go.mod h1:NAm9q3Rq2wIlGnOhpYICNI7+bpBebMJbh0yyp3aNw1Y=
cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28=
cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y=
cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA=
cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk=
-cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk=
-cloud.google.com/go/trace v1.10.2/go.mod h1:NPXemMi6MToRFcSxRl2uDnu/qAlAQ3oULUphcHGh1vA=
-cloud.google.com/go/trace v1.10.3/go.mod h1:Ke1bgfc73RV3wUFml+uQp7EsDw4dGaETLxB7Iq/r4CY=
-cloud.google.com/go/trace v1.10.4/go.mod h1:Nso99EDIK8Mj5/zmB+iGr9dosS/bzWCJ8wGmE6TXNWY=
cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs=
cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg=
cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0=
cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos=
cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos=
-cloud.google.com/go/translate v1.8.1/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs=
-cloud.google.com/go/translate v1.8.2/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs=
-cloud.google.com/go/translate v1.9.0/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs=
-cloud.google.com/go/translate v1.9.1/go.mod h1:TWIgDZknq2+JD4iRcojgeDtqGEp154HN/uL6hMvylS8=
-cloud.google.com/go/translate v1.9.2/go.mod h1:E3Tc6rUTsQkVrXW6avbUhKJSr7ZE3j7zNmqzXKHqRrY=
-cloud.google.com/go/translate v1.9.3/go.mod h1:Kbq9RggWsbqZ9W5YpM94Q1Xv4dshw/gr/SHfsl5yCZ0=
cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk=
cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw=
cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg=
cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk=
cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ=
cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ=
-cloud.google.com/go/video v1.17.1/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU=
-cloud.google.com/go/video v1.19.0/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU=
-cloud.google.com/go/video v1.20.0/go.mod h1:U3G3FTnsvAGqglq9LxgqzOiBc/Nt8zis8S+850N2DUM=
-cloud.google.com/go/video v1.20.1/go.mod h1:3gJS+iDprnj8SY6pe0SwLeC5BUW80NjhwX7INWEuWGU=
-cloud.google.com/go/video v1.20.2/go.mod h1:lrixr5JeKNThsgfM9gqtwb6Okuqzfo4VrY2xynaViTA=
-cloud.google.com/go/video v1.20.3/go.mod h1:TnH/mNZKVHeNtpamsSPygSR0iHtvrR/cW1/GDjN5+GU=
cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4=
cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M=
cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU=
cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU=
-cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo=
-cloud.google.com/go/videointelligence v1.11.2/go.mod h1:ocfIGYtIVmIcWk1DsSGOoDiXca4vaZQII1C85qtoplc=
-cloud.google.com/go/videointelligence v1.11.3/go.mod h1:tf0NUaGTjU1iS2KEkGWvO5hRHeCkFK3nPo0/cOZhZAo=
-cloud.google.com/go/videointelligence v1.11.4/go.mod h1:kPBMAYsTPFiQxMLmmjpcZUMklJp3nC9+ipJJtprccD8=
cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0=
cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo=
cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo=
@@ -1099,59 +594,29 @@ cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb
cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E=
cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY=
cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0=
-cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU=
-cloud.google.com/go/vision/v2 v2.7.3/go.mod h1:V0IcLCY7W+hpMKXK1JYE0LV5llEqVmj+UJChjvA1WsM=
-cloud.google.com/go/vision/v2 v2.7.4/go.mod h1:ynDKnsDN/0RtqkKxQZ2iatv3Dm9O+HfRb5djl7l4Vvw=
-cloud.google.com/go/vision/v2 v2.7.5/go.mod h1:GcviprJLFfK9OLf0z8Gm6lQb6ZFUulvpZws+mm6yPLM=
cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE=
cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g=
cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc=
cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY=
-cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro=
-cloud.google.com/go/vmmigration v1.7.2/go.mod h1:iA2hVj22sm2LLYXGPT1pB63mXHhrH1m/ruux9TwWLd8=
-cloud.google.com/go/vmmigration v1.7.3/go.mod h1:ZCQC7cENwmSWlwyTrZcWivchn78YnFniEQYRWQ65tBo=
-cloud.google.com/go/vmmigration v1.7.4/go.mod h1:yBXCmiLaB99hEl/G9ZooNx2GyzgsjKnw5fWcINRgD70=
cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208=
cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8=
cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY=
-cloud.google.com/go/vmwareengine v0.4.1/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0=
-cloud.google.com/go/vmwareengine v1.0.0/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0=
-cloud.google.com/go/vmwareengine v1.0.1/go.mod h1:aT3Xsm5sNx0QShk1Jc1B8OddrxAScYLwzVoaiXfdzzk=
-cloud.google.com/go/vmwareengine v1.0.2/go.mod h1:xMSNjIk8/itYrz1JA8nV3Ajg4L4n3N+ugP8JKzk3OaA=
-cloud.google.com/go/vmwareengine v1.0.3/go.mod h1:QSpdZ1stlbfKtyt6Iu19M6XRxjmXO+vb5a/R6Fvy2y4=
cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w=
cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8=
cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes=
-cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs=
-cloud.google.com/go/vpcaccess v1.7.2/go.mod h1:mmg/MnRHv+3e8FJUjeSibVFvQF1cCy2MsFaFqxeY1HU=
-cloud.google.com/go/vpcaccess v1.7.3/go.mod h1:YX4skyfW3NC8vI3Fk+EegJnlYFatA+dXK4o236EUCUc=
-cloud.google.com/go/vpcaccess v1.7.4/go.mod h1:lA0KTvhtEOb/VOdnH/gwPuOzGgM+CWsmGu6bb4IoMKk=
cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE=
cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg=
cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc=
cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A=
cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg=
-cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc=
-cloud.google.com/go/webrisk v1.9.2/go.mod h1:pY9kfDgAqxUpDBOrG4w8deLfhvJmejKB0qd/5uQIPBc=
-cloud.google.com/go/webrisk v1.9.3/go.mod h1:RUYXe9X/wBDXhVilss7EDLW9ZNa06aowPuinUOPCXH8=
-cloud.google.com/go/webrisk v1.9.4/go.mod h1:w7m4Ib4C+OseSr2GL66m0zMBywdrVNTDKsdEsfMl7X0=
cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo=
cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ=
cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng=
-cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg=
-cloud.google.com/go/websecurityscanner v1.6.2/go.mod h1:7YgjuU5tun7Eg2kpKgGnDuEOXWIrh8x8lWrJT4zfmas=
-cloud.google.com/go/websecurityscanner v1.6.3/go.mod h1:x9XANObUFR+83Cya3g/B9M/yoHVqzxPnFtgF8yYGAXw=
-cloud.google.com/go/websecurityscanner v1.6.4/go.mod h1:mUiyMQ+dGpPPRkHgknIZeCzSHJ45+fY4F52nZFDHm2o=
cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0=
cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M=
cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
-cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g=
-cloud.google.com/go/workflows v1.12.0/go.mod h1:PYhSk2b6DhZ508tj8HXKaBh+OFe+xdl0dHF/tJdzPQM=
-cloud.google.com/go/workflows v1.12.1/go.mod h1:5A95OhD/edtOhQd/O741NSfIMezNTbCwLM1P1tBRGHM=
-cloud.google.com/go/workflows v1.12.2/go.mod h1:+OmBIgNqYJPVggnMo9nqmizW0qEXHhmnAzK/CnBqsHc=
-cloud.google.com/go/workflows v1.12.3/go.mod h1:fmOUeeqEwPzIU81foMjTRQIdwQHADi/vEr1cx9R1m5g=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -1161,30 +626,22 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0=
github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
-github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
-github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
-github.com/Azure/azure-sdk-for-go v56.3.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/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw=
@@ -1209,24 +666,17 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag=
github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk=
github.com/Azure/azure-storage-blob-go v0.15.0/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58=
-github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
-github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
-github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
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.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
-github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
-github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw=
github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
-github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk=
@@ -1260,23 +710,22 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
-github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
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/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 h1:oVLqHXhnYtUwM89y9T1fXGaK9wTkXHgNp8/ZNMQzUxE=
+github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
-github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E=
-github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
+github.com/Jeffail/gabs/v2 v2.1.0 h1:6dV9GGOjoQgzWTQEltZPXlJdFloxvIq7DwqgxMCbq30=
+github.com/Jeffail/gabs/v2 v2.1.0/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@@ -1288,99 +737,53 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
-github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
-github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
-github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
-github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
-github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
-github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
-github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
-github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
-github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
-github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
-github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
-github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
-github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
-github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
-github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
-github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
-github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
-github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
-github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
-github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
-github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
-github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
-github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
-github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
-github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
-github.com/Microsoft/hcsshim v0.9.10/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
-github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
-github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
-github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
-github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
-github.com/SAP/go-hdb v0.14.1 h1:hkw4ozGZ/i4eak7ZuGkY5e0hxiXFdNUBNhr4AvZVNFE=
-github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo=
+github.com/SAP/go-hdb v1.10.1 h1:c9dGT5xHZNDwPL3NQcRpnNISn3MchwYaGoMZpCAllUs=
+github.com/SAP/go-hdb v1.10.1/go.mod h1:vxYDca44L2eRudZv5JAI6T+IygOfxb7vOCFh/Kj0pug=
github.com/Sectorbob/mlab-ns2 v0.0.0-20171030222938-d3aa0c295a8a h1:KFHLI4QGttB0i7M3qOkAo8Zn/GSsxwwCnInFqBaYtkM=
github.com/Sectorbob/mlab-ns2 v0.0.0-20171030222938-d3aa0c295a8a/go.mod h1:D73UAuEPckrDorYZdtlCu2ySOLuPB5W4rhIkmmc/XbI=
-github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
github.com/aerospike/aerospike-client-go/v5 v5.6.0 h1:tRxcUq0HY8fFPQEzF3EgrknF+w1xFO0YDfUb9Nm8yRI=
github.com/aerospike/aerospike-client-go/v5 v5.6.0/go.mod h1:rJ/KpmClE7kiBPfvAPrGw9WuNOiz8v2uKbQaUyYPXtI=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
-github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
-github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
-github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
-github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
-github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
-github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
-github.com/alexflint/go-filemutex v1.2.0/go.mod h1:mYyQSWvw9Tx2/H2n9qXPb52tTYfE0pZAWcBq5mK025c=
-github.com/aliyun/alibaba-cloud-sdk-go v1.62.676 h1:ChWMMr76tXrRh3ximWQyg83EROEfkkXQGkrhnzDCpr8=
-github.com/aliyun/alibaba-cloud-sdk-go v1.62.676/go.mod h1:CJJYa1ZMxjlN/NbXEwmejEnBkhi0DV+Yb3B2lxf+74o=
+github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
+github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
+github.com/aliyun/alibaba-cloud-sdk-go v1.62.737 h1:ZJQHOp8O0RpldZ8XQwCSlpiDMkiYwcqi1rTAs/7oxQY=
+github.com/aliyun/alibaba-cloud-sdk-go v1.62.737/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 h1:nWDRPCyCltiTsANwC/n3QZH7Vww33Npq9MKqlwRzI/c=
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
-github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
-github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
-github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
-github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
-github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg=
-github.com/apache/arrow/go/v14 v14.0.2 h1:N8OkaJEOfI3mEZt07BIkvo4sC6XDbL+48MBPWO5IONw=
-github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY=
+github.com/apache/arrow/go/v15 v15.0.0 h1:1zZACWf85oEZY5/kd9dsQS7i+2G5zVQcbKTHgslqHNA=
+github.com/apache/arrow/go/v15 v15.0.0/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA=
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
@@ -1398,17 +801,12 @@ 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
-github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
-github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.34.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
-github.com/aws/aws-sdk-go v1.36.29/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
-github.com/aws/aws-sdk-go v1.43.16/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
-github.com/aws/aws-sdk-go v1.50.13 h1:yeXram2g7q8uKkQkAEeZyk9FmPzxI4UpGwAZGZtEGmM=
-github.com/aws/aws-sdk-go v1.50.13/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
+github.com/aws/aws-sdk-go v1.53.5 h1:1OcVWMjGlwt7EU5OWmmEEXqaYfmX581EK317QJZXItM=
+github.com/aws/aws-sdk-go v1.53.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2 v1.23.4 h1:2P20ZjH0ouSAu/6yZep8oCmTReathLuEu6dwoqEgjts=
github.com/aws/aws-sdk-go-v2 v1.23.4/go.mod h1:t3szzKfP0NeRU27uBFczDivYJjsmSnqI8kIvKyWb9ds=
@@ -1455,25 +853,18 @@ github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a h1:eqjiAL3qoof
github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a/go.mod h1:2stgcRjl6QmW+gU2h5E7BQXg4HU0gzxKWDuT5HviN9s=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
-github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/immutable v0.4.0 h1:CTqXbEerYso8YzVPxmWxh2gnoRQbbB9X1quUC8+vGZA=
github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM=
-github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E=
+github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
-github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
-github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
-github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
-github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
-github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
-github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
@@ -1482,56 +873,29 @@ github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
-github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
-github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
-github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
-github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
-github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
-github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
-github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
-github.com/bytecodealliance/wasmtime-go v0.36.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
-github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
-github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
-github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
-github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
-github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
-github.com/centrify/cloud-golang-sdk v0.0.0-20210923165758-a8c48d049166 h1:jQ93fKqb/wRmK/KiHpa7Tk9rmHeKXhp4j+5Sg/tENiY=
-github.com/centrify/cloud-golang-sdk v0.0.0-20210923165758-a8c48d049166/go.mod h1:c/gmvyN8lq6lYtHvrqqoXrg2xyN65N0mBmbikxFWXNE=
-github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
-github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0/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/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/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
-github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
-github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 h1:CWU8piLyqoi9qXEUwzOh5KFKGgmSU5ZhktJyYcq6ryQ=
github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0/go.mod h1:5d8DqS60xkj9k3aXfL3+mXBH0DPYO0FQjcKosxl+b/Q=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
-github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
-github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
-github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
-github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
-github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
-github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
-github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA=
@@ -1548,7 +912,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
@@ -1557,230 +920,72 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY=
-github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw=
+github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
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/cockroach-go/v2 v2.3.8 h1:53yoUo4+EtrC1NrAEgnnad4AS3ntNvGup1PAXZ7UmpE=
github.com/cockroachdb/cockroach-go/v2 v2.3.8/go.mod h1:9uH5jK4yQ3ZQUT9IXe4I2fHzMIF5+JC/oOdzTRgJYJk=
-github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
-github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
-github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
-github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
-github.com/container-orchestrated-devices/container-device-interface v0.6.1/go.mod h1:40T6oW59rFrL/ksiSs7q45GzjGlbvxnA4xaK6cyq+kA=
-github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
-github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
-github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
-github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
-github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E=
-github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
-github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
-github.com/containerd/btrfs/v2 v2.0.0/go.mod h1:swkD/7j9HApWpzl8OHfrHNxppPd9l44DFZdF94BUj9k=
-github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
-github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
-github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
-github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
-github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
-github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
-github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
-github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
-github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA=
-github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
-github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
-github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
-github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
-github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
-github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
-github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
-github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
-github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
-github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
-github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
-github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
-github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
-github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
-github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
-github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
-github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=
-github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0=
-github.com/containerd/containerd v1.6.9/go.mod h1:XVicUvkxOrftE2Q1YWUXgZwkkAxwQYNOFzYWvfVfEfQ=
-github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw=
-github.com/containerd/containerd v1.6.23/go.mod h1:UrQOiyzrLi3n4aezYJbQH6Il+YzTvnHFbEuO3yfDrM4=
github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0=
github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk=
-github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
-github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
-github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
-github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
-github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
-github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
-github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
-github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk=
-github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
-github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
-github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
-github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
-github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
-github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
-github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
-github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
-github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU=
-github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk=
-github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA=
-github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA=
-github.com/containerd/go-cni v1.1.6/go.mod h1:BWtoWl5ghVymxu6MBjg79W9NZrCRyHIdUtk4cauMe34=
-github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM=
-github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
-github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
-github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
-github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
-github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
-github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0=
-github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA=
-github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
-github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
-github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4=
-github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
-github.com/containerd/imgcrypt v1.1.7/go.mod h1:FD8gqIcX5aTotCtOmjeCsi3A1dHmTZpnMISGKSczt4k=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
-github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
-github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
-github.com/containerd/nri v0.4.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI=
-github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
-github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
-github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
-github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
-github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
-github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
-github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
-github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
-github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3/go.mod h1:YYyNVhZrTMiaf51Vj6WhAJqJw+vl/nzABhj8pWrzle4=
-github.com/containerd/ttrpc v1.1.2/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
-github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
-github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
-github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
-github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
-github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
-github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
-github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw=
-github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y=
-github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
-github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
-github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
-github.com/containerd/zfs v1.1.0/go.mod h1:oZF9wBnrnQjpWLaPKEinrx3TQ9a+W/RJO7Zb41d8YLE=
-github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
-github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
-github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
-github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
-github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
-github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE=
-github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
-github.com/containernetworking/plugins v1.2.0/go.mod h1:/VjX4uHecW5vVimFa1wkG4s+r/s9qIfPdqlLF4TW8c4=
-github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
-github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4=
-github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g=
-github.com/containers/ocicrypt v1.1.6/go.mod h1:WgjxPWdTJMqYMjf3M6cuIFFA1/MpyyhIM99YInA+Rvc=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.27+incompatible h1:QIudLb9KeBsE5zyYxd1mjzRSkzLg9Wf9QlRwFgd6oTA=
github.com/coreos/etcd v3.3.27+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
-github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
-github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
-github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
-github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
-github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
-github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
-github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
-github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
+github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
+github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
-github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf h1:GOPo6vn/vTN+3IwZBvXX0y5doJfSC7My0cdzelyOCsQ=
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/couchbase/gocb/v2 v2.6.5 h1:xaZu29o8UJEV1ZQ3n2s9jcRCUHz/JsQ6+y6JBnVsy5A=
-github.com/couchbase/gocb/v2 v2.6.5/go.mod h1:0vFM09y+VPhnXeNrIb8tS0wKHGpJvjJBrJnriWEiwGs=
-github.com/couchbase/gocbcore/v10 v10.2.9/go.mod h1:lYQIIk+tzoMcwtwU5GzPbDdqEkwkH3isI2rkSpfL0oM=
-github.com/couchbase/gocbcore/v10 v10.3.1 h1:dx+lub02eDYiQXavtF0EwYMppVUcbjCxAAqa6/nQldg=
-github.com/couchbase/gocbcore/v10 v10.3.1/go.mod h1:lYQIIk+tzoMcwtwU5GzPbDdqEkwkH3isI2rkSpfL0oM=
-github.com/couchbaselabs/gocaves/client v0.0.0-20230307083111-cc3960c624b1/go.mod h1:AVekAZwIY2stsJOMWLAS/0uA/+qdp7pjO8EHnl61QkY=
+github.com/couchbase/gocb/v2 v2.8.1 h1:syeJEVy36IvUy4wyzK/74M4wc4OJ2eWZ1d6yWG31Qno=
+github.com/couchbase/gocb/v2 v2.8.1/go.mod h1:xI7kkiz4IhdrhBAAEcKC6R2oqVXxpMIV/ZkmxB+PWgM=
+github.com/couchbase/gocbcore/v10 v10.4.1 h1:2vZjYRTbSCp1HEcL3iFQv+r4HwiI13VhdnbTku+E/+M=
+github.com/couchbase/gocbcore/v10 v10.4.1/go.mod h1:rulbgUK70EuyRUiLQ0LhQAfSI/Rl+jWws8tTbHzvB6M=
+github.com/couchbase/gocbcoreps v0.1.2 h1:wlGyyMnkWpCNOlTtfy8UG+8XZsFtqTJtPXz63+QKC58=
+github.com/couchbase/gocbcoreps v0.1.2/go.mod h1:33hSdOKnrUVaBqw4+RiqW+2JoD8ylkbvqm89Wg81uXk=
+github.com/couchbase/goprotostellar v1.0.2 h1:yoPbAL9sCtcyZ5e/DcU5PRMOEFaJrF9awXYu3VPfGls=
+github.com/couchbase/goprotostellar v1.0.2/go.mod h1:5/yqVnZlW2/NSbAWu1hPJCFBEwjxgpe0PFFOlRixnp4=
github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259 h1:2TXy68EGEzIMHOx9UvczR5ApVecwCfQZ0LjkmwMI6g4=
github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259/go.mod h1:AVekAZwIY2stsJOMWLAS/0uA/+qdp7pjO8EHnl61QkY=
+github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 h1:2EAfFswAfgYn3a05DVcegiw6DgMgn1Mv5eGz6IHt1Cw=
+github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131/go.mod h1:o7T431UOfFVHDNvMBUmUxpHnhivwv7BziUao/nMl81E=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
-github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
-github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
-github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
-github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
-github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
-github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
-github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba h1:p6poVbjHDkKa+wtC8frBMwQtT3BmqGYBjzMwJ63tuR4=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
-github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M=
-github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug=
-github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
-github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc h1:8WFBn63wegobsYAX0YjD+8suexZDga5CctH4CCTx2+8=
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
@@ -1789,54 +994,23 @@ github.com/digitalocean/godo v1.7.5/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nb
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
-github.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
-github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
-github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
-github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
-github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
-github.com/docker/cli v23.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
-github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbTO1lpcGSkU=
-github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
-github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
-github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE=
-github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
-github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
-github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
+github.com/docker/cli v25.0.5+incompatible h1:3Llw3kcE1gOScEojA247iDD+p1l9hHeC7H3vf3Zd5fk=
+github.com/docker/cli v25.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg=
+github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
-github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
-github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
-github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
-github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
-github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
-github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
-github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 h1:2MIhn2R6oXQbgW5yHfS+d6YqyMfXiu2L55rFZC4UD/M=
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
-github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
@@ -1846,10 +1020,6 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkg
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
-github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
-github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
@@ -1864,80 +1034,51 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34=
-github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI=
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
-github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM=
-github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g=
+github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
+github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
-github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
-github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs=
-github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
-github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
+github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
+github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
-github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
-github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
-github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
+github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
-github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
-github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8=
-github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
-github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
-github.com/foxcpp/go-mockdns v0.0.0-20210729171921-fb145fc6f897/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4=
-github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
-github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU=
-github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
-github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
-github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
github.com/gammazero/workerpool v1.1.3 h1:WixN4xzukFoN0XSeXF6puqEqFTl2mECI9S6W44HWy9Q=
github.com/gammazero/workerpool v1.1.3/go.mod h1:wPjyBLDbyKnUn2XwwyD3EEwo9dHutia9/fwNmSHWACc=
-github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
-github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
-github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
-github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
-github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
-github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.4.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
-github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
@@ -1958,102 +1099,63 @@ github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lK
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
-github.com/go-ini/ini v1.66.6/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
-github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
-github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
+github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
+github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
github.com/go-ldap/ldap/v3 v3.1.7/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
-github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
-github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A=
-github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc=
+github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
+github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk=
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3 h1:sfz1YppV05y4sYaW7kXZtrocU/+vimnIWt4cxAYh7+o=
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3/go.mod h1:ZXFhGda43Z2TVbfGZefXyMJzsDHhCh0go3bZUcwTx7o=
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=
-github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
-github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
-github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
-github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc=
-github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
-github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
-github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M=
-github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk=
+github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
+github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
+github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
+github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
-github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
-github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
-github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
-github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
+github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
+github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
-github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
-github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
-github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
-github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
-github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
-github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
-github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro=
-github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw=
-github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc=
-github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ=
+github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
+github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
+github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
+github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
+github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
-github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
-github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
-github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
-github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
-github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
-github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k=
-github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew=
+github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
+github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
+github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
+github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
-github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
-github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-openapi/validate v0.22.2 h1:Lda8nadL/5kIvS5mdXCAIuZ7IVXvKFIppLnw+EZh+n0=
-github.com/go-openapi/validate v0.22.2/go.mod h1:kVxh31KbfsxU8ZyoHaDbLBWU5CnMdqBUEtadQ2G4d5M=
+github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
+github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
+github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE=
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
-github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
-github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
-github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
-github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@@ -2061,55 +1163,35 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
-github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
+github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
+github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
-github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
-github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
-github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
-github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
-github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
-github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gocql/gocql v1.0.0 h1:UnbTERpP72VZ/viKE1Q1gPtmLvyTZTvuAstvSRydw/c=
github.com/gocql/gocql v1.0.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
-github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
-github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
-github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
-github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc=
github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
-github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
-github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
-github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
-github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
-github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
-github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
-github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
+github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
+github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@@ -2119,7 +1201,6 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
-github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -2158,22 +1239,16 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
-github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
-github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw=
-github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg=
github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
-github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -2193,14 +1268,10 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
-github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMdlgB8eXiiYOY55gfN91Wk=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-metrics-stackdriver v0.2.0 h1:rbs2sxHAPn2OtUj9JdR/Gij1YKGl0BTVD0augB+HEjE=
github.com/google/go-metrics-stackdriver v0.2.0/go.mod h1:KLcPyp3dWJAFD+yHisGlJSZktIsTjb50eB72U2YZ9K0=
-github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY=
-github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY=
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
@@ -2213,8 +1284,9 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
-github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
+github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
+github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -2227,29 +1299,21 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM=
-github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
-github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
-github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w=
github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM=
-github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
@@ -2257,8 +1321,6 @@ github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
-github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
-github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@@ -2272,47 +1334,32 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
-github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
-github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw=
-github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
-github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
-github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
+github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg=
+github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
-github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
-github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
-github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
-github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
-github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
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.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
@@ -2325,28 +1372,28 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp-forge/bbolt v1.3.8-hc3 h1:iTWR3RDPj0TGChAvJ8QjHFcNFWAUVgNQV73IE6gAX4E=
github.com/hashicorp-forge/bbolt v1.3.8-hc3/go.mod h1:sQBu5UIJ+rcUFU4Fo9rpTHNV935jwmGWS3dQ/MV8810=
-github.com/hashicorp/cap v0.6.0 h1:uOSdbtXu8zsbRyjwpiTy6QiuX3+5paAbNkYlop7QexM=
-github.com/hashicorp/cap v0.6.0/go.mod h1:DwzHkoG6pxSARiqwvAgxmCPUpTTCCw2wVuPrIFOzpe0=
-github.com/hashicorp/cap/ldap v0.0.0-20240328153749-fcfe271d0227 h1:R5CMNyBNZqODw2DcGaSa2X96AgtLotXsH7aOa07zTTI=
-github.com/hashicorp/cap/ldap v0.0.0-20240328153749-fcfe271d0227/go.mod h1:Ofp5fMLl1ImcwjNGu9FtEwNOdxA0LYoWpcWQE2vltuI=
+github.com/hashicorp/cap v0.7.0 h1:atLIEU5lJslYXo1qsv7RtUL1HrJVVxnfkErIT3uxLp0=
+github.com/hashicorp/cap v0.7.0/go.mod h1:UynhCoGX3pxL0OfVrfMzPWAyjMYp96bk11BNTf2zt8o=
+github.com/hashicorp/cap/ldap v0.0.0-20240403125925-c0418810d10e h1:IakB/NhT0YtMEGqAf2tViMdBABC2cMAZn3O/mVeg2j4=
+github.com/hashicorp/cap/ldap v0.0.0-20240403125925-c0418810d10e/go.mod h1:Ofp5fMLl1ImcwjNGu9FtEwNOdxA0LYoWpcWQE2vltuI=
github.com/hashicorp/cli v1.1.6 h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8=
github.com/hashicorp/cli v1.1.6/go.mod h1:MPon5QYlgjjo0BSoAiN0ESeT5fRzDjVRp+uioJ0piz4=
-github.com/hashicorp/consul-template v0.37.6 h1:7iz+BjuO4/LHQn/x04o3b+42UspILcIKZQk6DQJd59M=
-github.com/hashicorp/consul-template v0.37.6/go.mod h1:tT9BVCw6W4JUxHJlv+onPuUzBTiYwvPRfXYPDgXDbIA=
-github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
-github.com/hashicorp/consul/api v1.27.0 h1:gmJ6DPKQog1426xsdmgk5iqDyoRiNc+ipBdJOqKQFjc=
-github.com/hashicorp/consul/api v1.27.0/go.mod h1:JkekNRSou9lANFdt+4IKx3Za7XY0JzzpQjEb4Ivo1c8=
+github.com/hashicorp/consul-template v0.39.1 h1:MfhPoNENzCVSEXtE7CnIm3JkCzM9K0I7rcJYofm1BYY=
+github.com/hashicorp/consul-template v0.39.1/go.mod h1:AKqYCDerwwX2k9w7mTWIEC0bEUemSjyYl6Cy+NlqNYw=
+github.com/hashicorp/consul/api v1.29.1 h1:UEwOjYJrd3lG1x5w7HxDRMGiAUPrb3f103EoeKuuEcc=
+github.com/hashicorp/consul/api v1.29.1/go.mod h1:lumfRkY/coLuqMICkI7Fh3ylMG31mQSRZyef2c5YvJI=
+github.com/hashicorp/consul/proto-public v0.6.1 h1:+uzH3olCrksXYWAYHKqK782CtK9scfqH+Unlw3UHhCg=
+github.com/hashicorp/consul/proto-public v0.6.1/go.mod h1:cXXbOg74KBNGajC+o8RlA502Esf0R9prcoJgiOX/2Tg=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
-github.com/hashicorp/consul/sdk v0.15.1 h1:kKIGxc7CZtflcF5DLfHeq7rOQmRq3vk7kwISN9bif8Q=
-github.com/hashicorp/consul/sdk v0.15.1/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A=
+github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg=
+github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s=
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
-github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
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/eventlogger v0.2.8 h1:WITwN1QGMtxHQE7l69WBwLJIJA5vH5pcvX69peURU14=
-github.com/hashicorp/eventlogger v0.2.8/go.mod h1://CHt6/j+Q2lc0NlUB5af4aS2M0c0aVBg9/JfcpAyhM=
+github.com/hashicorp/eventlogger v0.2.10 h1:Dddth3KVSribGE1rInGToM30tRNblvL0G1OG6N+i2pk=
+github.com/hashicorp/eventlogger v0.2.10/go.mod h1:imHMTfJH4qfb8Knh9nZw4iLfL9J1bX6TJKEurSB4t+U=
github.com/hashicorp/go-bexpr v0.1.12 h1:XrdVhmwu+9iYxIUWxsGVG7NQwrhzJZ0vR6nbN5bLgrA=
github.com/hashicorp/go-bexpr v0.1.12/go.mod h1:ACktpcSySkFNpcxWSClFrut7wicd9WzisnvHuw+g9K8=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@@ -2357,25 +1404,20 @@ github.com/hashicorp/go-discover v0.0.0-20210818145131-c573d69da192 h1:eje2KOX8S
github.com/hashicorp/go-discover v0.0.0-20210818145131-c573d69da192/go.mod h1:3/4dzY4lR1Hzt9bBqMhBzG7lngZ0GKx/nL6G/ad62wE=
github.com/hashicorp/go-gatedio v0.5.0 h1:Jm1X5yP4yCqqWj5L1TgW7iZwCVPGtVc+mro5r/XX7Tg=
github.com/hashicorp/go-gatedio v0.5.0/go.mod h1:Lr3t8L6IyxD3DAeaUxGcgl2JnRUpWMCsmBl4Omu/2t4=
-github.com/hashicorp/go-gcp-common v0.8.0 h1:/2vGAbCU1v+BZ3YHXTCzTvxqma9WOJHYtADTfhZixLo=
-github.com/hashicorp/go-gcp-common v0.8.0/go.mod h1:Q7zYRy9ue9SuaEN2s9YLIQs4SoKHdoRmKRcImY3SLgs=
+github.com/hashicorp/go-gcp-common v0.9.0 h1:dabqPrA+vlNWcyQV/3yOI6WCmQGFJgwyztDEsqDp+Q0=
+github.com/hashicorp/go-gcp-common v0.9.0/go.mod h1:aZnN6BVMqryPo4vIy97ZAYSoREnJWilLMmaOmi5P7vY=
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
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/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
-github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.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-kms-wrapping/entropy/v2 v2.0.1 h1:KIge4FHZEDb2/xjaWgmBheCTgRL6HV4sgTfDsH876L8=
github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.1/go.mod h1:aHO1EoFD0kBYLBedqxXgalfFT8lrWfP7kpuSoaqGjH0=
-github.com/hashicorp/go-kms-wrapping/v2 v2.0.8/go.mod h1:qTCjxGig/kjuj3hk1z8pOUrzbse/GxB1tGfbrq8tGJg=
github.com/hashicorp/go-kms-wrapping/v2 v2.0.16 h1:WZeXfD26QMWYC35at25KgE021SF9L3u9UMHK8fJAdV0=
github.com/hashicorp/go-kms-wrapping/v2 v2.0.16/go.mod h1:ZiKZctjRTLEppuRwrttWkp71VYMbTTCkazK4xT7U/NQ=
github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2 v2.0.9 h1:HpGOHc0Vd3aacMAEtAUVe38zMcq7BfYQSjrGCmtRNx0=
@@ -2398,9 +1440,8 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4=
-github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I=
-github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4=
-github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
+github.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0=
+github.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
@@ -2410,30 +1451,26 @@ github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/
github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a h1:FmnBDwGwlTgugDGbVxwV8UavqSMACbGrUpfc98yFLR4=
github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a/go.mod h1:xbXnmKqX9/+RhPkJ4zrEx4738HacP72aaUPlT2RZ4sU=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
-github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
-github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
-github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
-github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
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/awsutil v0.3.0 h1:I8bynUKMh9I7JdwtW9voJ0xmHvBpxQtLjrMFDYmhOxY=
github.com/hashicorp/go-secure-stdlib/awsutil v0.3.0/go.mod h1:oKHSQs4ivIfZ3fbXGQOop1XuDfdSb8RIsWTGaAanSfg=
-github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 h1:ET4pqyjiGmY09R5y+rSd70J2w45CtbWDNvGqWp/R3Ng=
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
github.com/hashicorp/go-secure-stdlib/fileutil v0.1.0 h1:f2mwVgMJjXuX/+eWD6ZW30+oIRgCofL+XMWknFkB1WM=
github.com/hashicorp/go-secure-stdlib/fileutil v0.1.0/go.mod h1:uwcr2oga9pN5+OkHZyTN5MDk3+1YHOuMukhpnPaQAoI=
github.com/hashicorp/go-secure-stdlib/gatedwriter v0.1.1 h1:9um9R8i0+HbRHS9d64kdvWR0/LJvo12sIonvR9zr1+U=
github.com/hashicorp/go-secure-stdlib/gatedwriter v0.1.1/go.mod h1:6RoRTSMDK2H/rKh3P/JIsk1tK8aatKTt3JyvIopi3GQ=
+github.com/hashicorp/go-secure-stdlib/httputil v0.1.0 h1:0cT/LmCfurGE6/MOq8ig3meKYS32YDh0sTE9g86ANgg=
+github.com/hashicorp/go-secure-stdlib/httputil v0.1.0/go.mod h1:Md+jfeLf7CjGjTmgBWzFyc4vznsIb8yEiX7/CGAJvkI=
github.com/hashicorp/go-secure-stdlib/kv-builder v0.1.2 h1:NS6BHieb/pDfx3M9jDdaPpGyyVp+aD4A3DjX3dgRmzs=
github.com/hashicorp/go-secure-stdlib/kv-builder v0.1.2/go.mod h1:rf5JPE13wi+NwjgsmGkbg4b2CgHq8v7Htn/F0nDe/hg=
-github.com/hashicorp/go-secure-stdlib/mlock v0.1.2/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I=
github.com/hashicorp/go-secure-stdlib/mlock v0.1.3 h1:kH3Rhiht36xhAfhuHyWJDgdXXEx9IIZhDGRk24CDhzg=
github.com/hashicorp/go-secure-stdlib/mlock v0.1.3/go.mod h1:ov1Q0oEDjC3+A4BwsG2YdKltrmEw8sf9Pau4V9JQ4Vo=
github.com/hashicorp/go-secure-stdlib/nonceutil v0.1.0 h1:iJG9Q3iUme12yH+wzBMGYrw/Am4CfX3sDcA8m5OGfhQ=
github.com/hashicorp/go-secure-stdlib/nonceutil v0.1.0/go.mod h1:s28ohJ0kU6tersf0it/WsBCyZSdziPlP+G1FRA3ar28=
-github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 h1:iBt4Ew4XEGLfh6/bPk4rSYmuZJGizr6/x/AEizP0CQc=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8/go.mod h1:aiJI+PIApBRQG7FZTEBx5GiiX+HbOHilUdNxUZi4eV0=
github.com/hashicorp/go-secure-stdlib/password v0.1.1 h1:6JzmBqXprakgFEHwBgdchsjaA9x3GyjdI568bXKxa60=
@@ -2442,22 +1479,19 @@ github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 h1:KMWpBsC65ZBXDpox
github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0/go.mod h1:qKYwSZ2EOpppko5ud+Sh9TrUgiTAZSaQCr8XWIYXsbM=
github.com/hashicorp/go-secure-stdlib/reloadutil v0.1.1 h1:SMGUnbpAcat8rIKHkBPjfv81yC46a8eCNZ2hsR2l1EI=
github.com/hashicorp/go-secure-stdlib/reloadutil v0.1.1/go.mod h1:Ch/bf00Qnx77MZd49JRgHYqHQjtEmTgGU2faufpVZb0=
-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.3 h1:xbrxd0U9XQW8qL1BAz2XrAjAF/P2vcqUTAues9c24B8=
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.3/go.mod h1:LWq2Sy8UoKKuK4lFuCNWSjJj57MhNNf2zzBWMtkAIX4=
-github.com/hashicorp/go-slug v0.13.4 h1:dIyjGKFVwbOVAqp0/s7tmONwCNr9D2UvmMuVE4mPfv0=
-github.com/hashicorp/go-slug v0.13.4/go.mod h1:THWVTAXwJEinbsp4/bBRcmbaO5EYNLTqxbG4tZ3gCYQ=
+github.com/hashicorp/go-slug v0.15.0 h1:AhMnE6JIyW0KoDJlmRDwv4xd52a5ZK3VdioQ7SMmZhI=
+github.com/hashicorp/go-slug v0.15.0/go.mod h1:THWVTAXwJEinbsp4/bBRcmbaO5EYNLTqxbG4tZ3gCYQ=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
-github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
-github.com/hashicorp/go-sockaddr v1.0.5/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI=
github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I=
github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI=
github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
-github.com/hashicorp/go-tfe v1.44.0 h1:eQ9n2Ecfel6O5j03UW6B9LNsM1x6KbHErsjwSd9BLmg=
-github.com/hashicorp/go-tfe v1.44.0/go.mod h1:3ZGX+wxeyp/JnP8qEZo8m3s0ggJ7H+L2BvJRpkRdtVU=
+github.com/hashicorp/go-tfe v1.61.0 h1:KlLB/hbU2nnHWzzS1Z9UNGw5gjrfFh+XntcKrf4CLv0=
+github.com/hashicorp/go-tfe v1.61.0/go.mod h1:XnTtBj3tVQ4uFkcFsv8Grn+O1CVcIcceL1uc2AgUcaU=
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/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
@@ -2465,7 +1499,6 @@ github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/C
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.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/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
@@ -2482,17 +1515,15 @@ github.com/hashicorp/hcp-link v0.2.1 h1:8w4YVJxRb2C7oXN+hCPSyDbBeo7RQsIYTR6nQXJt
github.com/hashicorp/hcp-link v0.2.1/go.mod h1:6otT7bD+nBW1cyzgz8Z4BPziZfwxTtAEkYUrF/MOT8o=
github.com/hashicorp/hcp-scada-provider v0.2.2 h1:S4Kz+Vc02XOz/5Sm9Gug6ivfyfgchM6qv48cgz0uRls=
github.com/hashicorp/hcp-scada-provider v0.2.2/go.mod h1:Q0WpS2RyhBKOPD4X/8oW7AJe7jA2HXB09EwDzwRTao0=
-github.com/hashicorp/hcp-sdk-go v0.75.0 h1:5SLvNpcTeZnG7YnwWIaZlqCottFCGKldEIQnaYjOIq8=
-github.com/hashicorp/hcp-sdk-go v0.75.0/go.mod h1:5GwdT+HGhEQsh4n1yK+RADnQkfOo6vHgr2BpYUt2t9U=
+github.com/hashicorp/hcp-sdk-go v0.101.0 h1:jRphqVzYCw3d/M0CyVe5FIMbS/FFv5Dq36mepIkqI7g=
+github.com/hashicorp/hcp-sdk-go v0.101.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk=
github.com/hashicorp/jsonapi v1.3.1 h1:GtPvnmcWgYwCuDGvYT5VZBHcUyFdq9lSyCzDjn1DdPo=
github.com/hashicorp/jsonapi v1.3.1/go.mod h1:kWfdn49yCjQvbpnvY1dxxAuAFzISwrrMDQOcu6NsFoM=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
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/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
-github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 h1:kBpVVl1sl3MaSrs97e0+pDQhSrqJv9gVbSUrPpVfl1w=
@@ -2502,8 +1533,8 @@ github.com/hashicorp/nomad/api v0.0.0-20240213164230-c364cb57298d/go.mod h1:ijDw
github.com/hashicorp/raft v1.0.1/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI=
github.com/hashicorp/raft v1.1.2-0.20191002163536-9c6bd3e3eb17/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
-github.com/hashicorp/raft v1.6.1 h1:v/jm5fcYHvVkL0akByAp+IDdDSzCNCGhdO6VdB56HIM=
-github.com/hashicorp/raft v1.6.1/go.mod h1:N1sKh6Vn47mrWvEArQgILTyng8GoDRNYlgKyK7PMjs0=
+github.com/hashicorp/raft v1.7.0 h1:4u24Qn6lQ6uwziM++UgsyiT64Q8GyRn43CV41qPiz1o=
+github.com/hashicorp/raft v1.7.0/go.mod h1:N1sKh6Vn47mrWvEArQgILTyng8GoDRNYlgKyK7PMjs0=
github.com/hashicorp/raft-autopilot v0.2.0 h1:2/R2RPgamgRKgNWGQioULZvjeKXQZmDuw5Ty+6c+H7Y=
github.com/hashicorp/raft-autopilot v0.2.0/go.mod h1:q6tZ8UAZ5xio2gv2JvjgmtOlh80M6ic8xQYBe2Egkg8=
github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk=
@@ -2515,99 +1546,84 @@ github.com/hashicorp/raft-snapshot v1.0.4 h1:EuDuayAJPdiDmVk1ygTDnG2zDzrs0/6/yBu
github.com/hashicorp/raft-snapshot v1.0.4/go.mod h1:5sL9eUn72lH5DzsFIJ9jaysITbHksSSszImWSOTC8Ic=
github.com/hashicorp/raft-wal v0.4.0 h1:oHCQLPa3gBTrfuBVHaDg2b/TVXpU0RIyeH/mU9ovk3Y=
github.com/hashicorp/raft-wal v0.4.0/go.mod h1:A6vP5o8hGOs1LHfC1Okh9xPwWDcmb6Vvuz/QyqUXlOE=
-github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
-github.com/hashicorp/vault-hcp-lib v0.0.0-20240402205111-2312b38227ab h1:n1GzFf7LwpVebVIjh5XKW2IQa/BqI/zPlFg2mmB26dQ=
-github.com/hashicorp/vault-hcp-lib v0.0.0-20240402205111-2312b38227ab/go.mod h1:Nb41BTPvmFbKB73D/+XpxIw6Nf2Rt+AOUvLzlDxwAGQ=
-github.com/hashicorp/vault-plugin-auth-alicloud v0.17.0 h1:0SOkYxjMjph3Tbtv37+pANJQnYDvlAdjKpdEbK6zzZs=
-github.com/hashicorp/vault-plugin-auth-alicloud v0.17.0/go.mod h1:79KUWOxY6Ftoad7b+vEmyCmY6eYKdHiADTP0w0TunsE=
-github.com/hashicorp/vault-plugin-auth-azure v0.17.0 h1:nFsWQV+sMEdJCvKpVODNeTPP36n5bi6yiQpBOdBsQWw=
-github.com/hashicorp/vault-plugin-auth-azure v0.17.0/go.mod h1:bkIcQTa19JcR426IkSoGEmXX5Yi7nfLp/6M965zvuww=
-github.com/hashicorp/vault-plugin-auth-centrify v0.15.1 h1:6StAr5tltpySNgyUwWC8czm9ZqkO7NIZfcRmxxtFwQ8=
-github.com/hashicorp/vault-plugin-auth-centrify v0.15.1/go.mod h1:xXs4I5yLxbQ5VHcpvSxkRhShCTXd8Zyrni8qnFrfQ4Y=
-github.com/hashicorp/vault-plugin-auth-cf v0.16.0 h1:t4+0LY6002NQvY6c0c43ikZjxqReCHUiy7+YXiMRbKo=
-github.com/hashicorp/vault-plugin-auth-cf v0.16.0/go.mod h1:q+Lt3FhtFlP+pulKSjrbnR8ecu4vY9TlgPvs+nnBey8=
-github.com/hashicorp/vault-plugin-auth-gcp v0.16.2 h1:HC1PpXxGNzfu7IUfN7Ok7dIMV29R8a/2EJ5uDnrpxz0=
-github.com/hashicorp/vault-plugin-auth-gcp v0.16.2/go.mod h1:8FWNvFElzQBWJGCZ3SBPqsSc/x9bge9Et+JuwVLlJPM=
-github.com/hashicorp/vault-plugin-auth-jwt v0.20.3 h1:mLsdorH4m43rBqybHDZKl33rrmc80ens4hSB6E7i9o0=
-github.com/hashicorp/vault-plugin-auth-jwt v0.20.3/go.mod h1:1IQjNAZ2z8GdTPM/XizC6eA4X9brnOXiwSoYEOfuDlM=
-github.com/hashicorp/vault-plugin-auth-kerberos v0.11.0 h1:XjdH8nqosqgKeAwBptMS7DoXsdi8IKL2fbBSyvL/HRM=
-github.com/hashicorp/vault-plugin-auth-kerberos v0.11.0/go.mod h1:xupzh9O6Us6bqKLZ6wfRsjqlf1Mb1TRylKpxZPJd5rA=
-github.com/hashicorp/vault-plugin-auth-kubernetes v0.18.0 h1:mGVVdcTI55t/NrMefkLjnenAVunJiQZg5o0opuU7ixw=
-github.com/hashicorp/vault-plugin-auth-kubernetes v0.18.0/go.mod h1:ju7B2fxYr3EtC2jX0ft79mUMuEGozz1Ws/ABpVvtlto=
-github.com/hashicorp/vault-plugin-auth-oci v0.15.1 h1:frikend6vdC09I60qmFkRwBVgXLlBz2qe1869bC5J5s=
-github.com/hashicorp/vault-plugin-auth-oci v0.15.1/go.mod h1:i3KYRLQFpAIJuvbXHBMgXzw0563Sp/2mMpAFU5F6Z9I=
-github.com/hashicorp/vault-plugin-database-couchbase v0.10.1 h1:U+UPB8FIh5UJo8mziK36waZ0o6q8Ik6hgncFTuJ1Bwg=
-github.com/hashicorp/vault-plugin-database-couchbase v0.10.1/go.mod h1:yxvB4Ky2JhtUtZOp+7M8z9jupxfEBKIIyiBNs9qvXpA=
-github.com/hashicorp/vault-plugin-database-elasticsearch v0.14.0 h1:7v7+WTlQKG/ZikiW3Q4Hef6UBw9A2Q4xAB0ytOkXNdU=
-github.com/hashicorp/vault-plugin-database-elasticsearch v0.14.0/go.mod h1:JKcIsHm0bi9tdNnwyOQKGkt8vEz/oO3KjQIsisViu1s=
-github.com/hashicorp/vault-plugin-database-mongodbatlas v0.11.0 h1:DNIwrmviDOq/BdIhFaU6wMYolOl/0N54xYBCy41HN3U=
-github.com/hashicorp/vault-plugin-database-mongodbatlas v0.11.0/go.mod h1:DTrqLTHGxHVPudf4OUnxA3RPFDYwDzvTPuGinok/sH8=
+github.com/hashicorp/vault-hcp-lib v0.0.0-20240704151836-a5c058ac604c h1:LCwgi0iiq6pPIRWG80MWwZfPxO2xoHPYwShWfnhAhNI=
+github.com/hashicorp/vault-hcp-lib v0.0.0-20240704151836-a5c058ac604c/go.mod h1:Nb41BTPvmFbKB73D/+XpxIw6Nf2Rt+AOUvLzlDxwAGQ=
+github.com/hashicorp/vault-plugin-auth-alicloud v0.18.0 h1:rGQ+zHJPSIFEpWJ/AEDrOCs7zWrVWIh/JDHRlccr8CI=
+github.com/hashicorp/vault-plugin-auth-alicloud v0.18.0/go.mod h1:yTlbTm6u0wLBmS905Puz68d+SAc7MjN2D4BeELPUON8=
+github.com/hashicorp/vault-plugin-auth-azure v0.18.0 h1:jQcbAWvEP2fFbmlomA6fnIGRhW5EZqat4NYNcmZUjOY=
+github.com/hashicorp/vault-plugin-auth-azure v0.18.0/go.mod h1:ioz9EmeUGS+nIJkcfrnkGa1Bs/FtwT2BdnlgL0tKSUw=
+github.com/hashicorp/vault-plugin-auth-cf v0.18.0 h1:UGfzrjgGS6kxpXLXx5ym1qkgyGHS2vn5r/LOBsRTNdA=
+github.com/hashicorp/vault-plugin-auth-cf v0.18.0/go.mod h1:tibzfC+K4587UzHH9468DizyQRIlAFXq3EnEVyfX83c=
+github.com/hashicorp/vault-plugin-auth-gcp v0.18.0 h1:chiaa1NLN/B2fcoN/WY/YWVxB8F+hE5koudzLWQcG2c=
+github.com/hashicorp/vault-plugin-auth-gcp v0.18.0/go.mod h1:HtXlc4HKAmUe8/WE4hP0dirpkq4joxhvm8EZ/TvOZk0=
+github.com/hashicorp/vault-plugin-auth-jwt v0.21.1 h1:SFk4j5AbXnKm3csXGCy61W7TrJmHK1vPnEwcH4GrMrg=
+github.com/hashicorp/vault-plugin-auth-jwt v0.21.1/go.mod h1:ggLUt/LHQ+H8GbfvLWSmw+rmujHaUvZ5g9pu4JCBoz8=
+github.com/hashicorp/vault-plugin-auth-kerberos v0.12.0 h1:zJF5jyIwDSqvze2QZ+ONE9k8p8GSql6+4aWSzDrCIUM=
+github.com/hashicorp/vault-plugin-auth-kerberos v0.12.0/go.mod h1:SHMeHUVjgH5lmmCukxEQiVsib8dQnMuhGJgwv5So7oI=
+github.com/hashicorp/vault-plugin-auth-kubernetes v0.19.0 h1:zJLrTPyVp62BEDrK3+ZimyELCx0ShBBQppFnloy/fJ8=
+github.com/hashicorp/vault-plugin-auth-kubernetes v0.19.0/go.mod h1:JHa4MgsZh6PopoDW4kyRi1E/F9g8eYLavyvva7z0llU=
+github.com/hashicorp/vault-plugin-auth-oci v0.16.0 h1:V8vz5b/rqo16cKuvczv8s6n5w6R3ebVEw71fSFlgbVs=
+github.com/hashicorp/vault-plugin-auth-oci v0.16.0/go.mod h1:BFcFkE1w2uPvQG52a2ZT7XsFENr0W2N7y4FwTqvDk/c=
+github.com/hashicorp/vault-plugin-database-couchbase v0.11.0 h1:SH+/CQUZayrmgqgozeyM8Ctz6i6ZkwT/q7fyB5OKFfg=
+github.com/hashicorp/vault-plugin-database-couchbase v0.11.0/go.mod h1:R4KHWLLyQhHUACZuFJqlNFasbm3hoDyF/kruiUvTEmM=
+github.com/hashicorp/vault-plugin-database-elasticsearch v0.15.0 h1:RGH87sxehWL74/JsEV8BacmErLeNRfxg6Pv1tudjGFU=
+github.com/hashicorp/vault-plugin-database-elasticsearch v0.15.0/go.mod h1:LYqjVkcdXvGCPDdYNeOM0j3MqWSkMAWeZ4r++Xn+tS8=
+github.com/hashicorp/vault-plugin-database-mongodbatlas v0.12.0 h1:SQLOOQcF/BuKXh/6AnVYTbCrwyK9MlqzP6AVaqZBAMA=
+github.com/hashicorp/vault-plugin-database-mongodbatlas v0.12.0/go.mod h1:++CfUO0B7GQk2dy6nawWVMcNHKdA1nhxoZx6dbMbudI=
github.com/hashicorp/vault-plugin-database-redis v0.3.0 h1:chSbAsc7cYkn5ajQ/528nKoCm9ExGpJaDjTDos2IUa4=
github.com/hashicorp/vault-plugin-database-redis v0.3.0/go.mod h1:Tr6VELF9q/VAslIO7+ROykrzrvEONVaONrcsthX9qcY=
-github.com/hashicorp/vault-plugin-database-redis-elasticache v0.3.0 h1:8sNYuHOxpUxcq1pxhR4HdYfZIaeEVCiWV5lV25u10ic=
-github.com/hashicorp/vault-plugin-database-redis-elasticache v0.3.0/go.mod h1:IoJwgHiY1vvIbBWO/lidH6wN85jVGnY4k78tZe1jctU=
-github.com/hashicorp/vault-plugin-database-snowflake v0.10.0 h1:XmGY3YsEwhs/LHHO6I9MmiHcI0peL31cQCbHMCniMro=
-github.com/hashicorp/vault-plugin-database-snowflake v0.10.0/go.mod h1:COMbAUyRr1KgNLv0R3n0/olFoy3JkXq57VYd5+9ulPw=
+github.com/hashicorp/vault-plugin-database-redis-elasticache v0.4.0 h1:kU6zic2/iIo40kUKzRvTIj1TozcC1T0sqkWimV5e290=
+github.com/hashicorp/vault-plugin-database-redis-elasticache v0.4.0/go.mod h1:KQmyYsR5CfoTPSjQqXq6TO9QqucESSga9f+bph+Rx74=
+github.com/hashicorp/vault-plugin-database-snowflake v0.11.0 h1:LsBrVl6/bHtn2kCyPAU+ki33iHPBMrOFVzzRvDt3c1g=
+github.com/hashicorp/vault-plugin-database-snowflake v0.11.0/go.mod h1:F4+eKtsa3yTdpGh0OfAvtpLodWt//NSIKZ7gDnqzqqc=
github.com/hashicorp/vault-plugin-mock v0.16.1 h1:5QQvSUHxDjEEbrd2REOeacqyJnCLPD51IQzy71hx8P0=
github.com/hashicorp/vault-plugin-mock v0.16.1/go.mod h1:83G4JKlOwUtxVourn5euQfze3ZWyXcUiLj2wqrKSDIM=
-github.com/hashicorp/vault-plugin-secrets-ad v0.17.0 h1:yXyjHkFduORBwI6g9GxIorXXKRb/wTwbMLkFEgnqzso=
-github.com/hashicorp/vault-plugin-secrets-ad v0.17.0/go.mod h1:HXT1QFK8wN+HYhWWPAIVYSXnNuBqUDM2TsRgiJT6qUc=
-github.com/hashicorp/vault-plugin-secrets-alicloud v0.16.0 h1:rkMe/n9/VylQEm7QeNXgdUaESvLz5UjkokMH1WkFiKU=
-github.com/hashicorp/vault-plugin-secrets-alicloud v0.16.0/go.mod h1:xkGzU7LrkgoRhdN2NwLsshqCpjPz2aqkMVzqS6JKJeg=
-github.com/hashicorp/vault-plugin-secrets-azure v0.17.2 h1:k1IQ6T5I+AkeEw0HI1yRsulCqfMUVm/S7T/gYIogXp0=
-github.com/hashicorp/vault-plugin-secrets-azure v0.17.2/go.mod h1:R4SSIIC5/NPpeV7GO1ZQ9z0cLUNufAAVi+oO7bpguUM=
-github.com/hashicorp/vault-plugin-secrets-gcp v0.18.0 h1:RPKGn6Ai/t4QtdCWg9W7VYTe44cN3jDxgtobTsHHfqE=
-github.com/hashicorp/vault-plugin-secrets-gcp v0.18.0/go.mod h1:b5ZdWNoPDo64g5mp16U6UVPTqCU3gKNIZ7Knc//uypg=
-github.com/hashicorp/vault-plugin-secrets-gcpkms v0.16.0 h1:1wEYeplJl/9FLwBQSmfpqMdKKwmNz/b3e6K9ZOdJK/s=
-github.com/hashicorp/vault-plugin-secrets-gcpkms v0.16.0/go.mod h1:dTyKQItGjGeCnjdWZtO+LPIpzi192uEwk8UxP/R3rMQ=
-github.com/hashicorp/vault-plugin-secrets-kubernetes v0.7.0 h1:IRsrGZyYjecQrAvpKXodQDus4oQRpGDUsQiyJ8Szlmk=
-github.com/hashicorp/vault-plugin-secrets-kubernetes v0.7.0/go.mod h1:StJ4o4D+ChaQ3lKzaWB5CAGDx62ONP9pDFr7iK8i9HU=
-github.com/hashicorp/vault-plugin-secrets-kv v0.18.0 h1:pho3GabXdDp8KM0UTNG88W0yEVrif4GtlS03EJa6uGo=
-github.com/hashicorp/vault-plugin-secrets-kv v0.18.0/go.mod h1:RWDJ382+SsTX/s+zfxkjkvIf9ckCUOhzJbg5AVRdNVY=
-github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.11.0 h1:NU7X28xzc/WBY0jMJNnan+elmKFWv/n5zbWXHfKf9/I=
-github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.11.0/go.mod h1:l6kmbSsAVTrzhsliH283dTo9LYZ4ClPMbBgEyWiUtz8=
-github.com/hashicorp/vault-plugin-secrets-openldap v0.12.1 h1:8BSRXpPplF15ZL77vIQFi9+8zUmbVWjHpdEmkIaqVLg=
-github.com/hashicorp/vault-plugin-secrets-openldap v0.12.1/go.mod h1:epAxjKFROBOI5rUg/8UgRmQlboR4l0AMoAPP5Mx9qkI=
-github.com/hashicorp/vault-plugin-secrets-terraform v0.7.5 h1:nyhdeSdkcb5ZT0drFaW3IePL0aUmcVTzuOToG7RjHwY=
-github.com/hashicorp/vault-plugin-secrets-terraform v0.7.5/go.mod h1:mVZiKjHtll1vqOvThL6F29W1DM2DK5FerAmO7SNz/VE=
+github.com/hashicorp/vault-plugin-secrets-ad v0.18.0 h1:amSAV4+W3wBWfuOQk1TA8lHETsrQ7c8PC2PDjroRQMI=
+github.com/hashicorp/vault-plugin-secrets-ad v0.18.0/go.mod h1:Dz4s3LTMaZg1wZs41Zqe0vAW19c0HSUzQN36yGzzO+U=
+github.com/hashicorp/vault-plugin-secrets-alicloud v0.17.0 h1:b8mTj3e/3JgkEpBFq3Qwp1gH1/YwU4vJHFohVJqWs08=
+github.com/hashicorp/vault-plugin-secrets-alicloud v0.17.0/go.mod h1:9eT3ysHGq0jIarcJFcb9rZoaVbQoAsG3Iug8KM9H83w=
+github.com/hashicorp/vault-plugin-secrets-azure v0.19.2 h1:/9eARO5fffhRh7/oLVgdKlylTl9mQuk5oXUVksvUjH8=
+github.com/hashicorp/vault-plugin-secrets-azure v0.19.2/go.mod h1:R8CJArW9qdsp7ycyKndTaHo7Zj4vXjFMgMXchr/ct1s=
+github.com/hashicorp/vault-plugin-secrets-gcp v0.19.0 h1:5FRAVA3JYpn7zDMebQ3V622NxMKtY6tJg3YDuvTzS3A=
+github.com/hashicorp/vault-plugin-secrets-gcp v0.19.0/go.mod h1:/xdangTVszef3HQdZ0Ct2MmokRuYSpjx/SyX7aWxTbg=
+github.com/hashicorp/vault-plugin-secrets-gcpkms v0.17.0 h1:GeARWON8OFWZFsulNOQqvDRG2H/38l9ye35VFk5MO1g=
+github.com/hashicorp/vault-plugin-secrets-gcpkms v0.17.0/go.mod h1:IQl89mmTl+GISbF16Rxr2d8YCfUfEdLeZJkV2rjuZCQ=
+github.com/hashicorp/vault-plugin-secrets-kubernetes v0.8.0 h1:PhLMvNO+VbTYzX04tZDkgQIrBxjDBYTbVFQsa7qbE84=
+github.com/hashicorp/vault-plugin-secrets-kubernetes v0.8.0/go.mod h1:idMLjrXasvIFI1DclLprHkbz3KrJtTd2Cq5jOYMr6WE=
+github.com/hashicorp/vault-plugin-secrets-kv v0.19.0 h1:vF38KPiu0pDK/WZYRPE4M9hmHd4EvO5Opkuokv+lkIE=
+github.com/hashicorp/vault-plugin-secrets-kv v0.19.0/go.mod h1:CxMY+Q23bIbkFk5dj+D9yI5fJ2uHQfpUiua11xo6mHM=
+github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.12.0 h1:zbddJmujV0YrtePRSeCsXxfloL0RbDyLhQsJ6l3yjrw=
+github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.12.0/go.mod h1:SFCvcu7ypRUcsuSC3DPUu7BFFhGOTwmZfiIRz3zBinE=
+github.com/hashicorp/vault-plugin-secrets-openldap v0.13.0 h1:FZ6kuNa2QU6V42khklnuXfMCwAvSOkCy24235UNQceM=
+github.com/hashicorp/vault-plugin-secrets-openldap v0.13.0/go.mod h1:s8mEVRoufS+ukZEPOgnmZbJia9LHibGZraGyvoF9B34=
+github.com/hashicorp/vault-plugin-secrets-terraform v0.9.0 h1:fEzcmdwxVKJoPaF4kgrxX5/riEqaGEIluJ9AetCpsTM=
+github.com/hashicorp/vault-plugin-secrets-terraform v0.9.0/go.mod h1:I/SuXxfo/J9YedVRAdT3MO7u4l3S8AsMKxvY0IAtGYk=
github.com/hashicorp/vault-testing-stepwise v0.1.4 h1:Lsv1KdpQyjhvmLgKeH65FG5MmY5hMkF5LoX3xIxurjg=
github.com/hashicorp/vault-testing-stepwise v0.1.4/go.mod h1:Ym1T/kMM2sT6qgCIIJ3an7uaSWCJ8O7ohsWB9UiB5tI=
github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77 h1:Y/+BtwxmRak3Us9jrByARvYW6uNeqZlEpMylIdXVIjY=
github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77/go.mod h1:a2crHoMWwY6aiL8GWT8hYj7vKD64uX0EdRPbnsHF5wU=
github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw=
github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo=
-github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
-github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
+github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
-github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
-github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb v1.7.6/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
-github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
-github.com/intel/goresctrl v0.3.0/go.mod h1:fdz3mD85cmP9sHD8JUlrNWAxvwM86CrbmVXltEKd7zk=
-github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
-github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
@@ -2619,7 +1635,6 @@ 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.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w=
github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
@@ -2637,7 +1652,6 @@ 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.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag=
github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
@@ -2656,7 +1670,6 @@ github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08
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.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA=
github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
@@ -2685,29 +1698,20 @@ github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2 h1:mex1izRBCD+7Wj
github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2/go.mod h1:xkfESuHriIekR+4RoV+fu91j/CfnYM29Zi2tMFw5iD4=
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f h1:E87tDTVS5W65euzixn7clSzK66puSt1H4I5SC0EmHH4=
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f/go.mod h1:3J2qVK16Lq8V+wfiL2lPeDZ7UWMxk5LemerHa1p6N00=
-github.com/jefferai/jsonx v1.0.0 h1:Xoz0ZbmkpBvED5W9W1B5B/zc3Oiq7oXqiW7iRV3B6EI=
-github.com/jefferai/jsonx v1.0.0/go.mod h1:OGmqmi2tTeI/PS+qQfBDToLHHJIy/RMp24fPo8vFvoQ=
+github.com/jefferai/jsonx v1.0.1 h1:GvWkLWihoLqDG0BSP45TUQJH9qsINX50PVrFULgpc/I=
+github.com/jefferai/jsonx v1.0.1/go.mod h1:yFo3l2fcm7cZVHGq3HKLXE+Pd4RWuRjNBDHksM7XekQ=
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.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/jimlambrt/gldap v0.1.13 h1:jxmVQn0lfmFbM9jglueoau5LLF/IGRti0SKf0vB753M=
github.com/jimlambrt/gldap v0.1.13/go.mod h1:nlC30c7xVphjImg6etk7vg7ZewHCCvl1dfAhO3ZJzPg=
-github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
-github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
-github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 h1:hgVxRoDDPtQE68PT4LFvNlPz2nBKd3OMlGKIQ69OmR4=
@@ -2717,13 +1721,9 @@ github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d/go.mod h1:b+Q3v8Yr
github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA=
github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f h1:ENpDacvnr8faw5ugQmEF1QYk+f/Y9lXFvuYmRxykago=
github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f/go.mod h1:KDSfL7qe5ZfQqvlDMkVjCztbmcpp/c8M77vhQP8ZPvk=
-github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
-github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
@@ -2732,7 +1732,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
@@ -2745,53 +1744,28 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
-github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
-github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
-github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
-github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
+github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
-github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
-github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.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.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
-github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
-github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
-github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
-github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
-github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
-github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
-github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY=
-github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
-github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -2801,23 +1775,15 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/linode/linodego v0.7.1 h1:4WZmMpSA2NRwlPZcc0+4Gyn7rr99Evk9bnr0B3gXRKE=
github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY=
-github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
-github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
-github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw=
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -2831,7 +1797,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -2840,119 +1805,75 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
-github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
-github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
-github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
-github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
-github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/mediocregopher/radix/v4 v4.1.4 h1:Uze6DEbEAvL+VHXUEu/EDBTkUk5CLct5h3nVSGpc6Ts=
github.com/mediocregopher/radix/v4 v4.1.4/go.mod h1:ajchozX/6ELmydxWeWM6xCFHVpZ4+67LXHOTOVR0nCE=
-github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
-github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/michaelklishin/rabbit-hole/v2 v2.12.0 h1:946p6jOYFcVJdtBBX8MwXvuBkpPjwm1Nm2Qg8oX+uFk=
github.com/michaelklishin/rabbit-hole/v2 v2.12.0/go.mod h1:AN/3zyz7d++OHf+4WUo/LR0+Q5nlPHMaXasIsG/mPY0=
github.com/microsoft/go-mssqldb v1.5.0 h1:CgENxkwtOBNj3Jg6T1X209y2blCfTTcwuOlznd2k9fk=
github.com/microsoft/go-mssqldb v1.5.0/go.mod h1:lmWsjHD8XX/Txr0f8ZqgbEZSC+BZjmEQy/Ms+rLrvho=
-github.com/microsoft/kiota-abstractions-go v1.5.6 h1:3hd1sACWB2B9grv8KG1T8g/gGQ4A8kTLv91OUxHSxkE=
-github.com/microsoft/kiota-abstractions-go v1.5.6/go.mod h1:2WX7Oh8V9SAdZ80OGeE53rcbdys54Pd38rAeDUghrpM=
-github.com/microsoft/kiota-authentication-azure-go v1.0.1 h1:F4HH+2QQHSecQg50gVEZaUcxA8/XxCaC2oOMYv2gTIM=
-github.com/microsoft/kiota-authentication-azure-go v1.0.1/go.mod h1:IbifJeoi+sULI0vjnsWYSmDu5atFo/4FZ6WCoAkPjsc=
-github.com/microsoft/kiota-http-go v1.1.1 h1:W4Olo7Z/MwNZCfkcvH/5eLhnn7koRBMMRhLEnf5MPKo=
-github.com/microsoft/kiota-http-go v1.1.1/go.mod h1:QzhhfW5xkoUuT+/ohflpHJvumWeXIxa/Xl0GmQ2M6mY=
+github.com/microsoft/kiota-abstractions-go v1.6.0 h1:qbGBNMU0/o5myKbikCBXJFohVCFrrpx2cO15Rta2WyA=
+github.com/microsoft/kiota-abstractions-go v1.6.0/go.mod h1:7YH20ZbRWXGfHSSvdHkdztzgCB9mRdtFx13+hrYIEpo=
+github.com/microsoft/kiota-authentication-azure-go v1.0.2 h1:tClGeyFZJ+4Bakf8u0euPM4wqy4ethycdOgx3jyH3pI=
+github.com/microsoft/kiota-authentication-azure-go v1.0.2/go.mod h1:aTcti0bUJEcq7kBfQG4Sr4ElvRNuaalXcFEu4iEyQ6M=
+github.com/microsoft/kiota-http-go v1.3.1 h1:S+ZDxE7Pc/Z06hbfqpFHkoq5xiC8/7d12iNovcgl+7o=
+github.com/microsoft/kiota-http-go v1.3.1/go.mod h1:4QjB+as08swnZXZLx5I+ZHZ8U/tVy7Zu49RNTmWgw48=
github.com/microsoft/kiota-serialization-form-go v1.0.0 h1:UNdrkMnLFqUCccQZerKjblsyVgifS11b3WCx+eFEsAI=
github.com/microsoft/kiota-serialization-form-go v1.0.0/go.mod h1:h4mQOO6KVTNciMF6azi1J9QB19ujSw3ULKcSNyXXOMA=
-github.com/microsoft/kiota-serialization-json-go v1.0.5 h1:DKLs/zcRlY+UrcmI8bCprqYeh3UKfbgbzwy/H2elrmM=
-github.com/microsoft/kiota-serialization-json-go v1.0.5/go.mod h1:SgAmhkzRPX1cjnzEWTv988IcBet7wbr4y6y014l5Y1w=
+github.com/microsoft/kiota-serialization-json-go v1.0.7 h1:yMbckSTPrjZdM4EMXgzLZSA3CtDaUBI350u0VoYRz7Y=
+github.com/microsoft/kiota-serialization-json-go v1.0.7/go.mod h1:1krrY7DYl3ivPIzl4xTaBpew6akYNa8/Tal8g+kb0cc=
github.com/microsoft/kiota-serialization-multipart-go v1.0.0 h1:3O5sb5Zj+moLBiJympbXNaeV07K0d46IfuEd5v9+pBs=
github.com/microsoft/kiota-serialization-multipart-go v1.0.0/go.mod h1:yauLeBTpANk4L03XD985akNysG24SnRJGaveZf+p4so=
github.com/microsoft/kiota-serialization-text-go v1.0.0 h1:XOaRhAXy+g8ZVpcq7x7a0jlETWnWrEum0RhmbYrTFnA=
github.com/microsoft/kiota-serialization-text-go v1.0.0/go.mod h1:sM1/C6ecnQ7IquQOGUrUldaO5wj+9+v7G2W3sQ3fy6M=
-github.com/microsoftgraph/msgraph-sdk-go v1.32.0 h1:nWhgHiCYAuctf9j/2S84um23tU1fAg+jBoAF5QefoxE=
-github.com/microsoftgraph/msgraph-sdk-go v1.32.0/go.mod h1:YDj5bLJkl2kMu50iwG5b3PKGmkUsF26Wto5heVGVfNQ=
-github.com/microsoftgraph/msgraph-sdk-go-core v1.0.1 h1:uq4qZD8VXLiNZY0t4NoRpLDoEiNYJvAQK3hc0ZMmdxs=
-github.com/microsoftgraph/msgraph-sdk-go-core v1.0.1/go.mod h1:HUITyuFN556+0QZ/IVfH5K4FyJM7kllV6ExKi2ImKhE=
+github.com/microsoftgraph/msgraph-sdk-go v1.42.0 h1:AJ/8hJl9lSIKSKaa/+8AxHslpt8QR5z03rHxw4GlsqM=
+github.com/microsoftgraph/msgraph-sdk-go v1.42.0/go.mod h1:u/ciVhK5eBqzQvsVnTVdeEl+Jgy9WbUoUHHKgcw54hk=
+github.com/microsoftgraph/msgraph-sdk-go-core v1.1.0 h1:NB7c/n4Knj+TLaLfjsahhSqoUqoN/CtyNB0XIe/nJnM=
+github.com/microsoftgraph/msgraph-sdk-go-core v1.1.0/go.mod h1:M3w/5IFJ1u/DpwOyjsjNSVEA43y1rLOeX58suyfBhGk=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
-github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
-github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
-github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a h1:eU8j/ClY2Ty3qdHnn0TyW3ivFoPC/0F1gQZz8yTxbbE=
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a/go.mod h1:v8eSC2SMp9/7FTKUncp7fH9IwPfw+ysMObcEz5FWheQ=
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
-github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
-github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
-github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
-github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
-github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
-github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
-github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
-github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
-github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw=
github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
-github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
-github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
-github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
-github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
-github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
-github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
-github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
-github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
-github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
-github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
-github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
-github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
-github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
-github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
-github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -2963,135 +1884,59 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
-github.com/mongodb-forks/digest v1.0.5 h1:EJu3wtLZcA0HCvsZpX5yuD193/sW9tHiNvrEM5apXMk=
-github.com/mongodb-forks/digest v1.0.5/go.mod h1:rb+EX8zotClD5Dj4NdgxnJXG9nwrlx3NWKJ8xttz1Dg=
-github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
-github.com/montanaflynn/stats v0.7.0 h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY/JU=
-github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
+github.com/mongodb-forks/digest v1.1.0 h1:7eUdsR1BtqLv0mdNm4OXs6ddWvR4X2/OsLwdKksrOoc=
+github.com/mongodb-forks/digest v1.1.0/go.mod h1:rb+EX8zotClD5Dj4NdgxnJXG9nwrlx3NWKJ8xttz1Dg=
+github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
+github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
-github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
-github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
github.com/ncw/swift v1.0.47 h1:4DQRPj35Y41WogBxyhOXlrI37nzGlyEcsforeudyYPQ=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
-github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s=
github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
-github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M=
-github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
-github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/okta/okta-sdk-golang/v2 v2.12.1 h1:U+smE7trkHSZO8Mval3Ow85dbxawO+pMAr692VZq9gM=
github.com/okta/okta-sdk-golang/v2 v2.12.1/go.mod h1:KRoAArk1H216oiRnQT77UN6JAhBOnOWkK27yA1SM7FQ=
-github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.0-20180130162743-b8a9be070da4/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
-github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
-github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
-github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
-github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
-github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
-github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
-github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
-github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
-github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
-github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
-github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
-github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
-github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
-github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
-github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
-github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
-github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
-github.com/open-policy-agent/opa v0.42.2/go.mod h1:MrmoTi/BsKWT58kXlVayBb+rYVeaMwuBm3nYAN3923s=
-github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
-github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
-github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
-github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
-github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
-github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
-github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
-github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
-github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runc v1.2.0-rc.1 h1:SMjop2pxxYRTfKdsigna/8xRoaoCfIQfD2cVuOb64/o=
github.com/opencontainers/runc v1.2.0-rc.1/go.mod h1:m9JwxfHzXz5YTTXBQr7EY9KTuazFAGPyMQx2nRR3vTw=
-github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
-github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
-github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
-github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
-github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
-github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
-github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
-github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
-github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
-github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
@@ -3115,34 +1960,26 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
-github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
-github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
-github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
+github.com/peteski22/go-proxyproto v1.0.0 h1:838NKdKEeViAMkaz08Pe+lvvAnGLYhZ0M0z246iCYv0=
+github.com/peteski22/go-proxyproto v1.0.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
-github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
-github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw=
-github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -3156,73 +1993,40 @@ github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXq
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
-github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
-github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=
-github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d h1:PinQItctnaL2LtkaSM678+ZLLy5TajwOeXzWvYC7tII=
github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
-github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
-github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
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.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
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_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
-github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
-github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
-github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
+github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
-github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
-github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
-github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
-github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
+github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
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.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
-github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
-github.com/prometheus/common v0.49.0 h1:ToNTdK4zSnPVJmh698mGFkDor9wBI/iGaJy5dbH1EgI=
-github.com/prometheus/common v0.49.0/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE=
-github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
+github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
-github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
-github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
+github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rboyer/safeio v0.2.1 h1:05xhhdRNAdS3apYm7JRjOqngf4xruaW959jmRxGDuSU=
github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy7Fmig=
-github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
-github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o=
github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
@@ -3231,44 +2035,29 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
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/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
-github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
-github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
-github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
-github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
-github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ=
github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
-github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
-github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/sean-/conswriter v0.0.0-20180208195008-f5ae3917a627/go.mod h1:7zjs06qF79/FKAJpBvFx3P8Ww4UTIMAe+lpNXDHziac=
github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6qbIiqJ6/Bqeq25bCLbL7YFmpaFfJDuM=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
-github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
-github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
@@ -3281,18 +2070,13 @@ github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk=
github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
-github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
@@ -3301,20 +2085,17 @@ github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EE
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/snowflakedb/gosnowflake v1.7.2 h1:HRSwva8YXC64WUppfmHcMNVVzSE1+EwXXaJxgS0EkTo=
-github.com/snowflakedb/gosnowflake v1.7.2/go.mod h1:03tW856vc3ceM4rJuj7KO4dzqN7qoezTm+xw7aPIIFo=
+github.com/snowflakedb/gosnowflake v1.10.0 h1:5hBGKa/jJEhciokzgJcz5xmLNlJ8oUm8vhfu5tg82tM=
+github.com/snowflakedb/gosnowflake v1.10.0/go.mod h1:WC4eGUOH3K9w3pLsdwZsdawIwtWgse4kZPPqNG0Ky/k=
github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d h1:bVQRCxQvfjNUeRqaY/uT0tFuvuFY0ulgnczuR684Xic=
github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
@@ -3325,32 +2106,18 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
-github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
-github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
-github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
-github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
-github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
-github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
-github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
-github.com/std-uritemplate/std-uritemplate/go v0.0.50 h1:LAE6WYRmLlDXPtEzr152BnD/MHxGCKmcp5D2Pw0NvmU=
-github.com/std-uritemplate/std-uritemplate/go v0.0.50/go.mod h1:CLZ1543WRCuUQQjK0BvPM4QrG2toY8xNZUm8Vbt7vTc=
-github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
-github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
+github.com/std-uritemplate/std-uritemplate/go v0.0.55 h1:muSH037g97K7U2f94G9LUuE8tZlJsoSSrPsO9V281WY=
+github.com/std-uritemplate/std-uritemplate/go v0.0.55/go.mod h1:rG/bqh/ThY4xE5de7Rap3vaDkYUT76B0GPJ0loYeTTc=
github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
@@ -3358,7 +2125,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
-github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -3372,18 +2138,10 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
-github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
-github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
-github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
-github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/tencentcloud/tencentcloud-sdk-go v1.0.162 h1:8fDzz4GuVg4skjY2B0nMN7h6uN61EDVkuLyI2+qGHhI=
github.com/tencentcloud/tencentcloud-sdk-go v1.0.162/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI=
-github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao=
github.com/tilinna/clock v1.1.0 h1:6IQQQCo6KoBxVudv6gwtY8o4eDfhHo8ojA5dP0MfhSs=
github.com/tilinna/clock v1.1.0/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao=
@@ -3391,9 +2149,7 @@ github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03O
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
@@ -3402,47 +2158,15 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
-github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
-github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
-github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
-github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
-github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
-github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
-github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
-github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
-github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
-github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
-github.com/vektah/gqlparser/v2 v2.4.5/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0=
-github.com/veraison/go-cose v1.0.0-rc.1/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4=
-github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
-github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
-github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
-github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
-github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
-github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
-github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
-github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
-github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo=
github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
-github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
-github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
-github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
-github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
-github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -3450,14 +2174,10 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMc
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
-github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
-github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
-github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -3472,9 +2192,6 @@ github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLC
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
-github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
-github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
-github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY=
github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
@@ -3483,40 +2200,22 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
-go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
-go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
-go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
-go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY=
-go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA=
-go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4=
+go.etcd.io/etcd/api/v3 v3.5.13/go.mod h1:gBqlqkcMMZMVTMm4NDZloEVJzxQOQIls8splbqBDa0c=
go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
-go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg=
-go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY=
-go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
+go.etcd.io/etcd/client/pkg/v3 v3.5.13 h1:RVZSAnWWWiI5IrYAXjQorajncORbS0zI48LQlE2kQWg=
+go.etcd.io/etcd/client/pkg/v3 v3.5.13/go.mod h1:XxHT4u1qU12E2+po+UVPrEeL94Um6zL58ppuJWXSAB8=
go.etcd.io/etcd/client/v2 v2.305.5 h1:DktRP60//JJpnPC0VBymAN/7V71GHMdjDCBt4ZPXDjI=
go.etcd.io/etcd/client/v2 v2.305.5/go.mod h1:zQjKllfqfBVyVStbt4FaosoX2iYd8fV/GRy/PbowgP4=
-go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
-go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c=
-go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4=
-go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw=
-go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE=
-go.etcd.io/etcd/pkg/v3 v3.5.5/go.mod h1:6ksYFxttiUGzC2uxyqiyOEvhAiD0tuIqSZkX3TyPdaE=
-go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc=
-go.etcd.io/etcd/raft/v3 v3.5.5/go.mod h1:76TA48q03g1y1VpTue92jZLr9lIHKUNcYdZOOGyx8rI=
-go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4=
-go.etcd.io/etcd/server/v3 v3.5.5/go.mod h1:rZ95vDw/jrvsbj9XpTqPrTAB9/kzchVdhRirySPkUBc=
-go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M=
+go.etcd.io/etcd/client/v3 v3.5.13 h1:o0fHTNJLeO0MyVbc7I3fsCf6nrOqn5d+diSarKnB2js=
+go.etcd.io/etcd/client/v3 v3.5.13/go.mod h1:cqiAeY8b5DEEcpxvgWKsbLIWNM/8Wy2xJSDMtioMcoI=
go.mongodb.org/atlas v0.36.0 h1:m05S3AO7zkl+bcG1qaNsEKBnAqnKx2FDwLooHpIG3j4=
go.mongodb.org/atlas v0.36.0/go.mod h1:nfPldE9dSama6G2IbIzmEza02Ly7yFZjMMVscaM0uEc=
-go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
-go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
-go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
-go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
+go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4=
+go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -3526,80 +2225,24 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0/go.mod h1:5eCOqeGphOyz6TsY3ZDNjE33SM/TFAK3RGuCL2naTgY=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
-go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
-go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU=
-go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
-go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
-go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM=
-go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ=
-go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
-go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
-go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
-go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg=
-go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
-go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
-go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0/go.mod h1:M1hVZHNxcbkAlcvrOMlpQ4YOO3Awf+4N2dxkZL3xm04=
-go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.7.0/go.mod h1:ceUgdyfNv4h4gLxHR0WNfDiiVmZFodZhZSbOLhpxqXE=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
+go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
+go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0/go.mod h1:E+/KKhwOSw8yoPxSSuUHG6vKppkvhN+S1Jc7Nib3k3o=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY=
-go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
-go.opentelemetry.io/otel/metric v0.30.0/go.mod h1:/ShZ7+TS4dHzDFmfi1kSXMhMVubNoP0oIaBp70J6UXU=
-go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A=
-go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
-go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
-go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
-go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
-go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
-go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI=
-go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
-go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
-go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE=
-go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
-go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E=
-go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk=
-go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
-go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
-go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
-go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk=
-go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
-go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
-go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4=
-go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM=
-go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
-go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
-go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk=
+go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
+go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
+go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
+go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
+go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
+go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg=
-go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ=
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
-go.opentelemetry.io/proto/otlp v0.16.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
@@ -3611,12 +2254,9 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
-go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU=
-go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
-go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
-go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
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.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -3628,12 +2268,10 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
-go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
-go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
-golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -3642,52 +2280,32 @@ golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaE
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
-golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
-golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
-golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
-golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
-golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
+golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -3703,8 +2321,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
-golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
-golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
+golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
+golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -3743,22 +2361,16 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
-golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -3772,12 +2384,10 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -3796,11 +2406,9 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -3810,17 +2418,12 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -3833,9 +2436,7 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-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.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
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=
@@ -3843,17 +2444,10 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
-golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
-golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
-golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
-golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
+golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -3884,13 +2478,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
-golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
-golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
-golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
-golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
-golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
-golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
-golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
+golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
+golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
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=
@@ -3907,13 +2496,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
+golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -3933,21 +2517,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -3958,20 +2533,14 @@ golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -3979,26 +2548,12 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/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-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/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-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -4011,18 +2566,14 @@ golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -4030,29 +2581,20 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/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-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -4063,9 +2605,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/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.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -4074,23 +2614,14 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
-golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
+golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
+golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
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.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
@@ -4098,16 +2629,11 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
-golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
-golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
-golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
-golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
+golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
+golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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=
@@ -4125,22 +2651,13 @@ 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/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
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-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -4163,11 +2680,8 @@ golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -4177,7 +2691,6 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -4198,23 +2711,19 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/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-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -4225,21 +2734,13 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
-golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
-golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
-golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
-golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
-golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
-golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
-golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
-golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -4262,7 +2763,6 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6d
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY=
gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo=
-google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@@ -4280,7 +2780,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
@@ -4322,17 +2821,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
-google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E=
-google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
-google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4=
-google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
-google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
-google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750=
-google.golang.org/api v0.134.0/go.mod h1:sjRL3UnjTx5UqNQS9EWr9N8p7xbHpy1k0XGRLCf3Spk=
-google.golang.org/api v0.139.0/go.mod h1:CVagp6Eekz9CjGZ718Z+sloknzkDJE7Vc1Ckj9+viBk=
-google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI=
-google.golang.org/api v0.163.0 h1:4BBDpPaSH+H28NhnX+WwjXxbRLQ7TWuEKp4BQyEjxvk=
-google.golang.org/api v0.163.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0=
+google.golang.org/api v0.181.0 h1:rPdjwnWgiPPOJx3IcSAQ2III5aX5tCer6wMpa/xmZi4=
+google.golang.org/api v0.181.0/go.mod h1:MnQ+M0CFsfUwA5beZ+g/vCBCPXvtmZwRz2qzZk8ih1k=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -4340,16 +2830,12 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
-google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
-google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
@@ -4358,7 +2844,6 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
@@ -4373,15 +2858,12 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfG
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-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -4413,7 +2895,6 @@ google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
@@ -4482,80 +2963,19 @@ google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVix
google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
-google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
-google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY=
-google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
-google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
-google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
-google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
-google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
-google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0=
-google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108=
-google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
-google.golang.org/genproto v0.0.0-20230821184602-ccc8af3d0e93/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
-google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
-google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
-google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:CCviP9RmpZ1mxVr8MUjCnSiY09IbAXZxhLE6EhHIdPU=
-google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk=
-google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:EMfReVxb80Dq1hhioy0sOsY9jCE46YDgHlJ7fWVUWRE=
-google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI=
-google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405/go.mod h1:3WDQMjmJk36UQhjQ89emUzb1mdaHcPeeAh4SCBKznB4=
-google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
-google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe h1:USL2DhxfgRchafRvt/wYyyQNzwgL7ZiURcozOE/Pkvo=
-google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
-google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8=
-google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
-google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
-google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
-google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
-google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ=
-google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
-google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
-google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q=
-google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
-google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
-google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U=
-google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0=
-google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww=
-google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870=
-google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405/go.mod h1:oT32Z4o8Zv2xPQTg0pbVaPr0MPOH6f14RgXt7zfIpwg=
-google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
-google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8=
-google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
-google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA=
-google.golang.org/genproto/googleapis/bytestream v0.0.0-20230720185612-659f7aaaa771/go.mod h1:3QoBVwTHkXbY1oRGzlhwhOykfcATQN43LJ6iT8Wy8kE=
-google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577/go.mod h1:NjCQG/D8JandXxM57PZbAJL1DCNL6EypA0vPPwfsc7c=
-google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405/go.mod h1:GRUCuLdzVqZte8+Dl/D4N25yLzcGqqWaYkeVOwulFqw=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230920183334-c177e329c48b/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
-google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5 h1:IGsMFz879l+GhhDJ9fN5rWnkVrGnoZv8oeYfpk82QZQ=
+google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:ch5ZrEj5+9MCxUeR3Gp3mCJ4u0eVpusYAmSr/mvpMSk=
+google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf h1:GillM0Ef0pkZPIB+5iO6SDK+4T9pf6TpaYR6ICD5rVE=
+google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:OFMYQFHJ4TM3JRlWDZhJbZfra2uqc3WLBZiaaqP4DtU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 h1:V71AcdLZr2p8dC9dbOIMCpqi4EmRl8wUwnJzXXLmbmc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@@ -4580,7 +3000,6 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
@@ -4591,22 +3010,12 @@ google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
-google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
-google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
-google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
-google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
-google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
-google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
-google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
-google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
-google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
-google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
-google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
-google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY=
-google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
+google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
+google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
+google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
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=
@@ -4623,44 +3032,35 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.28.2-0.20230222093303-bc1253ad3743/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
-google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
-google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
+gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
+gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
-gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI=
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
-gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/ory-am/dockertest.v3 v3.3.4 h1:oen8RiwxVNxtQ1pRoV4e4jqh6UjNsOuIZ1NXns6jdcw=
gopkg.in/ory-am/dockertest.v3 v3.3.4/go.mod h1:s9mmoLkaGeAh97qygnNj4xWkiN7e1SKekYC6CovU+ek=
gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
-gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
-gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
-gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
@@ -4678,18 +3078,12 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
-gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
-gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
-gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
-gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -4701,87 +3095,24 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
-k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
-k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
-k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
-k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs=
-k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU=
-k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw=
-k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ=
+k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
+k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
-k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
-k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
-k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
-k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
-k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U=
-k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
-k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
-k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc=
-k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
-k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
-k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
-k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
-k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ=
-k8s.io/apiserver v0.26.2/go.mod h1:GHcozwXgXsPuOJ28EnQ/jXEM9QeG6HT22YxSNmpYNh8=
+k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
+k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
-k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
-k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
-k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
-k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y=
-k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU=
-k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A=
-k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks=
-k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
-k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
-k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
-k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
-k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI=
-k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs=
-k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
-k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
-k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
-k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
-k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4=
-k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc=
-k8s.io/cri-api v0.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU=
-k8s.io/cri-api v0.27.1/go.mod h1:+Ts/AVYbIo04S86XbTD73UPp/DkTiYxtsFeOFEu32L0=
+k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
+k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
-k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
-k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
-k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
-k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
-k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
-k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
-k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
-k8s.io/kms v0.26.2/go.mod h1:69qGnf1NsFOQP07fBYqNLZklqEHSJF024JqYCaeVxHg=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
-k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
-k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
-k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
-k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
-k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
-k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
-k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
-k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
layeh.com/radius v0.0.0-20231213012653-1006025d24f8 h1:orYXpi6BJZdvgytfHH4ybOe4wHnLbbS71Cmd8mWdZjs=
@@ -4791,17 +3122,12 @@ lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
-modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20=
-modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
-modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI=
modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws=
modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo=
-modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g=
-modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
@@ -4811,55 +3137,30 @@ modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0=
modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s=
-modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA=
-modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0=
-modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
-modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
-modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
-modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
-modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
-modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4=
-modernc.org/sqlite v1.18.2/go.mod h1:kvrTLEWgxUcHa2GfHBQtanR1H9ht3hTJNtKpzH9k1u0=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw=
-modernc.org/tcl v1.13.2/go.mod h1:7CLiGIPo1M8Rv1Mitpv5akc2+8fxUd2y2UzC/MfMzy0=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
-modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
-modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
-mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48=
-mvdan.cc/gofumpt v0.2.1/go.mod h1:a/rvZPhsNaedOJBzqRD9omnwVwHZsBdJirXHa9Gh9Ig=
-nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
-nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
-oras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc=
+nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
+nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35/go.mod h1:WxjusMwXlKzfAs4p9km6XJRndVt2FROgMVCE4cdohFo=
-sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
-sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
-sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
-sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
-sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/helper/benchhelpers/benchhelpers.go b/helper/benchhelpers/benchhelpers.go
deleted file mode 100644
index afb0d4a88a..0000000000
--- a/helper/benchhelpers/benchhelpers.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) HashiCorp, Inc.
-// SPDX-License-Identifier: BUSL-1.1
-
-package benchhelpers
-
-import (
- "testing"
-
- testinginterface "github.com/mitchellh/go-testing-interface"
-)
-
-type tbWrapper struct {
- testing.TB
-}
-
-func (b tbWrapper) Parallel() {
- // no-op
-}
-
-func TBtoT(tb testing.TB) testinginterface.T {
- return tbWrapper{tb}
-}
diff --git a/helper/builtinplugins/registry.go b/helper/builtinplugins/registry.go
index 978321c8ad..e5a6044e5f 100644
--- a/helper/builtinplugins/registry.go
+++ b/helper/builtinplugins/registry.go
@@ -6,55 +6,14 @@ package builtinplugins
import (
"context"
- credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
- credAzure "github.com/hashicorp/vault-plugin-auth-azure"
- credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
- credCF "github.com/hashicorp/vault-plugin-auth-cf"
- credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
credJWT "github.com/hashicorp/vault-plugin-auth-jwt"
- credKerb "github.com/hashicorp/vault-plugin-auth-kerberos"
- credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
- credOCI "github.com/hashicorp/vault-plugin-auth-oci"
- dbCouchbase "github.com/hashicorp/vault-plugin-database-couchbase"
- dbElastic "github.com/hashicorp/vault-plugin-database-elasticsearch"
- dbMongoAtlas "github.com/hashicorp/vault-plugin-database-mongodbatlas"
- dbRedis "github.com/hashicorp/vault-plugin-database-redis"
- dbRedisElastiCache "github.com/hashicorp/vault-plugin-database-redis-elasticache"
- dbSnowflake "github.com/hashicorp/vault-plugin-database-snowflake"
- logicalAd "github.com/hashicorp/vault-plugin-secrets-ad/plugin"
- logicalAlicloud "github.com/hashicorp/vault-plugin-secrets-alicloud"
- logicalAzure "github.com/hashicorp/vault-plugin-secrets-azure"
- logicalGcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin"
- logicalGcpKms "github.com/hashicorp/vault-plugin-secrets-gcpkms"
- logicalKube "github.com/hashicorp/vault-plugin-secrets-kubernetes"
logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
- logicalMongoAtlas "github.com/hashicorp/vault-plugin-secrets-mongodbatlas"
- logicalLDAP "github.com/hashicorp/vault-plugin-secrets-openldap"
- logicalTerraform "github.com/hashicorp/vault-plugin-secrets-terraform"
credAppRole "github.com/hashicorp/vault/builtin/credential/approle"
- credAws "github.com/hashicorp/vault/builtin/credential/aws"
credCert "github.com/hashicorp/vault/builtin/credential/cert"
- credGitHub "github.com/hashicorp/vault/builtin/credential/github"
- credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
- credOkta "github.com/hashicorp/vault/builtin/credential/okta"
- credRadius "github.com/hashicorp/vault/builtin/credential/radius"
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
- logicalAws "github.com/hashicorp/vault/builtin/logical/aws"
- logicalConsul "github.com/hashicorp/vault/builtin/logical/consul"
- logicalNomad "github.com/hashicorp/vault/builtin/logical/nomad"
logicalPki "github.com/hashicorp/vault/builtin/logical/pki"
- logicalRabbit "github.com/hashicorp/vault/builtin/logical/rabbitmq"
logicalSsh "github.com/hashicorp/vault/builtin/logical/ssh"
- logicalTotp "github.com/hashicorp/vault/builtin/logical/totp"
logicalTransit "github.com/hashicorp/vault/builtin/logical/transit"
- dbCass "github.com/hashicorp/vault/plugins/database/cassandra"
- dbHana "github.com/hashicorp/vault/plugins/database/hana"
- dbInflux "github.com/hashicorp/vault/plugins/database/influxdb"
- dbMongo "github.com/hashicorp/vault/plugins/database/mongodb"
- dbMssql "github.com/hashicorp/vault/plugins/database/mssql"
- dbMysql "github.com/hashicorp/vault/plugins/database/mysql"
- dbPostgres "github.com/hashicorp/vault/plugins/database/postgresql"
- dbRedshift "github.com/hashicorp/vault/plugins/database/redshift"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/logical"
@@ -94,108 +53,29 @@ func removedFactory(ctx context.Context, config *logical.BackendConfig) (logical
return removedBackend, nil
}
-func newRegistry() *registry {
- reg := ®istry{
+func newMinimalRegistry() *registry {
+ return ®istry{
credentialBackends: map[string]credentialBackend{
- "alicloud": {Factory: credAliCloud.Factory},
- "app-id": {
- Factory: removedFactory,
- DeprecationStatus: consts.Removed,
- },
- "approle": {Factory: credAppRole.Factory},
- "aws": {Factory: credAws.Factory},
- "azure": {Factory: credAzure.Factory},
- "centrify": {
- Factory: credCentrify.Factory,
- DeprecationStatus: consts.Deprecated,
- },
- "cert": {Factory: credCert.Factory},
- "cf": {Factory: credCF.Factory},
- "gcp": {Factory: credGcp.Factory},
- "github": {Factory: credGitHub.Factory},
- "jwt": {Factory: credJWT.Factory},
- "kerberos": {Factory: credKerb.Factory},
- "kubernetes": {Factory: credKube.Factory},
- "ldap": {Factory: credLdap.Factory},
- "oci": {Factory: credOCI.Factory},
- "oidc": {Factory: credJWT.Factory},
- "okta": {Factory: credOkta.Factory},
- "pcf": {
- Factory: credCF.Factory,
- DeprecationStatus: consts.Deprecated,
- },
- "radius": {Factory: credRadius.Factory},
+ "approle": {Factory: credAppRole.Factory},
+ "cert": {Factory: credCert.Factory},
+ "jwt": {Factory: credJWT.Factory},
+ "oidc": {Factory: credJWT.Factory},
"userpass": {Factory: credUserpass.Factory},
},
- databasePlugins: map[string]databasePlugin{
- // These four plugins all use the same mysql implementation but with
- // different username settings passed by the constructor.
- "mysql-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultUserNameTemplate)},
- "mysql-aurora-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)},
- "mysql-rds-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)},
- "mysql-legacy-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)},
-
- "cassandra-database-plugin": {Factory: dbCass.New},
- "couchbase-database-plugin": {Factory: dbCouchbase.New},
- "elasticsearch-database-plugin": {Factory: dbElastic.New},
- "hana-database-plugin": {Factory: dbHana.New},
- "influxdb-database-plugin": {Factory: dbInflux.New},
- "mongodb-database-plugin": {Factory: dbMongo.New},
- "mongodbatlas-database-plugin": {Factory: dbMongoAtlas.New},
- "mssql-database-plugin": {Factory: dbMssql.New},
- "postgresql-database-plugin": {Factory: dbPostgres.New},
- "redshift-database-plugin": {Factory: dbRedshift.New},
- "redis-database-plugin": {Factory: dbRedis.New},
- "redis-elasticache-database-plugin": {Factory: dbRedisElastiCache.New},
- "snowflake-database-plugin": {Factory: dbSnowflake.New},
- },
+ databasePlugins: map[string]databasePlugin{},
logicalBackends: map[string]logicalBackend{
- "ad": {
- Factory: logicalAd.Factory,
- DeprecationStatus: consts.Deprecated,
- },
- "alicloud": {Factory: logicalAlicloud.Factory},
- "aws": {Factory: logicalAws.Factory},
- "azure": {Factory: logicalAzure.Factory},
- "cassandra": {
- Factory: removedFactory,
- DeprecationStatus: consts.Removed,
- },
- "consul": {Factory: logicalConsul.Factory},
- "gcp": {Factory: logicalGcp.Factory},
- "gcpkms": {Factory: logicalGcpKms.Factory},
- "kubernetes": {Factory: logicalKube.Factory},
- "kv": {Factory: logicalKv.Factory},
- "mongodb": {
- Factory: removedFactory,
- DeprecationStatus: consts.Removed,
- },
- // The mongodbatlas secrets engine is not the same as the database plugin equivalent
- // (`mongodbatlas-database-plugin`), and thus will not be deprecated at this time.
- "mongodbatlas": {Factory: logicalMongoAtlas.Factory},
- "mssql": {
- Factory: removedFactory,
- DeprecationStatus: consts.Removed,
- },
- "mysql": {
- Factory: removedFactory,
- DeprecationStatus: consts.Removed,
- },
- "nomad": {Factory: logicalNomad.Factory},
- "openldap": {Factory: logicalLDAP.Factory},
- "ldap": {Factory: logicalLDAP.Factory},
- "pki": {Factory: logicalPki.Factory},
- "postgresql": {
- Factory: removedFactory,
- DeprecationStatus: consts.Removed,
- },
- "rabbitmq": {Factory: logicalRabbit.Factory},
- "ssh": {Factory: logicalSsh.Factory},
- "terraform": {Factory: logicalTerraform.Factory},
- "totp": {Factory: logicalTotp.Factory},
- "transit": {Factory: logicalTransit.Factory},
+ "kv": {Factory: logicalKv.Factory},
+ "pki": {Factory: logicalPki.Factory},
+ "ssh": {Factory: logicalSsh.Factory},
+ "transit": {Factory: logicalTransit.Factory},
},
}
+}
+
+func newRegistry() *registry {
+ reg := newMinimalRegistry()
+
+ extendAddonPlugins(reg)
entAddExtPlugins(reg)
diff --git a/helper/builtinplugins/registry_full.go b/helper/builtinplugins/registry_full.go
new file mode 100644
index 0000000000..32bba40487
--- /dev/null
+++ b/helper/builtinplugins/registry_full.go
@@ -0,0 +1,149 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build !minimal
+
+package builtinplugins
+
+import (
+ "maps"
+
+ credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
+ credAzure "github.com/hashicorp/vault-plugin-auth-azure"
+ credCF "github.com/hashicorp/vault-plugin-auth-cf"
+ credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
+ credKerb "github.com/hashicorp/vault-plugin-auth-kerberos"
+ credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
+ credOCI "github.com/hashicorp/vault-plugin-auth-oci"
+ dbCouchbase "github.com/hashicorp/vault-plugin-database-couchbase"
+ dbElastic "github.com/hashicorp/vault-plugin-database-elasticsearch"
+ dbMongoAtlas "github.com/hashicorp/vault-plugin-database-mongodbatlas"
+ dbRedis "github.com/hashicorp/vault-plugin-database-redis"
+ dbRedisElastiCache "github.com/hashicorp/vault-plugin-database-redis-elasticache"
+ dbSnowflake "github.com/hashicorp/vault-plugin-database-snowflake"
+ logicalAd "github.com/hashicorp/vault-plugin-secrets-ad/plugin"
+ logicalAlicloud "github.com/hashicorp/vault-plugin-secrets-alicloud"
+ logicalAzure "github.com/hashicorp/vault-plugin-secrets-azure"
+ logicalGcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin"
+ logicalGcpKms "github.com/hashicorp/vault-plugin-secrets-gcpkms"
+ logicalKube "github.com/hashicorp/vault-plugin-secrets-kubernetes"
+ logicalMongoAtlas "github.com/hashicorp/vault-plugin-secrets-mongodbatlas"
+ logicalLDAP "github.com/hashicorp/vault-plugin-secrets-openldap"
+ logicalTerraform "github.com/hashicorp/vault-plugin-secrets-terraform"
+ credAws "github.com/hashicorp/vault/builtin/credential/aws"
+ credGitHub "github.com/hashicorp/vault/builtin/credential/github"
+ credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
+ credOkta "github.com/hashicorp/vault/builtin/credential/okta"
+ credRadius "github.com/hashicorp/vault/builtin/credential/radius"
+ logicalAws "github.com/hashicorp/vault/builtin/logical/aws"
+ logicalConsul "github.com/hashicorp/vault/builtin/logical/consul"
+ logicalNomad "github.com/hashicorp/vault/builtin/logical/nomad"
+ logicalRabbit "github.com/hashicorp/vault/builtin/logical/rabbitmq"
+ logicalTotp "github.com/hashicorp/vault/builtin/logical/totp"
+ dbCass "github.com/hashicorp/vault/plugins/database/cassandra"
+ dbHana "github.com/hashicorp/vault/plugins/database/hana"
+ dbInflux "github.com/hashicorp/vault/plugins/database/influxdb"
+ dbMongo "github.com/hashicorp/vault/plugins/database/mongodb"
+ dbMssql "github.com/hashicorp/vault/plugins/database/mssql"
+ dbMysql "github.com/hashicorp/vault/plugins/database/mysql"
+ dbPostgres "github.com/hashicorp/vault/plugins/database/postgresql"
+ dbRedshift "github.com/hashicorp/vault/plugins/database/redshift"
+ "github.com/hashicorp/vault/sdk/helper/consts"
+)
+
+func newFullAddonRegistry() *registry {
+ return ®istry{
+ credentialBackends: map[string]credentialBackend{
+ "alicloud": {Factory: credAliCloud.Factory},
+ "app-id": {
+ Factory: removedFactory,
+ DeprecationStatus: consts.Removed,
+ },
+ "aws": {Factory: credAws.Factory},
+ "azure": {Factory: credAzure.Factory},
+ "cf": {Factory: credCF.Factory},
+ "gcp": {Factory: credGcp.Factory},
+ "github": {Factory: credGitHub.Factory},
+ "kerberos": {Factory: credKerb.Factory},
+ "kubernetes": {Factory: credKube.Factory},
+ "ldap": {Factory: credLdap.Factory},
+ "oci": {Factory: credOCI.Factory},
+ "okta": {Factory: credOkta.Factory},
+ "pcf": {
+ Factory: credCF.Factory,
+ DeprecationStatus: consts.Deprecated,
+ },
+ "radius": {Factory: credRadius.Factory},
+ },
+ databasePlugins: map[string]databasePlugin{
+ // These four plugins all use the same mysql implementation but with
+ // different username settings passed by the constructor.
+ "mysql-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultUserNameTemplate)},
+ "mysql-aurora-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)},
+ "mysql-rds-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)},
+ "mysql-legacy-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)},
+
+ "cassandra-database-plugin": {Factory: dbCass.New},
+ "couchbase-database-plugin": {Factory: dbCouchbase.New},
+ "elasticsearch-database-plugin": {Factory: dbElastic.New},
+ "hana-database-plugin": {Factory: dbHana.New},
+ "influxdb-database-plugin": {Factory: dbInflux.New},
+ "mongodb-database-plugin": {Factory: dbMongo.New},
+ "mongodbatlas-database-plugin": {Factory: dbMongoAtlas.New},
+ "mssql-database-plugin": {Factory: dbMssql.New},
+ "postgresql-database-plugin": {Factory: dbPostgres.New},
+ "redshift-database-plugin": {Factory: dbRedshift.New},
+ "redis-database-plugin": {Factory: dbRedis.New},
+ "redis-elasticache-database-plugin": {Factory: dbRedisElastiCache.New},
+ "snowflake-database-plugin": {Factory: dbSnowflake.New},
+ },
+ logicalBackends: map[string]logicalBackend{
+ "ad": {
+ Factory: logicalAd.Factory,
+ DeprecationStatus: consts.Deprecated,
+ },
+ "alicloud": {Factory: logicalAlicloud.Factory},
+ "aws": {Factory: logicalAws.Factory},
+ "azure": {Factory: logicalAzure.Factory},
+ "cassandra": {
+ Factory: removedFactory,
+ DeprecationStatus: consts.Removed,
+ },
+ "consul": {Factory: logicalConsul.Factory},
+ "gcp": {Factory: logicalGcp.Factory},
+ "gcpkms": {Factory: logicalGcpKms.Factory},
+ "kubernetes": {Factory: logicalKube.Factory},
+ "mongodb": {
+ Factory: removedFactory,
+ DeprecationStatus: consts.Removed,
+ },
+ "mongodbatlas": {Factory: logicalMongoAtlas.Factory},
+ "mssql": {
+ Factory: removedFactory,
+ DeprecationStatus: consts.Removed,
+ },
+ "mysql": {
+ Factory: removedFactory,
+ DeprecationStatus: consts.Removed,
+ },
+ "nomad": {Factory: logicalNomad.Factory},
+ "openldap": {Factory: logicalLDAP.Factory},
+ "ldap": {Factory: logicalLDAP.Factory},
+ "postgresql": {
+ Factory: removedFactory,
+ DeprecationStatus: consts.Removed,
+ },
+ "rabbitmq": {Factory: logicalRabbit.Factory},
+ "terraform": {Factory: logicalTerraform.Factory},
+ "totp": {Factory: logicalTotp.Factory},
+ },
+ }
+}
+
+func extendAddonPlugins(reg *registry) {
+ addonReg := newFullAddonRegistry()
+
+ maps.Copy(reg.credentialBackends, addonReg.credentialBackends)
+ maps.Copy(reg.databasePlugins, addonReg.databasePlugins)
+ maps.Copy(reg.logicalBackends, addonReg.logicalBackends)
+}
diff --git a/helper/builtinplugins/registry_full_test.go b/helper/builtinplugins/registry_full_test.go
new file mode 100644
index 0000000000..23626daf52
--- /dev/null
+++ b/helper/builtinplugins/registry_full_test.go
@@ -0,0 +1,30 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build !enterprise && !minimal
+
+package builtinplugins
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+// Test_newRegistry tests that newRegistry() returns a registry with
+// the expected minimal registry extended with full addon registry
+func Test_newRegistry(t *testing.T) {
+ actual := newRegistry()
+ expMinimal := newMinimalRegistry()
+ expFullAddon := newFullAddonRegistry()
+
+ require.Equal(t, len(expMinimal.credentialBackends)+len(expFullAddon.credentialBackends), len(actual.credentialBackends),
+ "newRegistry() total auth backends mismatch total of minimal and full addon registries")
+ require.Equal(t, len(expMinimal.databasePlugins)+len(expFullAddon.databasePlugins), len(actual.databasePlugins),
+ "newRegistry() total database plugins mismatch total of minimal and full addon registries")
+ require.Equal(t, len(expMinimal.logicalBackends)+len(expFullAddon.logicalBackends), len(actual.logicalBackends),
+ "newRegistry() total logical backends mismatch total of minimal and full addon registries")
+
+ assertRegistrySubset(t, actual, expMinimal, "common")
+ assertRegistrySubset(t, actual, expFullAddon, "full addon")
+}
diff --git a/helper/builtinplugins/registry_min.go b/helper/builtinplugins/registry_min.go
new file mode 100644
index 0000000000..75b281f631
--- /dev/null
+++ b/helper/builtinplugins/registry_min.go
@@ -0,0 +1,10 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+//go:build minimal
+
+package builtinplugins
+
+func extendAddonPlugins(_ *registry) {
+ // No-op
+}
diff --git a/helper/builtinplugins/registry_test.go b/helper/builtinplugins/registry_test.go
index 0602ec8bee..dda57921ab 100644
--- a/helper/builtinplugins/registry_test.go
+++ b/helper/builtinplugins/registry_test.go
@@ -98,7 +98,7 @@ func Test_RegistryKeyCounts(t *testing.T) {
{
name: "number of auth plugins",
pluginType: consts.PluginTypeCredential,
- want: 19,
+ want: 18,
entWant: 1,
},
{
diff --git a/helper/builtinplugins/registry_testing_util.go b/helper/builtinplugins/registry_testing_util.go
new file mode 100644
index 0000000000..78d0f93867
--- /dev/null
+++ b/helper/builtinplugins/registry_testing_util.go
@@ -0,0 +1,27 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package builtinplugins
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func assertRegistrySubset(t *testing.T, r, subset *registry, subsetName string) {
+ t.Helper()
+
+ for k := range subset.credentialBackends {
+ require.Contains(t, r.credentialBackends, k, fmt.Sprintf("expected to contain %s auth backend", subsetName))
+ }
+
+ for k := range subset.databasePlugins {
+ require.Contains(t, r.databasePlugins, k, fmt.Sprintf("expected to contain %s database plugin", subsetName))
+ }
+
+ for k := range subset.logicalBackends {
+ require.Contains(t, r.logicalBackends, k, fmt.Sprintf("expected to contain %s logical backend", subsetName))
+ }
+}
diff --git a/helper/forwarding/types.pb.go b/helper/forwarding/types.pb.go
index fbd67a4933..66b6decb99 100644
--- a/helper/forwarding/types.pb.go
+++ b/helper/forwarding/types.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: helper/forwarding/types.proto
@@ -422,7 +422,7 @@ func file_helper_forwarding_types_proto_rawDescGZIP() []byte {
}
var file_helper_forwarding_types_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
-var file_helper_forwarding_types_proto_goTypes = []interface{}{
+var file_helper_forwarding_types_proto_goTypes = []any{
(*Request)(nil), // 0: forwarding.Request
(*URL)(nil), // 1: forwarding.URL
(*HeaderEntry)(nil), // 2: forwarding.HeaderEntry
@@ -449,7 +449,7 @@ func file_helper_forwarding_types_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_helper_forwarding_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_forwarding_types_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Request); i {
case 0:
return &v.state
@@ -461,7 +461,7 @@ func file_helper_forwarding_types_proto_init() {
return nil
}
}
- file_helper_forwarding_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_forwarding_types_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*URL); i {
case 0:
return &v.state
@@ -473,7 +473,7 @@ func file_helper_forwarding_types_proto_init() {
return nil
}
}
- file_helper_forwarding_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_forwarding_types_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*HeaderEntry); i {
case 0:
return &v.state
@@ -485,7 +485,7 @@ func file_helper_forwarding_types_proto_init() {
return nil
}
}
- file_helper_forwarding_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_forwarding_types_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*Response); i {
case 0:
return &v.state
diff --git a/helper/identity/mfa/types.pb.go b/helper/identity/mfa/types.pb.go
index 9d68aba1b5..55c992fc8a 100644
--- a/helper/identity/mfa/types.pb.go
+++ b/helper/identity/mfa/types.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: helper/identity/mfa/types.proto
@@ -1024,7 +1024,7 @@ func file_helper_identity_mfa_types_proto_rawDescGZIP() []byte {
}
var file_helper_identity_mfa_types_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
-var file_helper_identity_mfa_types_proto_goTypes = []interface{}{
+var file_helper_identity_mfa_types_proto_goTypes = []any{
(*Config)(nil), // 0: mfa.Config
(*TOTPConfig)(nil), // 1: mfa.TOTPConfig
(*DuoConfig)(nil), // 2: mfa.DuoConfig
@@ -1053,7 +1053,7 @@ func file_helper_identity_mfa_types_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_helper_identity_mfa_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Config); i {
case 0:
return &v.state
@@ -1065,7 +1065,7 @@ func file_helper_identity_mfa_types_proto_init() {
return nil
}
}
- file_helper_identity_mfa_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*TOTPConfig); i {
case 0:
return &v.state
@@ -1077,7 +1077,7 @@ func file_helper_identity_mfa_types_proto_init() {
return nil
}
}
- file_helper_identity_mfa_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*DuoConfig); i {
case 0:
return &v.state
@@ -1089,7 +1089,7 @@ func file_helper_identity_mfa_types_proto_init() {
return nil
}
}
- file_helper_identity_mfa_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*OktaConfig); i {
case 0:
return &v.state
@@ -1101,7 +1101,7 @@ func file_helper_identity_mfa_types_proto_init() {
return nil
}
}
- file_helper_identity_mfa_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*PingIDConfig); i {
case 0:
return &v.state
@@ -1113,7 +1113,7 @@ func file_helper_identity_mfa_types_proto_init() {
return nil
}
}
- file_helper_identity_mfa_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*Secret); i {
case 0:
return &v.state
@@ -1125,7 +1125,7 @@ func file_helper_identity_mfa_types_proto_init() {
return nil
}
}
- file_helper_identity_mfa_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*TOTPSecret); i {
case 0:
return &v.state
@@ -1137,7 +1137,7 @@ func file_helper_identity_mfa_types_proto_init() {
return nil
}
}
- file_helper_identity_mfa_types_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_mfa_types_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*MFAEnforcementConfig); i {
case 0:
return &v.state
@@ -1150,13 +1150,13 @@ func file_helper_identity_mfa_types_proto_init() {
}
}
}
- file_helper_identity_mfa_types_proto_msgTypes[0].OneofWrappers = []interface{}{
+ file_helper_identity_mfa_types_proto_msgTypes[0].OneofWrappers = []any{
(*Config_TOTPConfig)(nil),
(*Config_OktaConfig)(nil),
(*Config_DuoConfig)(nil),
(*Config_PingIDConfig)(nil),
}
- file_helper_identity_mfa_types_proto_msgTypes[5].OneofWrappers = []interface{}{
+ file_helper_identity_mfa_types_proto_msgTypes[5].OneofWrappers = []any{
(*Secret_TOTPSecret)(nil),
}
type x struct{}
diff --git a/helper/identity/types.pb.go b/helper/identity/types.pb.go
index 031581da70..fbdcb63673 100644
--- a/helper/identity/types.pb.go
+++ b/helper/identity/types.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: helper/identity/types.proto
@@ -1106,7 +1106,7 @@ func file_helper_identity_types_proto_rawDescGZIP() []byte {
}
var file_helper_identity_types_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
-var file_helper_identity_types_proto_goTypes = []interface{}{
+var file_helper_identity_types_proto_goTypes = []any{
(*Group)(nil), // 0: identity.Group
(*LocalAliases)(nil), // 1: identity.LocalAliases
(*Entity)(nil), // 2: identity.Entity
@@ -1162,7 +1162,7 @@ func file_helper_identity_types_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_helper_identity_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_types_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Group); i {
case 0:
return &v.state
@@ -1174,7 +1174,7 @@ func file_helper_identity_types_proto_init() {
return nil
}
}
- file_helper_identity_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_types_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*LocalAliases); i {
case 0:
return &v.state
@@ -1186,7 +1186,7 @@ func file_helper_identity_types_proto_init() {
return nil
}
}
- file_helper_identity_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_types_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*Entity); i {
case 0:
return &v.state
@@ -1198,7 +1198,7 @@ func file_helper_identity_types_proto_init() {
return nil
}
}
- file_helper_identity_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_types_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*Alias); i {
case 0:
return &v.state
@@ -1210,7 +1210,7 @@ func file_helper_identity_types_proto_init() {
return nil
}
}
- file_helper_identity_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_types_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*EntityStorageEntry); i {
case 0:
return &v.state
@@ -1222,7 +1222,7 @@ func file_helper_identity_types_proto_init() {
return nil
}
}
- file_helper_identity_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_identity_types_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*PersonaIndexEntry); i {
case 0:
return &v.state
diff --git a/helper/locking/core_locking.go b/helper/locking/core_locking.go
new file mode 100644
index 0000000000..abd1718094
--- /dev/null
+++ b/helper/locking/core_locking.go
@@ -0,0 +1,44 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package locking
+
+import (
+ "slices"
+ "strings"
+)
+
+// ParseDeadlockDetectionSetting takes the detectDeadlockConfigParameter string
+// and transforms it to a lowercase version of the string, then splits it into
+// a slice of strings by interpreting commas as the element delimiters.
+func ParseDetectDeadlockConfigParameter(detectDeadlockConfigParameter string) []string {
+ if detectDeadlockConfigParameter == "" {
+ // This doesn't seem necessary, since the companion functions that use
+ // this slice can handle an empty slice just the same as a nil slice,
+ // but for the sake of compatibility, this will be introduced for now
+ // until all occurrences that rely on Core.detectDeadlocks have been
+ // switched to using functions from this file to create their locks.
+ return nil
+ }
+
+ result := strings.Split(strings.ToLower(detectDeadlockConfigParameter), ",")
+ for i := range result {
+ result[i] = strings.TrimSpace(result[i])
+ }
+
+ return result
+}
+
+// CreateConfigurableRWMutex determines if the specified lock (identifier) should
+// use a deadlock detecting implementation (DeadlockRWMutex) or simply a basic
+// sync.RWMutex instance. This is done by splitting the deadlockDetectionLocks
+// string into a slice of strings. If the slice contains the specified lock
+// (identifier), then the deadlock detecting implementation is used, otherwise a
+// sync.Mutex is returned.
+func CreateConfigurableRWMutex(deadlockDetectionLocks []string, identifier string) RWMutex {
+ if slices.Contains(deadlockDetectionLocks, strings.ToLower(identifier)) {
+ return &DeadlockRWMutex{}
+ }
+
+ return &SyncRWMutex{}
+}
diff --git a/helper/locking/core_locking_test.go b/helper/locking/core_locking_test.go
new file mode 100644
index 0000000000..55017812d3
--- /dev/null
+++ b/helper/locking/core_locking_test.go
@@ -0,0 +1,103 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+
+package locking
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// TestParseDetectDeadlockConfigParameter verifies that all types of strings
+// that could be obtained from the configuration file, are correctly parsed
+// into a slice of string elements.
+func TestParseDetectDeadlockConfigParameter(t *testing.T) {
+ for _, tc := range []struct {
+ name string
+ detectDeadlockConfigParameter string
+ expectedResult []string
+ }{
+ {
+ name: "empty-string",
+ },
+ {
+ name: "single-value",
+ detectDeadlockConfigParameter: "bar",
+ expectedResult: []string{"bar"},
+ },
+ {
+ name: "single-value-mixed-case",
+ detectDeadlockConfigParameter: "BaR",
+ expectedResult: []string{"bar"},
+ },
+ {
+ name: "multiple-values",
+ detectDeadlockConfigParameter: "bar,BAZ,fIZ",
+ expectedResult: []string{"bar", "baz", "fiz"},
+ },
+ {
+ name: "non-canonical-string-list",
+ detectDeadlockConfigParameter: "bar , baz, ",
+ expectedResult: []string{"bar", "baz", ""},
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ result := ParseDetectDeadlockConfigParameter(tc.detectDeadlockConfigParameter)
+ assert.ElementsMatch(t, tc.expectedResult, result)
+ })
+ }
+}
+
+// TestCreateConfigurableRWMutex verifies the correct behaviour in determining
+// whether a deadlock detecting RWMutex should be returned or not based on the
+// input arguments for the CreateConfigurableRWMutex function.
+func TestCreateConfigurableRWMutex(t *testing.T) {
+ mutexTypes := map[bool]string{
+ false: "locking.SyncRWMutex",
+ true: "locking.DeadlockRWMutex",
+ }
+
+ for _, tc := range []struct {
+ name string
+ detectDeadlocks []string
+ lock string
+ expectDeadlockLock bool
+ }{
+ {
+ name: "no-lock-types-specified",
+ lock: "foo",
+ },
+ {
+ name: "single-lock-specified-no-match",
+ detectDeadlocks: []string{"bar"},
+ lock: "foo",
+ },
+ {
+ name: "single-lock-specified-match",
+ detectDeadlocks: []string{"foo"},
+ lock: "foo",
+ expectDeadlockLock: true,
+ },
+ {
+ name: "multiple-locks-specified-no-match",
+ detectDeadlocks: []string{"bar", "baz", "fiz"},
+ lock: "foo",
+ },
+ {
+ name: "multiple-locks-specified-match",
+ detectDeadlocks: []string{"bar", "foo", "baz"},
+ lock: "foo",
+ expectDeadlockLock: true,
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ m := CreateConfigurableRWMutex(tc.detectDeadlocks, tc.lock)
+
+ _, ok := m.(*DeadlockRWMutex)
+ if tc.expectDeadlockLock != ok {
+ t.Fatalf("unexpected RWMutex type returned, expected: %s got %s", mutexTypes[tc.expectDeadlockLock], mutexTypes[ok])
+ }
+ })
+ }
+}
diff --git a/helper/pkcs7/ber.go b/helper/pkcs7/ber.go
index eb6b1d0af6..898cf262ee 100644
--- a/helper/pkcs7/ber.go
+++ b/helper/pkcs7/ber.go
@@ -140,25 +140,22 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
tagStart := offset
b := ber[offset]
offset++
- if offset >= berLen {
- return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
- }
tag := b & 0x1F // last 5 bits
if tag == 0x1F {
tag = 0
+ if offset >= berLen {
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
for ber[offset] >= 0x80 {
- tag = tag*128 + ber[offset] - 0x80
- offset++
if offset >= berLen {
return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
}
+ tag = tag*128 + ber[offset] - 0x80
+ offset++
}
// jvehent 20170227: this doesn't appear to be used anywhere...
// tag = tag*128 + ber[offset] - 0x80
offset++
- if offset >= berLen {
- return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
- }
}
tagEnd := offset
@@ -170,14 +167,17 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
}
// read length
var length int
- l := ber[offset]
- offset++
if offset >= berLen {
return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
}
+ l := ber[offset]
+ offset++
indefinite := false
if l > 0x80 {
numberOfBytes := (int)(l & 0x7F)
+ if offset >= berLen {
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
if numberOfBytes > 4 { // int is only guaranteed to be 32bit
return nil, 0, errors.New("ber2der: BER tag length too long")
}
@@ -217,6 +217,9 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
return nil, 0, errors.New("ber2der: Indefinite form tag must have constructed encoding")
}
if kind == 0 {
+ if offset >= berLen {
+ return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
+ }
obj = asn1Primitive{
tagBytes: ber[tagStart:tagEnd],
length: length,
diff --git a/helper/pkcs7/ber_test.go b/helper/pkcs7/ber_test.go
index d3908f6bc3..d93bcf57b2 100644
--- a/helper/pkcs7/ber_test.go
+++ b/helper/pkcs7/ber_test.go
@@ -80,7 +80,7 @@ func TestBer2Der_Negatives(t *testing.T) {
{[]byte{0x30, 0x84, 0x80, 0x0, 0x0, 0x0}, "length is negative"},
{[]byte{0x30, 0x82, 0x0, 0x1}, "length has leading zero"},
{[]byte{0x30, 0x80, 0x1, 0x2, 0x1, 0x2}, "Invalid BER format"},
- {[]byte{0x30, 0x80, 0x1, 0x2}, "end of ber data reached"},
+ {[]byte{0x30, 0x80, 0x1, 0x2}, "BER tag length is more than available data"},
{[]byte{0x30, 0x03, 0x01, 0x02}, "length is more than available data"},
{[]byte{0x30}, "end of ber data reached"},
{[]byte("?0"), "end of ber data reached"},
diff --git a/helper/pkcs7/sign_test.go b/helper/pkcs7/sign_test.go
index e08d737563..2a4829a7e8 100644
--- a/helper/pkcs7/sign_test.go
+++ b/helper/pkcs7/sign_test.go
@@ -256,6 +256,12 @@ func TestDegenerateCertificate(t *testing.T) {
}
testOpenSSLParse(t, deg)
pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: deg})
+
+ // Make sure the library can parse the PKCS7 we generated along with OpenSSL
+ _, err = Parse(deg)
+ if err != nil {
+ t.Fatalf("failed parsing degenerated certificate: %v", err)
+ }
}
// writes the cert to a temporary file and tests that openssl can read it.
diff --git a/helper/proxyutil/proxyutil.go b/helper/proxyutil/proxyutil.go
index 7724dde2fd..5b0e523b51 100644
--- a/helper/proxyutil/proxyutil.go
+++ b/helper/proxyutil/proxyutil.go
@@ -4,15 +4,14 @@
package proxyutil
import (
- "errors"
"fmt"
"net"
"sync"
"time"
"github.com/hashicorp/go-secure-stdlib/parseutil"
- sockaddr "github.com/hashicorp/go-sockaddr"
- proxyproto "github.com/pires/go-proxyproto"
+ "github.com/hashicorp/go-sockaddr"
+ "github.com/pires/go-proxyproto"
)
// ProxyProtoConfig contains configuration for the PROXY protocol
@@ -72,7 +71,7 @@ func WrapInProxyProto(listener net.Listener, config *ProxyProtoConfig) (net.List
return proxyproto.IGNORE, nil
}
- return proxyproto.REJECT, errors.New(`upstream connection not trusted proxy_protocol_behavior is "deny_unauthorized"`)
+ return proxyproto.REJECT, proxyproto.ErrInvalidUpstream
},
}
default:
diff --git a/helper/storagepacker/types.pb.go b/helper/storagepacker/types.pb.go
index 778ebea1b8..fd73a0ebb2 100644
--- a/helper/storagepacker/types.pb.go
+++ b/helper/storagepacker/types.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: helper/storagepacker/types.proto
@@ -203,7 +203,7 @@ func file_helper_storagepacker_types_proto_rawDescGZIP() []byte {
}
var file_helper_storagepacker_types_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
-var file_helper_storagepacker_types_proto_goTypes = []interface{}{
+var file_helper_storagepacker_types_proto_goTypes = []any{
(*Item)(nil), // 0: storagepacker.Item
(*Bucket)(nil), // 1: storagepacker.Bucket
nil, // 2: storagepacker.Bucket.ItemMapEntry
@@ -227,7 +227,7 @@ func file_helper_storagepacker_types_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_helper_storagepacker_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_storagepacker_types_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Item); i {
case 0:
return &v.state
@@ -239,7 +239,7 @@ func file_helper_storagepacker_types_proto_init() {
return nil
}
}
- file_helper_storagepacker_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_helper_storagepacker_types_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*Bucket); i {
case 0:
return &v.state
diff --git a/helper/testhelpers/corehelpers/corehelpers.go b/helper/testhelpers/corehelpers/corehelpers.go
index abd5cb8cba..1c7da787d7 100644
--- a/helper/testhelpers/corehelpers/corehelpers.go
+++ b/helper/testhelpers/corehelpers/corehelpers.go
@@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"strings"
+ "testing"
"time"
"github.com/hashicorp/go-hclog"
@@ -19,14 +20,13 @@ import (
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/logical"
- "github.com/mitchellh/go-testing-interface"
)
var externalPlugins = []string{"transform", "kmip", "keymgmt"}
// RetryUntil runs f until it returns a nil result or the timeout is reached.
// If a nil result hasn't been obtained by timeout, calls t.Fatal.
-func RetryUntil(t testing.T, timeout time.Duration, f func() error) {
+func RetryUntil(t testing.TB, timeout time.Duration, f func() error) {
t.Helper()
deadline := time.Now().Add(timeout)
var err error
@@ -41,7 +41,7 @@ func RetryUntil(t testing.T, timeout time.Duration, f func() error) {
// MakeTestPluginDir creates a temporary directory suitable for holding plugins.
// This helper also resolves symlinks to make tests happy on OS X.
-func MakeTestPluginDir(t testing.T) string {
+func MakeTestPluginDir(t testing.TB) string {
t.Helper()
dir, err := os.MkdirTemp("", "")
@@ -210,11 +210,11 @@ type TestLogger struct {
sink hclog.SinkAdapter
}
-func NewTestLogger(t testing.T) *TestLogger {
+func NewTestLogger(t testing.TB) *TestLogger {
return NewTestLoggerWithSuffix(t, "")
}
-func NewTestLoggerWithSuffix(t testing.T, logFileSuffix string) *TestLogger {
+func NewTestLoggerWithSuffix(t testing.TB, logFileSuffix string) *TestLogger {
var logFile *os.File
var logPath string
output := os.Stderr
diff --git a/helper/testhelpers/ldap/ldaphelper.go b/helper/testhelpers/ldap/ldaphelper.go
index d19bfebef4..fa6cf9ff99 100644
--- a/helper/testhelpers/ldap/ldaphelper.go
+++ b/helper/testhelpers/ldap/ldaphelper.go
@@ -4,6 +4,7 @@
package ldap
import (
+ "bytes"
"context"
"fmt"
"runtime"
@@ -22,12 +23,16 @@ func PrepareTestContainer(t *testing.T, version string) (cleanup func(), cfg *ld
t.Skip("Skipping, as this image is not supported on ARM architectures")
}
+ logsWriter := bytes.NewBuffer([]byte{})
+
runner, err := docker.NewServiceRunner(docker.RunOptions{
ImageRepo: "ghcr.io/rroemhild/docker-test-openldap",
ImageTag: version,
ContainerName: "ldap",
Ports: []string{"10389/tcp"},
// Env: []string{"LDAP_DEBUG_LEVEL=384"},
+ LogStderr: logsWriter,
+ LogStdout: logsWriter,
})
if err != nil {
t.Fatalf("could not start local LDAP docker container: %s", err)
@@ -44,27 +49,47 @@ func PrepareTestContainer(t *testing.T, version string) (cleanup func(), cfg *ld
cfg.RequestTimeout = 60
cfg.MaximumPageSize = 1000
- svc, err := runner.StartService(context.Background(), func(ctx context.Context, host string, port int) (docker.ServiceConfig, error) {
- connURL := fmt.Sprintf("ldap://%s:%d", host, port)
- cfg.Url = connURL
+ var started bool
- client, err := ldap.NewClient(ctx, ldaputil.ConvertConfig(cfg))
+ for i := 0; i < 3; i++ {
+ svc, err := runner.StartService(context.Background(), func(ctx context.Context, host string, port int) (docker.ServiceConfig, error) {
+ connURL := fmt.Sprintf("ldap://%s:%d", host, port)
+ cfg.Url = connURL
+
+ client, err := ldap.NewClient(ctx, ldaputil.ConvertConfig(cfg))
+ if err != nil {
+ return nil, err
+ }
+
+ defer client.Close(ctx)
+
+ _, err = client.Authenticate(ctx, "Philip J. Fry", "fry")
+ if err != nil {
+ return nil, err
+ }
+
+ return docker.NewServiceURLParse(connURL)
+ })
if err != nil {
- return nil, err
+ t.Logf("could not start local LDAP docker container: %s", err)
+ t.Log("Docker container logs: ")
+ t.Log(logsWriter.String())
+ continue
}
- defer client.Close(ctx)
-
- _, err = client.Authenticate(ctx, "Philip J. Fry", "fry")
- if err != nil {
- return nil, err
+ started = true
+ cleanup = func() {
+ if t.Failed() {
+ t.Log(logsWriter.String())
+ }
+ svc.Cleanup()
}
-
- return docker.NewServiceURLParse(connURL)
- })
- if err != nil {
- t.Fatalf("could not start local LDAP docker container: %s", err)
+ break
}
- return svc.Cleanup, cfg
+ if !started {
+ t.FailNow()
+ }
+
+ return cleanup, cfg
}
diff --git a/helper/testhelpers/minimal/minimal.go b/helper/testhelpers/minimal/minimal.go
index caf440d26f..5af4d6d603 100644
--- a/helper/testhelpers/minimal/minimal.go
+++ b/helper/testhelpers/minimal/minimal.go
@@ -4,6 +4,8 @@
package minimal
import (
+ "testing"
+
logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
"github.com/hashicorp/vault/audit"
logicalDb "github.com/hashicorp/vault/builtin/logical/database"
@@ -15,7 +17,6 @@ import (
"github.com/hashicorp/vault/sdk/physical/inmem"
"github.com/hashicorp/vault/vault"
"github.com/mitchellh/copystructure"
- "github.com/mitchellh/go-testing-interface"
)
// NewTestSoloCluster is a simpler version of NewTestCluster that only creates
@@ -23,7 +24,7 @@ import (
// from vault.TestClusterOptions, use NewTestCluster instead. It should work fine
// with a nil config argument. There is no need to call Start or Cleanup or
// TestWaitActive on the resulting cluster.
-func NewTestSoloCluster(t testing.T, config *vault.CoreConfig) *vault.TestCluster {
+func NewTestSoloCluster(t testing.TB, config *vault.CoreConfig) *vault.TestCluster {
logger := corehelpers.NewTestLogger(t)
mycfg := &vault.CoreConfig{}
diff --git a/helper/testhelpers/pluginhelpers/pluginhelpers.go b/helper/testhelpers/pluginhelpers/pluginhelpers.go
index 40035fc59f..2d9c235539 100644
--- a/helper/testhelpers/pluginhelpers/pluginhelpers.go
+++ b/helper/testhelpers/pluginhelpers/pluginhelpers.go
@@ -14,9 +14,9 @@ import (
"path/filepath"
"strings"
"sync"
+ "testing"
"github.com/hashicorp/vault/sdk/helper/consts"
- "github.com/mitchellh/go-testing-interface"
)
var (
@@ -34,7 +34,7 @@ type TestPlugin struct {
ImageSha256 string
}
-func GetPlugin(t testing.T, typ consts.PluginType) (string, string, string, string) {
+func GetPlugin(t testing.TB, typ consts.PluginType) (string, string, string, string) {
t.Helper()
var pluginName string
var pluginType string
@@ -65,7 +65,7 @@ func GetPlugin(t testing.T, typ consts.PluginType) (string, string, string, stri
// to mount a plugin, we need a working binary plugin, so we compile one here.
// pluginVersion is used to override the plugin's self-reported version
-func CompilePlugin(t testing.T, typ consts.PluginType, pluginVersion string, pluginDir string) TestPlugin {
+func CompilePlugin(t testing.TB, typ consts.PluginType, pluginVersion string, pluginDir string) TestPlugin {
t.Helper()
pluginName, pluginType, pluginMain, pluginVersionLocation := GetPlugin(t, typ)
@@ -76,15 +76,17 @@ func CompilePlugin(t testing.T, typ consts.PluginType, pluginVersion string, plu
var pluginBytes []byte
dir := ""
- var err error
pluginRootDir := "builtin"
if typ == consts.PluginTypeDatabase {
pluginRootDir = "plugins"
}
for {
- dir, err = os.Getwd()
- if err != nil {
- t.Fatal(err)
+ // So that we can assign to dir without overshadowing the other
+ // err variables.
+ var getWdErr error
+ dir, getWdErr = os.Getwd()
+ if getWdErr != nil {
+ t.Fatal(getWdErr)
}
// detect if we are in a subdirectory or the root directory and compensate
if _, err := os.Stat(pluginRootDir); os.IsNotExist(err) {
@@ -128,15 +130,20 @@ func CompilePlugin(t testing.T, typ consts.PluginType, pluginVersion string, plu
}
// write the cached plugin if necessary
- if _, err := os.Stat(pluginPath); os.IsNotExist(err) {
- err = os.WriteFile(pluginPath, pluginBytes, 0o755)
- }
- if err != nil {
- t.Fatal(err)
+ _, statErr := os.Stat(pluginPath)
+ if os.IsNotExist(statErr) {
+ err := os.WriteFile(pluginPath, pluginBytes, 0o755)
+ if err != nil {
+ t.Fatal(err)
+ }
+ } else {
+ if statErr != nil {
+ t.Fatal(statErr)
+ }
}
sha := sha256.New()
- _, err = sha.Write(pluginBytes)
+ _, err := sha.Write(pluginBytes)
if err != nil {
t.Fatal(err)
}
@@ -149,7 +156,7 @@ func CompilePlugin(t testing.T, typ consts.PluginType, pluginVersion string, plu
}
}
-func BuildPluginContainerImage(t testing.T, plugin TestPlugin, pluginDir string) (image string, sha256 string) {
+func BuildPluginContainerImage(t testing.TB, plugin TestPlugin, pluginDir string) (image string, sha256 string) {
t.Helper()
ref := plugin.Name
if plugin.Version != "" {
diff --git a/helper/testhelpers/postgresql/postgresqlhelper.go b/helper/testhelpers/postgresql/postgresqlhelper.go
index 7e5f25c626..7229d2127b 100644
--- a/helper/testhelpers/postgresql/postgresqlhelper.go
+++ b/helper/testhelpers/postgresql/postgresqlhelper.go
@@ -9,18 +9,49 @@ import (
"fmt"
"net/url"
"os"
+ "strconv"
"testing"
+ "time"
+ "github.com/hashicorp/vault/helper/testhelpers/certhelpers"
"github.com/hashicorp/vault/sdk/helper/docker"
+ "github.com/hashicorp/vault/sdk/helper/pluginutil"
)
-func PrepareTestContainer(t *testing.T, version string) (func(), string) {
- env := []string{
- "POSTGRES_PASSWORD=secret",
- "POSTGRES_DB=database",
- }
+const (
+ defaultPGImage = "docker.mirror.hashicorp.services/postgres"
+ defaultPGVersion = "13.4-buster"
+ defaultPGPass = "secret"
+)
- _, cleanup, url, _ := prepareTestContainer(t, "postgres", "docker.mirror.hashicorp.services/postgres", version, "secret", true, false, false, env)
+func defaultRunOpts(t *testing.T) docker.RunOptions {
+ return docker.RunOptions{
+ ContainerName: "postgres",
+ ImageRepo: defaultPGImage,
+ ImageTag: defaultPGVersion,
+ Env: []string{
+ "POSTGRES_PASSWORD=" + defaultPGPass,
+ "POSTGRES_DB=database",
+ },
+ Ports: []string{"5432/tcp"},
+ DoNotAutoRemove: false,
+ OmitLogTimestamps: true,
+ LogConsumer: func(s string) {
+ if t.Failed() {
+ t.Logf("container logs: %s", s)
+ }
+ },
+ }
+}
+
+func PrepareTestContainer(t *testing.T) (func(), string) {
+ _, cleanup, url, _ := prepareTestContainer(t, defaultRunOpts(t), defaultPGPass, true, false, false)
+
+ return cleanup, url
+}
+
+func PrepareTestContainerMultiHost(t *testing.T) (func(), string) {
+ _, cleanup, url, _ := prepareTestContainer(t, defaultRunOpts(t), defaultPGPass, true, false, true)
return cleanup, url
}
@@ -28,73 +59,138 @@ func PrepareTestContainer(t *testing.T, version string) (func(), string) {
// PrepareTestContainerWithVaultUser will setup a test container with a Vault
// admin user configured so that we can safely call rotate-root without
// rotating the root DB credentials
-func PrepareTestContainerWithVaultUser(t *testing.T, ctx context.Context, version string) (func(), string) {
- env := []string{
- "POSTGRES_PASSWORD=secret",
- "POSTGRES_DB=database",
- }
-
- runner, cleanup, url, id := prepareTestContainer(t, "postgres", "docker.mirror.hashicorp.services/postgres", version, "secret", true, false, false, env)
+func PrepareTestContainerWithVaultUser(t *testing.T, ctx context.Context) (func(), string) {
+ runner, cleanup, url, id := prepareTestContainer(t, defaultRunOpts(t), defaultPGPass, true, false, false)
cmd := []string{"psql", "-U", "postgres", "-c", "CREATE USER vaultadmin WITH LOGIN PASSWORD 'vaultpass' SUPERUSER"}
- _, err := runner.RunCmdInBackground(ctx, id, cmd)
- if err != nil {
- t.Fatalf("Could not run command (%v) in container: %v", cmd, err)
- }
+ mustRunCommand(t, ctx, runner, id, cmd)
return cleanup, url
}
-func PrepareTestContainerWithPassword(t *testing.T, version, password string) (func(), string) {
- env := []string{
+// PrepareTestContainerWithSSL will setup a test container with SSL enabled so
+// that we can test client certificate authentication.
+func PrepareTestContainerWithSSL(
+ t *testing.T,
+ sslMode string,
+ caCert certhelpers.Certificate,
+ clientCert certhelpers.Certificate,
+ useFallback bool,
+) (func(), string) {
+ runOpts := defaultRunOpts(t)
+ runner, err := docker.NewServiceRunner(runOpts)
+ if err != nil {
+ t.Fatalf("Could not provision docker service runner: %s", err)
+ }
+
+ // first we connect with username/password because ssl is not enabled yet
+ svc, id, err := runner.StartNewService(context.Background(), true, false, connectPostgres(defaultPGPass, runOpts.ImageRepo, false))
+ if err != nil {
+ t.Fatalf("Could not start docker Postgres: %s", err)
+ }
+
+ // Create certificates for postgres authentication
+ serverCert := certhelpers.NewCert(t,
+ certhelpers.CommonName("server"),
+ certhelpers.DNS("localhost"),
+ certhelpers.Parent(caCert),
+ )
+
+ bCtx := docker.NewBuildContext()
+ bCtx["ca.crt"] = docker.PathContentsFromBytes(caCert.CombinedPEM())
+ bCtx["server.crt"] = docker.PathContentsFromBytes(serverCert.CombinedPEM())
+ bCtx["server.key"] = &docker.FileContents{
+ Data: serverCert.PrivateKeyPEM(),
+ Mode: 0o600,
+ // postgres uid
+ UID: 999,
+ }
+
+ // https://www.postgresql.org/docs/current/auth-pg-hba-conf.html
+ clientAuthConfig := "echo 'hostssl all all all cert clientcert=verify-ca' > /var/lib/postgresql/data/pg_hba.conf"
+ bCtx["ssl-conf.sh"] = docker.PathContentsFromString(clientAuthConfig)
+ pgConfig := `
+cat << EOF > /var/lib/postgresql/data/postgresql.conf
+# PostgreSQL configuration file
+listen_addresses = '*'
+max_connections = 100
+shared_buffers = 128MB
+dynamic_shared_memory_type = posix
+max_wal_size = 1GB
+min_wal_size = 80MB
+ssl = on
+ssl_ca_file = '/var/lib/postgresql/ca.crt'
+ssl_cert_file = '/var/lib/postgresql/server.crt'
+ssl_key_file= '/var/lib/postgresql/server.key'
+EOF
+`
+ bCtx["pg-conf.sh"] = docker.PathContentsFromString(pgConfig)
+
+ err = runner.CopyTo(id, "/var/lib/postgresql/", bCtx)
+ if err != nil {
+ t.Fatalf("failed to copy to container: %v", err)
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+
+ // overwrite the postgresql.conf config file with our ssl settings
+ mustRunCommand(t, ctx, runner, id,
+ []string{"bash", "/var/lib/postgresql/pg-conf.sh"})
+
+ // overwrite the pg_hba.conf file and set it to require SSL for each connection
+ mustRunCommand(t, ctx, runner, id,
+ []string{"bash", "/var/lib/postgresql/ssl-conf.sh"})
+
+ // reload so the config changes take effect and ssl is enabled
+ mustRunCommand(t, ctx, runner, id,
+ []string{"psql", "-U", "postgres", "-c", "SELECT pg_reload_conf()"})
+
+ if sslMode == "disable" {
+ // return non-tls connection url
+ return svc.Cleanup, svc.Config.URL().String()
+ }
+
+ sslConfig := getPostgresSSLConfig(
+ t,
+ svc.Config.URL().Host,
+ sslMode,
+ string(caCert.CombinedPEM()),
+ string(clientCert.CombinedPEM()),
+ string(clientCert.PrivateKeyPEM()),
+ useFallback,
+ )
+ if err != nil {
+ svc.Cleanup()
+ t.Fatalf("failed to connect to postgres container via SSL: %v", err)
+ }
+ return svc.Cleanup, sslConfig.URL().String()
+}
+
+func PrepareTestContainerWithPassword(t *testing.T, password string) (func(), string) {
+ runOpts := defaultRunOpts(t)
+ runOpts.Env = []string{
"POSTGRES_PASSWORD=" + password,
"POSTGRES_DB=database",
}
- _, cleanup, url, _ := prepareTestContainer(t, "postgres", "docker.mirror.hashicorp.services/postgres", version, password, true, false, false, env)
+ _, cleanup, url, _ := prepareTestContainer(t, runOpts, password, true, false, false)
return cleanup, url
}
-func PrepareTestContainerRepmgr(t *testing.T, name, version string, envVars []string) (*docker.Runner, func(), string, string) {
- env := append(envVars,
- "REPMGR_PARTNER_NODES=psql-repl-node-0,psql-repl-node-1",
- "REPMGR_PRIMARY_HOST=psql-repl-node-0",
- "REPMGR_PASSWORD=repmgrpass",
- "POSTGRESQL_PASSWORD=secret")
-
- return prepareTestContainer(t, name, "docker.mirror.hashicorp.services/bitnami/postgresql-repmgr", version, "secret", false, true, true, env)
-}
-
-func prepareTestContainer(t *testing.T, name, repo, version, password string,
- addSuffix, forceLocalAddr, doNotAutoRemove bool, envVars []string,
+func prepareTestContainer(t *testing.T, runOpts docker.RunOptions, password string, addSuffix, forceLocalAddr, useFallback bool,
) (*docker.Runner, func(), string, string) {
if os.Getenv("PG_URL") != "" {
return nil, func() {}, "", os.Getenv("PG_URL")
}
- if version == "" {
- version = "11"
- }
-
- runOpts := docker.RunOptions{
- ContainerName: name,
- ImageRepo: repo,
- ImageTag: version,
- Env: envVars,
- Ports: []string{"5432/tcp"},
- DoNotAutoRemove: doNotAutoRemove,
- }
- if repo == "bitnami/postgresql-repmgr" {
- runOpts.NetworkID = os.Getenv("POSTGRES_MULTIHOST_NET")
- }
-
runner, err := docker.NewServiceRunner(runOpts)
if err != nil {
t.Fatalf("Could not start docker Postgres: %s", err)
}
- svc, containerID, err := runner.StartNewService(context.Background(), addSuffix, forceLocalAddr, connectPostgres(password, repo))
+ svc, containerID, err := runner.StartNewService(context.Background(), addSuffix, forceLocalAddr, connectPostgres(password, runOpts.ImageRepo, useFallback))
if err != nil {
t.Fatalf("Could not start docker Postgres: %s", err)
}
@@ -102,12 +198,53 @@ func prepareTestContainer(t *testing.T, name, repo, version, password string,
return runner, svc.Cleanup, svc.Config.URL().String(), containerID
}
-func connectPostgres(password, repo string) docker.ServiceAdapter {
+func getPostgresSSLConfig(t *testing.T, host, sslMode, caCert, clientCert, clientKey string, useFallback bool) docker.ServiceConfig {
+ if useFallback {
+ // set the first host to a bad address so we can test the fallback logic
+ host = "localhost:55," + host
+ }
+
+ u := url.URL{}
+
+ if ok, _ := strconv.ParseBool(os.Getenv(pluginutil.PluginUsePostgresSSLInline)); ok {
+ // TODO: remove this when we remove the underlying feature in a future SDK version
+ u = url.URL{
+ Scheme: "postgres",
+ User: url.User("postgres"),
+ Host: host,
+ Path: "postgres",
+ RawQuery: url.Values{
+ "sslmode": {sslMode},
+ "sslinline": {"true"},
+ "sslrootcert": {caCert},
+ "sslcert": {clientCert},
+ "sslkey": {clientKey},
+ }.Encode(),
+ }
+ } else {
+ u = url.URL{
+ Scheme: "postgres",
+ User: url.User("postgres"),
+ Host: host,
+ Path: "postgres",
+ RawQuery: url.Values{"sslmode": {sslMode}}.Encode(),
+ }
+ }
+
+ return docker.NewServiceURL(u)
+}
+
+func connectPostgres(password, repo string, useFallback bool) docker.ServiceAdapter {
return func(ctx context.Context, host string, port int) (docker.ServiceConfig, error) {
+ hostAddr := fmt.Sprintf("%s:%d", host, port)
+ if useFallback {
+ // set the first host to a bad address so we can test the fallback logic
+ hostAddr = "localhost:55," + hostAddr
+ }
u := url.URL{
Scheme: "postgres",
User: url.UserPassword("postgres", password),
- Host: fmt.Sprintf("%s:%d", host, port),
+ Host: hostAddr,
Path: "postgres",
RawQuery: "sslmode=disable",
}
@@ -136,3 +273,14 @@ func RestartContainer(t *testing.T, ctx context.Context, runner *docker.Runner,
t.Fatalf("Could not restart docker Postgres: %s", err)
}
}
+
+func mustRunCommand(t *testing.T, ctx context.Context, runner *docker.Runner, containerID string, cmd []string) {
+ t.Helper()
+ _, stderr, retcode, err := runner.RunCmdWithOutput(ctx, containerID, cmd)
+ if err != nil {
+ t.Fatalf("Could not run command (%v) in container: %v", cmd, err)
+ }
+ if retcode != 0 || len(stderr) != 0 {
+ t.Fatalf("exit code: %v, stderr: %v", retcode, string(stderr))
+ }
+}
diff --git a/helper/testhelpers/seal/sealhelper.go b/helper/testhelpers/seal/sealhelper.go
index 580f42e9e0..474367faa4 100644
--- a/helper/testhelpers/seal/sealhelper.go
+++ b/helper/testhelpers/seal/sealhelper.go
@@ -6,6 +6,7 @@ package sealhelper
import (
"path"
"strconv"
+ "testing"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/builtin/logical/transit"
@@ -16,14 +17,13 @@ import (
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/vault"
"github.com/hashicorp/vault/vault/seal"
- "github.com/mitchellh/go-testing-interface"
)
type TransitSealServer struct {
*vault.TestCluster
}
-func NewTransitSealServer(t testing.T, idx int) *TransitSealServer {
+func NewTransitSealServer(t testing.TB, idx int) *TransitSealServer {
conf := &vault.CoreConfig{
LogicalBackends: map[string]logical.Factory{
"transit": transit.Factory,
@@ -47,7 +47,7 @@ func NewTransitSealServer(t testing.T, idx int) *TransitSealServer {
return &TransitSealServer{cluster}
}
-func (tss *TransitSealServer) MakeKey(t testing.T, key string) {
+func (tss *TransitSealServer) MakeKey(t testing.TB, key string) {
client := tss.Cores[0].Client
if _, err := client.Logical().Write(path.Join("transit", "keys", key), nil); err != nil {
t.Fatal(err)
@@ -59,7 +59,7 @@ func (tss *TransitSealServer) MakeKey(t testing.T, key string) {
}
}
-func (tss *TransitSealServer) MakeSeal(t testing.T, key string) (vault.Seal, error) {
+func (tss *TransitSealServer) MakeSeal(t testing.TB, key string) (vault.Seal, error) {
client := tss.Cores[0].Client
wrapperConfig := map[string]string{
"address": client.Address(),
diff --git a/helper/testhelpers/testhelpers.go b/helper/testhelpers/testhelpers.go
index b087e1fcac..e7f8ed30a0 100644
--- a/helper/testhelpers/testhelpers.go
+++ b/helper/testhelpers/testhelpers.go
@@ -9,10 +9,11 @@ import (
"encoding/json"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"math/rand"
"os"
"strings"
+ "testing"
"time"
"github.com/armon/go-metrics"
@@ -23,7 +24,6 @@ import (
"github.com/hashicorp/vault/physical/raft"
"github.com/hashicorp/vault/sdk/helper/xor"
"github.com/hashicorp/vault/vault"
- "github.com/mitchellh/go-testing-interface"
)
//go:generate enumer -type=GenerateRootKind -trimprefix=GenerateRoot
@@ -36,7 +36,7 @@ const (
)
// GenerateRoot generates a root token on the target cluster.
-func GenerateRoot(t testing.T, cluster *vault.TestCluster, kind GenerateRootKind) string {
+func GenerateRoot(t testing.TB, cluster *vault.TestCluster, kind GenerateRootKind) string {
t.Helper()
token, err := GenerateRootWithError(t, cluster, kind)
if err != nil {
@@ -45,7 +45,7 @@ func GenerateRoot(t testing.T, cluster *vault.TestCluster, kind GenerateRootKind
return token
}
-func GenerateRootWithError(t testing.T, cluster *vault.TestCluster, kind GenerateRootKind) (string, error) {
+func GenerateRootWithError(t testing.TB, cluster *vault.TestCluster, kind GenerateRootKind) (string, error) {
t.Helper()
// If recovery keys supported, use those to perform root token generation instead
var keys [][]byte
@@ -118,14 +118,14 @@ func RandomWithPrefix(name string) string {
return fmt.Sprintf("%s-%d", name, rand.New(rand.NewSource(time.Now().UnixNano())).Int())
}
-func EnsureCoresSealed(t testing.T, c *vault.TestCluster) {
+func EnsureCoresSealed(t testing.TB, c *vault.TestCluster) {
t.Helper()
for _, core := range c.Cores {
EnsureCoreSealed(t, core)
}
}
-func EnsureCoreSealed(t testing.T, core *vault.TestClusterCore) {
+func EnsureCoreSealed(t testing.TB, core *vault.TestClusterCore) {
t.Helper()
core.Seal(t)
timeout := time.Now().Add(60 * time.Second)
@@ -140,7 +140,7 @@ func EnsureCoreSealed(t testing.T, core *vault.TestClusterCore) {
}
}
-func EnsureCoresUnsealed(t testing.T, c *vault.TestCluster) {
+func EnsureCoresUnsealed(t testing.TB, c *vault.TestCluster) {
t.Helper()
for i, core := range c.Cores {
err := AttemptUnsealCore(c, core)
@@ -150,7 +150,7 @@ func EnsureCoresUnsealed(t testing.T, c *vault.TestCluster) {
}
}
-func EnsureCoreUnsealed(t testing.T, c *vault.TestCluster, core *vault.TestClusterCore) {
+func EnsureCoreUnsealed(t testing.TB, c *vault.TestCluster, core *vault.TestClusterCore) {
t.Helper()
err := AttemptUnsealCore(c, core)
if err != nil {
@@ -208,17 +208,17 @@ func AttemptUnsealCore(c *vault.TestCluster, core *vault.TestClusterCore) error
return nil
}
-func EnsureStableActiveNode(t testing.T, cluster *vault.TestCluster) {
+func EnsureStableActiveNode(t testing.TB, cluster *vault.TestCluster) {
t.Helper()
deriveStableActiveCore(t, cluster)
}
-func DeriveStableActiveCore(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore {
+func DeriveStableActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore {
t.Helper()
return deriveStableActiveCore(t, cluster)
}
-func deriveStableActiveCore(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore {
+func deriveStableActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore {
t.Helper()
activeCore := DeriveActiveCore(t, cluster)
minDuration := time.NewTimer(3 * time.Second)
@@ -247,7 +247,7 @@ func deriveStableActiveCore(t testing.T, cluster *vault.TestCluster) *vault.Test
return activeCore
}
-func DeriveActiveCore(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore {
+func DeriveActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore {
t.Helper()
for i := 0; i < 60; i++ {
for _, core := range cluster.Cores {
@@ -268,7 +268,7 @@ func DeriveActiveCore(t testing.T, cluster *vault.TestCluster) *vault.TestCluste
return nil
}
-func DeriveStandbyCores(t testing.T, cluster *vault.TestCluster) []*vault.TestClusterCore {
+func DeriveStandbyCores(t testing.TB, cluster *vault.TestCluster) []*vault.TestClusterCore {
t.Helper()
cores := make([]*vault.TestClusterCore, 0, 2)
for _, core := range cluster.Cores {
@@ -287,7 +287,7 @@ func DeriveStandbyCores(t testing.T, cluster *vault.TestCluster) []*vault.TestCl
return cores
}
-func WaitForNCoresUnsealed(t testing.T, cluster *vault.TestCluster, n int) {
+func WaitForNCoresUnsealed(t testing.TB, cluster *vault.TestCluster, n int) {
t.Helper()
for i := 0; i < 30; i++ {
unsealed := 0
@@ -306,7 +306,7 @@ func WaitForNCoresUnsealed(t testing.T, cluster *vault.TestCluster, n int) {
t.Fatalf("%d cores were not unsealed", n)
}
-func SealCores(t testing.T, cluster *vault.TestCluster) {
+func SealCores(t testing.TB, cluster *vault.TestCluster) {
t.Helper()
for _, core := range cluster.Cores {
if err := core.Shutdown(); err != nil {
@@ -325,7 +325,7 @@ func SealCores(t testing.T, cluster *vault.TestCluster) {
}
}
-func WaitForNCoresSealed(t testing.T, cluster *vault.TestCluster, n int) {
+func WaitForNCoresSealed(t testing.TB, cluster *vault.TestCluster, n int) {
t.Helper()
for i := 0; i < 60; i++ {
sealed := 0
@@ -344,7 +344,7 @@ func WaitForNCoresSealed(t testing.T, cluster *vault.TestCluster, n int) {
t.Fatalf("%d cores were not sealed", n)
}
-func WaitForActiveNode(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore {
+func WaitForActiveNode(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore {
t.Helper()
for i := 0; i < 60; i++ {
for _, core := range cluster.Cores {
@@ -360,7 +360,7 @@ func WaitForActiveNode(t testing.T, cluster *vault.TestCluster) *vault.TestClust
return nil
}
-func WaitForStandbyNode(t testing.T, core *vault.TestClusterCore) {
+func WaitForStandbyNode(t testing.TB, core *vault.TestClusterCore) {
t.Helper()
for i := 0; i < 30; i++ {
if isLeader, _, clusterAddr, _ := core.Core.Leader(); isLeader != true && clusterAddr != "" {
@@ -376,7 +376,7 @@ func WaitForStandbyNode(t testing.T, core *vault.TestClusterCore) {
t.Fatalf("node did not become standby")
}
-func RekeyCluster(t testing.T, cluster *vault.TestCluster, recovery bool) [][]byte {
+func RekeyCluster(t testing.TB, cluster *vault.TestCluster, recovery bool) [][]byte {
t.Helper()
cluster.Logger.Info("rekeying cluster", "recovery", recovery)
client := cluster.Cores[0].Client
@@ -505,7 +505,7 @@ func RaftAppliedIndex(core *vault.TestClusterCore) uint64 {
return core.UnderlyingRawStorage.(*raft.RaftBackend).AppliedIndex()
}
-func WaitForRaftApply(t testing.T, core *vault.TestClusterCore, index uint64) {
+func WaitForRaftApply(t testing.TB, core *vault.TestClusterCore, index uint64) {
t.Helper()
backend := core.UnderlyingRawStorage.(*raft.RaftBackend)
@@ -521,7 +521,7 @@ func WaitForRaftApply(t testing.T, core *vault.TestClusterCore, index uint64) {
}
// AwaitLeader waits for one of the cluster's nodes to become leader.
-func AwaitLeader(t testing.T, cluster *vault.TestCluster) (int, error) {
+func AwaitLeader(t testing.TB, cluster *vault.TestCluster) (int, error) {
timeout := time.Now().Add(60 * time.Second)
for {
if time.Now().After(timeout) {
@@ -545,7 +545,7 @@ func AwaitLeader(t testing.T, cluster *vault.TestCluster) (int, error) {
return 0, fmt.Errorf("timeout waiting leader")
}
-func GenerateDebugLogs(t testing.T, client *api.Client) chan struct{} {
+func GenerateDebugLogs(t testing.TB, client *api.Client) chan struct{} {
t.Helper()
stopCh := make(chan struct{})
@@ -584,7 +584,7 @@ func GenerateDebugLogs(t testing.T, client *api.Client) chan struct{} {
// from the map by removing entries whose keys are in the raft configuration.
// Remaining entries result in an error return so that the caller can poll for
// an expected configuration.
-func VerifyRaftPeers(t testing.T, client *api.Client, expected map[string]bool) error {
+func VerifyRaftPeers(t testing.TB, client *api.Client, expected map[string]bool) error {
t.Helper()
resp, err := client.Logical().Read("sys/storage/raft/configuration")
@@ -641,7 +641,7 @@ func SysMetricsReq(client *api.Client, cluster *vault.TestCluster, unauth bool)
if err != nil {
return nil, err
}
- bodyBytes, err := ioutil.ReadAll(resp.Response.Body)
+ bodyBytes, err := io.ReadAll(resp.Response.Body)
if err != nil {
return nil, err
}
@@ -720,7 +720,7 @@ func SetNonRootToken(client *api.Client) error {
// RetryUntilAtCadence runs f until it returns a nil result or the timeout is reached.
// If a nil result hasn't been obtained by timeout, calls t.Fatal.
-func RetryUntilAtCadence(t testing.T, timeout, sleepTime time.Duration, f func() error) {
+func RetryUntilAtCadence(t testing.TB, timeout, sleepTime time.Duration, f func() error) {
t.Helper()
fail := func(err error) {
t.Fatalf("did not complete before deadline, err: %v", err)
@@ -730,7 +730,7 @@ func RetryUntilAtCadence(t testing.T, timeout, sleepTime time.Duration, f func()
// RetryUntilAtCadenceWithHandler runs f until it returns a nil result or the timeout is reached.
// If a nil result hasn't been obtained by timeout, onFailure is called.
-func RetryUntilAtCadenceWithHandler(t testing.T, timeout, sleepTime time.Duration, onFailure func(error), f func() error) {
+func RetryUntilAtCadenceWithHandler(t testing.TB, timeout, sleepTime time.Duration, onFailure func(error), f func() error) {
t.Helper()
deadline := time.Now().Add(timeout)
var err error
@@ -748,20 +748,20 @@ func RetryUntilAtCadenceWithHandler(t testing.T, timeout, sleepTime time.Duratio
// If a nil result hasn't been obtained by timeout, calls t.Fatal.
// NOTE: See RetryUntilAtCadence if you want to specify a different wait/sleep
// duration between calls.
-func RetryUntil(t testing.T, timeout time.Duration, f func() error) {
+func RetryUntil(t testing.TB, timeout time.Duration, f func() error) {
t.Helper()
RetryUntilAtCadence(t, timeout, 100*time.Millisecond, f)
}
// CreateEntityAndAlias clones an existing client and creates an entity/alias, uses userpass mount path
// It returns the cloned client, entityID, and aliasID.
-func CreateEntityAndAlias(t testing.T, client *api.Client, mountAccessor, entityName, aliasName string) (*api.Client, string, string) {
+func CreateEntityAndAlias(t testing.TB, client *api.Client, mountAccessor, entityName, aliasName string) (*api.Client, string, string) {
return CreateEntityAndAliasWithinMount(t, client, mountAccessor, "userpass", entityName, aliasName)
}
// CreateEntityAndAliasWithinMount clones an existing client and creates an entity/alias, within the specified mountPath
// It returns the cloned client, entityID, and aliasID.
-func CreateEntityAndAliasWithinMount(t testing.T, client *api.Client, mountAccessor, mountPath, entityName, aliasName string) (*api.Client, string, string) {
+func CreateEntityAndAliasWithinMount(t testing.TB, client *api.Client, mountAccessor, mountPath, entityName, aliasName string) (*api.Client, string, string) {
t.Helper()
userClient, err := client.Clone()
if err != nil {
@@ -802,7 +802,7 @@ func CreateEntityAndAliasWithinMount(t testing.T, client *api.Client, mountAcces
// SetupTOTPMount enables the totp secrets engine by mounting it. This requires
// that the test cluster has a totp backend available.
-func SetupTOTPMount(t testing.T, client *api.Client) {
+func SetupTOTPMount(t testing.TB, client *api.Client) {
t.Helper()
// Mount the TOTP backend
mountInfo := &api.MountInput{
@@ -814,7 +814,7 @@ func SetupTOTPMount(t testing.T, client *api.Client) {
}
// SetupTOTPMethod configures the TOTP secrets engine with a provided config map.
-func SetupTOTPMethod(t testing.T, client *api.Client, config map[string]interface{}) string {
+func SetupTOTPMethod(t testing.TB, client *api.Client, config map[string]interface{}) string {
t.Helper()
resp1, err := client.Logical().Write("identity/mfa/method/totp", config)
@@ -833,7 +833,7 @@ func SetupTOTPMethod(t testing.T, client *api.Client, config map[string]interfac
// SetupMFALoginEnforcement configures a single enforcement method using the
// provided config map. "name" field is required in the config map.
-func SetupMFALoginEnforcement(t testing.T, client *api.Client, config map[string]interface{}) {
+func SetupMFALoginEnforcement(t testing.TB, client *api.Client, config map[string]interface{}) {
t.Helper()
enfName, ok := config["name"]
if !ok {
@@ -848,7 +848,7 @@ func SetupMFALoginEnforcement(t testing.T, client *api.Client, config map[string
// SetupUserpassMountAccessor sets up userpass auth and returns its mount
// accessor. This requires that the test cluster has a "userpass" auth method
// available.
-func SetupUserpassMountAccessor(t testing.T, client *api.Client) string {
+func SetupUserpassMountAccessor(t testing.TB, client *api.Client) string {
t.Helper()
// Enable Userpass authentication
err := client.Sys().EnableAuthWithOptions("userpass", &api.EnableAuthOptions{
@@ -871,7 +871,7 @@ func SetupUserpassMountAccessor(t testing.T, client *api.Client) string {
// RegisterEntityInTOTPEngine registers an entity with a methodID and returns
// the generated name.
-func RegisterEntityInTOTPEngine(t testing.T, client *api.Client, entityID, methodID string) string {
+func RegisterEntityInTOTPEngine(t testing.TB, client *api.Client, entityID, methodID string) string {
t.Helper()
totpGenName := fmt.Sprintf("%s-%s", entityID, methodID)
secret, err := client.Logical().WriteWithContext(context.Background(), "identity/mfa/method/totp/admin-generate", map[string]interface{}{
@@ -905,7 +905,7 @@ func RegisterEntityInTOTPEngine(t testing.T, client *api.Client, entityID, metho
}
// GetTOTPCodeFromEngine requests a TOTP code from the specified enginePath.
-func GetTOTPCodeFromEngine(t testing.T, client *api.Client, enginePath string) string {
+func GetTOTPCodeFromEngine(t testing.TB, client *api.Client, enginePath string) string {
t.Helper()
totpPath := fmt.Sprintf("totp/code/%s", enginePath)
secret, err := client.Logical().ReadWithContext(context.Background(), totpPath)
@@ -920,7 +920,7 @@ func GetTOTPCodeFromEngine(t testing.T, client *api.Client, enginePath string) s
// SetupLoginMFATOTP setups up a TOTP MFA using some basic configuration and
// returns all relevant information to the client.
-func SetupLoginMFATOTP(t testing.T, client *api.Client, methodName string, waitPeriod int) (*api.Client, string, string) {
+func SetupLoginMFATOTP(t testing.TB, client *api.Client, methodName string, waitPeriod int) (*api.Client, string, string) {
t.Helper()
// Mount the totp secrets engine
SetupTOTPMount(t, client)
@@ -956,7 +956,7 @@ func SetupLoginMFATOTP(t testing.T, client *api.Client, methodName string, waitP
return entityClient, entityID, methodID
}
-func SkipUnlessEnvVarsSet(t testing.T, envVars []string) {
+func SkipUnlessEnvVarsSet(t testing.TB, envVars []string) {
t.Helper()
for _, i := range envVars {
@@ -974,7 +974,7 @@ func SkipUnlessEnvVarsSet(t testing.T, envVars []string) {
// The intention/use case for this function is to allow a cluster to start and become active with one
// or more nodes not joined, so that we can test scenarios where a node joins later.
// e.g. 4 nodes in the cluster, only 3 nodes in cluster 'active', 1 node can be joined later in tests.
-func WaitForNodesExcludingSelectedStandbys(t testing.T, cluster *vault.TestCluster, indexesToSkip ...int) {
+func WaitForNodesExcludingSelectedStandbys(t testing.TB, cluster *vault.TestCluster, indexesToSkip ...int) {
WaitForActiveNode(t, cluster)
contains := func(elems []int, e int) bool {
diff --git a/helper/testhelpers/testhelpers_oss.go b/helper/testhelpers/testhelpers_oss.go
index 8965ed9169..e7e6ff8eba 100644
--- a/helper/testhelpers/testhelpers_oss.go
+++ b/helper/testhelpers/testhelpers_oss.go
@@ -6,13 +6,14 @@
package testhelpers
import (
+ "testing"
+
"github.com/hashicorp/vault/vault"
- "github.com/mitchellh/go-testing-interface"
)
// WaitForActiveNodeAndStandbys does nothing more than wait for the active node
// on OSS. On enterprise it waits for perf standbys to be healthy too.
-func WaitForActiveNodeAndStandbys(t testing.T, cluster *vault.TestCluster) {
+func WaitForActiveNodeAndStandbys(t testing.TB, cluster *vault.TestCluster) {
WaitForActiveNode(t, cluster)
for _, core := range cluster.Cores {
if standby, _ := core.Core.Standby(); standby {
diff --git a/helper/testhelpers/teststorage/consul/consul.go b/helper/testhelpers/teststorage/consul/consul.go
index 26a2175dac..cb5cec92d5 100644
--- a/helper/testhelpers/teststorage/consul/consul.go
+++ b/helper/testhelpers/teststorage/consul/consul.go
@@ -5,16 +5,16 @@ package consul
import (
"sync"
+ "testing"
realtesting "testing"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/testhelpers/consul"
physConsul "github.com/hashicorp/vault/physical/consul"
"github.com/hashicorp/vault/vault"
- "github.com/mitchellh/go-testing-interface"
)
-func MakeConsulBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle {
+func MakeConsulBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle {
cleanup, config := consul.PrepareTestContainer(t.(*realtesting.T), "", false, true)
consulConf := map[string]string{
@@ -56,7 +56,7 @@ type consulContainerManager struct {
current *consulContainerBackendFactory
}
-func (m *consulContainerManager) Backend(t testing.T, coreIdx int,
+func (m *consulContainerManager) Backend(t testing.TB, coreIdx int,
logger hclog.Logger, conf map[string]interface{},
) *vault.PhysicalBackendBundle {
m.mu.Lock()
@@ -77,7 +77,7 @@ type consulContainerBackendFactory struct {
config map[string]string
}
-func (f *consulContainerBackendFactory) Backend(t testing.T, coreIdx int,
+func (f *consulContainerBackendFactory) Backend(t testing.TB, coreIdx int,
logger hclog.Logger, conf map[string]interface{},
) *vault.PhysicalBackendBundle {
f.mu.Lock()
@@ -100,7 +100,7 @@ func (f *consulContainerBackendFactory) Backend(t testing.T, coreIdx int,
}
}
-func (f *consulContainerBackendFactory) startContainerLocked(t testing.T) {
+func (f *consulContainerBackendFactory) startContainerLocked(t testing.TB) {
cleanup, config := consul.PrepareTestContainer(t.(*realtesting.T), "", false, true)
f.config = map[string]string{
"address": config.Address(),
diff --git a/helper/testhelpers/teststorage/teststorage.go b/helper/testhelpers/teststorage/teststorage.go
index 96a3a1bd0f..4a39e8f98e 100644
--- a/helper/testhelpers/teststorage/teststorage.go
+++ b/helper/testhelpers/teststorage/teststorage.go
@@ -9,6 +9,7 @@ import (
"io/ioutil"
"math/rand"
"os"
+ "testing"
"time"
"github.com/hashicorp/go-hclog"
@@ -25,10 +26,9 @@ import (
physFile "github.com/hashicorp/vault/sdk/physical/file"
"github.com/hashicorp/vault/sdk/physical/inmem"
"github.com/hashicorp/vault/vault"
- "github.com/mitchellh/go-testing-interface"
)
-func MakeInmemBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle {
+func MakeInmemBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle {
inm, err := inmem.NewTransactionalInmem(nil, logger)
if err != nil {
t.Fatal(err)
@@ -44,7 +44,7 @@ func MakeInmemBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBu
}
}
-func MakeLatentInmemBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle {
+func MakeLatentInmemBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
jitter := r.Intn(20)
latency := time.Duration(r.Intn(15)) * time.Millisecond
@@ -55,7 +55,7 @@ func MakeLatentInmemBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBac
return pbb
}
-func MakeInmemNonTransactionalBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle {
+func MakeInmemNonTransactionalBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle {
inm, err := inmem.NewInmem(nil, logger)
if err != nil {
t.Fatal(err)
@@ -71,7 +71,7 @@ func MakeInmemNonTransactionalBackend(t testing.T, logger hclog.Logger) *vault.P
}
}
-func MakeFileBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle {
+func MakeFileBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle {
path, err := ioutil.TempDir("", "vault-integ-file-")
if err != nil {
t.Fatal(err)
@@ -101,7 +101,7 @@ func MakeFileBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBun
}
}
-func MakeRaftBackend(t testing.T, coreIdx int, logger hclog.Logger, extraConf map[string]interface{}, bridge *raft.ClusterAddrBridge) *vault.PhysicalBackendBundle {
+func MakeRaftBackend(t testing.TB, coreIdx int, logger hclog.Logger, extraConf map[string]interface{}, bridge *raft.ClusterAddrBridge) *vault.PhysicalBackendBundle {
nodeID := fmt.Sprintf("core-%d", coreIdx)
raftDir, err := ioutil.TempDir("", "vault-raft-")
if err != nil {
@@ -155,8 +155,8 @@ func makeRaftBackend(logger hclog.Logger, nodeID, raftDir string, extraConf map[
// RaftHAFactory returns a PhysicalBackendBundle with raft set as the HABackend
// and the physical.Backend provided in PhysicalBackendBundler as the storage
// backend.
-func RaftHAFactory(f PhysicalBackendBundler) func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
- return func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+func RaftHAFactory(f PhysicalBackendBundler) func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+ return func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
// Call the factory func to create the storage backend
physFactory := SharedPhysicalFactory(f)
bundle := physFactory(t, coreIdx, logger, nil)
@@ -201,10 +201,10 @@ func RaftHAFactory(f PhysicalBackendBundler) func(t testing.T, coreIdx int, logg
}
}
-type PhysicalBackendBundler func(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle
+type PhysicalBackendBundler func(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle
-func SharedPhysicalFactory(f PhysicalBackendBundler) func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
- return func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+func SharedPhysicalFactory(f PhysicalBackendBundler) func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+ return func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
if coreIdx == 0 {
return f(t, logger)
}
@@ -230,7 +230,7 @@ func FileBackendSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions) {
opts.PhysicalFactory = SharedPhysicalFactory(MakeFileBackend)
}
-func RaftClusterJoinNodes(t testing.T, cluster *vault.TestCluster) {
+func RaftClusterJoinNodes(t testing.TB, cluster *vault.TestCluster) {
leader := cluster.Cores[0]
leaderInfos := []*raft.LeaderJoinInfo{
@@ -255,7 +255,7 @@ func RaftClusterJoinNodes(t testing.T, cluster *vault.TestCluster) {
func RaftBackendSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions) {
opts.KeepStandbysSealed = true
var bridge *raft.ClusterAddrBridge
- opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+ opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
// The same PhysicalFactory can be shared across multiple clusters.
// The coreIdx == 0 check ensures that each time a new cluster is setup,
// when setting up its first node we create a new ClusterAddrBridge.
@@ -269,7 +269,7 @@ func RaftBackendSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions) {
}
return bundle
}
- opts.SetupFunc = func(t testing.T, c *vault.TestCluster) {
+ opts.SetupFunc = func(t testing.TB, c *vault.TestCluster) {
if opts.NumCores != 1 {
RaftClusterJoinNodes(t, c)
time.Sleep(15 * time.Second)
diff --git a/helper/testhelpers/teststorage/teststorage_reusable.go b/helper/testhelpers/teststorage/teststorage_reusable.go
index 89642cf61f..db18dfb8c2 100644
--- a/helper/testhelpers/teststorage/teststorage_reusable.go
+++ b/helper/testhelpers/teststorage/teststorage_reusable.go
@@ -7,12 +7,12 @@ import (
"fmt"
"io/ioutil"
"os"
+ "testing"
hclog "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/physical/raft"
"github.com/hashicorp/vault/sdk/physical"
"github.com/hashicorp/vault/vault"
- "github.com/mitchellh/go-testing-interface"
)
// ReusableStorage is a physical backend that can be re-used across
@@ -29,7 +29,7 @@ type ReusableStorage struct {
// Cleanup should be called after a TestCluster is no longer
// needed -- generally in a defer, just before the call to
// cluster.Cleanup().
- Cleanup func(t testing.T, cluster *vault.TestCluster)
+ Cleanup func(t testing.TB, cluster *vault.TestCluster)
}
// StorageCleanup is a function that should be called once -- at the very end
@@ -39,12 +39,12 @@ type StorageCleanup func()
// MakeReusableStorage makes a physical backend that can be re-used across
// multiple test clusters in sequence.
-func MakeReusableStorage(t testing.T, logger hclog.Logger, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) {
+func MakeReusableStorage(t testing.TB, logger hclog.Logger, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) {
storage := ReusableStorage{
IsRaft: false,
Setup: func(conf *vault.CoreConfig, opts *vault.TestClusterOptions) {
- opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+ opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
if coreIdx == 0 {
// We intentionally do not clone the backend's Cleanup func,
// because we don't want it to be run until the entire test has
@@ -59,7 +59,7 @@ func MakeReusableStorage(t testing.T, logger hclog.Logger, bundle *vault.Physica
},
// No-op
- Cleanup: func(t testing.T, cluster *vault.TestCluster) {},
+ Cleanup: func(t testing.TB, cluster *vault.TestCluster) {},
}
cleanup := func() {
@@ -73,7 +73,7 @@ func MakeReusableStorage(t testing.T, logger hclog.Logger, bundle *vault.Physica
// MakeReusableRaftStorage makes a physical raft backend that can be re-used
// across multiple test clusters in sequence.
-func MakeReusableRaftStorage(t testing.T, logger hclog.Logger, numCores int) (ReusableStorage, StorageCleanup) {
+func MakeReusableRaftStorage(t testing.TB, logger hclog.Logger, numCores int) (ReusableStorage, StorageCleanup) {
raftDirs := make([]string, numCores)
for i := 0; i < numCores; i++ {
raftDirs[i] = makeRaftDir(t)
@@ -85,13 +85,13 @@ func MakeReusableRaftStorage(t testing.T, logger hclog.Logger, numCores int) (Re
Setup: func(conf *vault.CoreConfig, opts *vault.TestClusterOptions) {
conf.DisablePerformanceStandby = true
opts.KeepStandbysSealed = true
- opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+ opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
return makeReusableRaftBackend(t, coreIdx, logger, raftDirs[coreIdx], false)
}
},
// Close open files being used by raft.
- Cleanup: func(t testing.T, cluster *vault.TestCluster) {
+ Cleanup: func(t testing.TB, cluster *vault.TestCluster) {
for i := 0; i < len(cluster.Cores); i++ {
CloseRaftStorage(t, cluster, i)
}
@@ -108,14 +108,14 @@ func MakeReusableRaftStorage(t testing.T, logger hclog.Logger, numCores int) (Re
}
// CloseRaftStorage closes open files being used by raft.
-func CloseRaftStorage(t testing.T, cluster *vault.TestCluster, idx int) {
+func CloseRaftStorage(t testing.TB, cluster *vault.TestCluster, idx int) {
raftStorage := cluster.Cores[idx].UnderlyingRawStorage.(*raft.RaftBackend)
if err := raftStorage.Close(); err != nil {
t.Fatal(err)
}
}
-func MakeReusableRaftHAStorage(t testing.T, logger hclog.Logger, numCores int, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) {
+func MakeReusableRaftHAStorage(t testing.TB, logger hclog.Logger, numCores int, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) {
raftDirs := make([]string, numCores)
for i := 0; i < numCores; i++ {
raftDirs[i] = makeRaftDir(t)
@@ -125,7 +125,7 @@ func MakeReusableRaftHAStorage(t testing.T, logger hclog.Logger, numCores int, b
Setup: func(conf *vault.CoreConfig, opts *vault.TestClusterOptions) {
opts.InmemClusterLayers = true
opts.KeepStandbysSealed = true
- opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
+ opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle {
haBundle := makeReusableRaftBackend(t, coreIdx, logger, raftDirs[coreIdx], true)
return &vault.PhysicalBackendBundle{
@@ -136,7 +136,7 @@ func MakeReusableRaftHAStorage(t testing.T, logger hclog.Logger, numCores int, b
},
// Close open files being used by raft.
- Cleanup: func(t testing.T, cluster *vault.TestCluster) {
+ Cleanup: func(t testing.TB, cluster *vault.TestCluster) {
for _, core := range cluster.Cores {
raftStorage := core.UnderlyingHAStorage.(*raft.RaftBackend)
if err := raftStorage.Close(); err != nil {
@@ -159,7 +159,7 @@ func MakeReusableRaftHAStorage(t testing.T, logger hclog.Logger, numCores int, b
return storage, cleanup
}
-func makeRaftDir(t testing.T) string {
+func makeRaftDir(t testing.TB) string {
raftDir, err := ioutil.TempDir("", "vault-raft-")
if err != nil {
t.Fatal(err)
@@ -168,7 +168,7 @@ func makeRaftDir(t testing.T) string {
return raftDir
}
-func makeReusableRaftBackend(t testing.T, coreIdx int, logger hclog.Logger, raftDir string, ha bool) *vault.PhysicalBackendBundle {
+func makeReusableRaftBackend(t testing.TB, coreIdx int, logger hclog.Logger, raftDir string, ha bool) *vault.PhysicalBackendBundle {
nodeID := fmt.Sprintf("core-%d", coreIdx)
backend, err := makeRaftBackend(logger, nodeID, raftDir, nil, nil)
if err != nil {
diff --git a/helper/timeutil/timeutil.go b/helper/timeutil/timeutil.go
index eeba1797d0..30b894d9cc 100644
--- a/helper/timeutil/timeutil.go
+++ b/helper/timeutil/timeutil.go
@@ -179,3 +179,13 @@ func (_ DefaultClock) NewTicker(d time.Duration) *time.Ticker {
func (_ DefaultClock) NewTimer(d time.Duration) *time.Timer {
return time.NewTimer(d)
}
+
+// NormalizeToYear returns date normalized to the latest date
+// within one year of normal. Assumes the date argument is
+// some date before normal.
+func NormalizeToYear(date, normal time.Time) time.Time {
+ for date.AddDate(1, 0, 0).Compare(normal) <= 0 {
+ date = date.AddDate(1, 0, 0)
+ }
+ return date
+}
diff --git a/helper/timeutil/timeutil_test.go b/helper/timeutil/timeutil_test.go
index df14a6fd17..7692fd280d 100644
--- a/helper/timeutil/timeutil_test.go
+++ b/helper/timeutil/timeutil_test.go
@@ -7,6 +7,8 @@ import (
"reflect"
"testing"
"time"
+
+ "github.com/stretchr/testify/require"
)
func TestTimeutil_StartOfPreviousMonth(t *testing.T) {
@@ -367,3 +369,94 @@ func TestTimeUtil_ParseTimeFromPath(t *testing.T) {
}
}
}
+
+// TestTimeUtil_NormalizeToYear tests NormalizeToYear function which returns the normalized input date wrt to the normal.
+func TestTimeUtil_NormalizeToYear(t *testing.T) {
+ testCases := []struct {
+ inputDate time.Time
+ normalDate time.Time
+ expectedNormalizedDate time.Time
+ }{
+ {
+ inputDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2024, 10, 1, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2025, 9, 29, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2025, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2025, 10, 1, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2025, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ // inputDate more than 2 years prior to normal date
+ {
+ inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2024, 6, 15, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2023, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2024, 9, 28, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2023, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2024, 9, 30, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2020, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2024, 12, 1, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ // leap year test cases
+ {
+ inputDate: time.Date(2020, 9, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2024, 9, 28, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2023, 9, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2025, 2, 28, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2025, 3, 2, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2028, 2, 28, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2027, 3, 1, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2028, 2, 29, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2027, 3, 1, 0, 0, 0, 0, time.UTC),
+ },
+ {
+ inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
+ normalDate: time.Date(2028, 3, 1, 0, 0, 0, 0, time.UTC),
+ expectedNormalizedDate: time.Date(2028, 3, 1, 0, 0, 0, 0, time.UTC),
+ },
+ }
+ for _, tc := range testCases {
+ normalizedDate := NormalizeToYear(tc.inputDate, tc.normalDate)
+ require.Equal(t, tc.expectedNormalizedDate, normalizedDate)
+ }
+}
diff --git a/http/forwarding_bench_test.go b/http/forwarding_bench_test.go
index 287a6c9ff4..311dc0bc66 100644
--- a/http/forwarding_bench_test.go
+++ b/http/forwarding_bench_test.go
@@ -14,7 +14,6 @@ import (
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/builtin/logical/transit"
- "github.com/hashicorp/vault/helper/benchhelpers"
"github.com/hashicorp/vault/helper/forwarding"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/logging"
@@ -32,7 +31,7 @@ func BenchmarkHTTP_Forwarding_Stress(b *testing.B) {
},
}
- cluster := vault.NewTestCluster(benchhelpers.TBtoT(b), coreConfig, &vault.TestClusterOptions{
+ cluster := vault.NewTestCluster(b, coreConfig, &vault.TestClusterOptions{
HandlerFunc: Handler,
Logger: logging.NewVaultLoggerWithWriter(ioutil.Discard, log.Error),
})
@@ -42,7 +41,7 @@ func BenchmarkHTTP_Forwarding_Stress(b *testing.B) {
// make it easy to get access to the active
core := cores[0].Core
- vault.TestWaitActive(benchhelpers.TBtoT(b), core)
+ vault.TestWaitActive(b, core)
handler := cores[0].Handler
host := fmt.Sprintf("https://127.0.0.1:%d/v1/transit/", cores[0].Listeners[0].Address.Port)
diff --git a/http/handler.go b/http/handler.go
index 905838ba19..7de46649f4 100644
--- a/http/handler.go
+++ b/http/handler.go
@@ -14,7 +14,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"mime"
"net"
"net/http"
@@ -116,7 +115,7 @@ var (
"/v1/sys/wrapping/wrap",
}
websocketRawPaths = []string{
- "/v1/sys/events/subscribe",
+ "sys/events/subscribe",
}
oidcProtectedPathRegex = regexp.MustCompile(`^identity/oidc/provider/\w(([\w-.]+)?\w)?/userinfo$`)
)
@@ -128,9 +127,7 @@ func init() {
"!sys/storage/raft/snapshot-auto/config",
})
websocketPaths.AddPaths(websocketRawPaths)
- for _, path := range websocketRawPaths {
- alwaysRedirectPaths.AddPaths([]string{strings.TrimPrefix(path, "/v1/")})
- }
+ alwaysRedirectPaths.AddPaths(websocketRawPaths)
}
type HandlerAnchor struct{}
@@ -315,7 +312,7 @@ func (w *copyResponseWriter) WriteHeader(code int) {
func handleAuditNonLogical(core *vault.Core, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origBody := new(bytes.Buffer)
- reader := ioutil.NopCloser(io.TeeReader(r.Body, origBody))
+ reader := io.NopCloser(io.TeeReader(r.Body, origBody))
r.Body = reader
req, _, status, err := buildLogicalRequestNoAuth(core.PerfStandby(), core.RouterAccess(), w, r)
if err != nil || status != 0 {
@@ -434,7 +431,7 @@ func wrapGenericHandler(core *vault.Core, h http.Handler, props *vault.HandlerPr
} else if standby && !perfStandby {
// Standby nodes, not performance standbys, don't start plugins
// so registration can not happen, instead redirect to active
- respondStandby(core, w, r.URL)
+ respondStandby(core, w, r)
cancelFunc()
return
} else {
@@ -817,14 +814,14 @@ func parseJSONRequest(perfStandby bool, r *http.Request, w http.ResponseWriter,
// Since we're checking PerfStandby here we key on origBody being nil
// or not later, so we need to always allocate so it's non-nil
origBody = new(bytes.Buffer)
- reader = ioutil.NopCloser(io.TeeReader(reader, origBody))
+ reader = io.NopCloser(io.TeeReader(reader, origBody))
}
err := jsonutil.DecodeJSONFromReader(reader, out)
if err != nil && err != io.EOF {
return nil, fmt.Errorf("failed to parse JSON input: %w", err)
}
if origBody != nil {
- return ioutil.NopCloser(origBody), err
+ return io.NopCloser(origBody), err
}
return nil, err
}
@@ -867,6 +864,7 @@ func forwardBasedOnHeaders(core *vault.Core, r *http.Request) (bool, error) {
return false, fmt.Errorf("forwarding via header %s disabled in configuration", VaultForwardHeaderName)
}
if rawForward == "active-node" {
+ core.Logger().Trace("request will be routed based on the 'active-node' header")
return true, nil
}
return false, nil
@@ -908,7 +906,7 @@ func handleRequestForwarding(core *vault.Core, handler http.Handler) http.Handle
respondError(w, http.StatusBadRequest, err)
return
}
- path := ns.TrimmedPath(r.URL.Path[len("/v1/"):])
+ path := trimPath(ns, r.URL.Path)
if !perfStandbyAlwaysForwardPaths.HasPath(path) && !alwaysRedirectPaths.HasPath(path) {
handler.ServeHTTP(w, r)
return
@@ -945,14 +943,14 @@ func handleRequestForwarding(core *vault.Core, handler http.Handler) http.Handle
func forwardRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) {
if r.Header.Get(vault.IntNoForwardingHeaderName) != "" {
- respondStandby(core, w, r.URL)
+ respondStandby(core, w, r)
return
}
if r.Header.Get(NoRequestForwardingHeaderName) != "" {
// Forwarding explicitly disabled, fall back to previous behavior
core.Logger().Debug("handleRequestForwarding: forwarding disabled by client request")
- respondStandby(core, w, r.URL)
+ respondStandby(core, w, r)
return
}
@@ -961,9 +959,25 @@ func forwardRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) {
respondError(w, http.StatusBadRequest, err)
return
}
- path := ns.TrimmedPath(r.URL.Path[len("/v1/"):])
- if alwaysRedirectPaths.HasPath(path) {
- respondStandby(core, w, r.URL)
+ path := trimPath(ns, r.URL.Path)
+ redirect := alwaysRedirectPaths.HasPath(path)
+ // websocket paths are special, because they can contain a namespace
+ // in front of them. This isn't an issue on perf standbys where the
+ // namespace manager will know all the namespaces, so we will have
+ // already extracted it from the path. But regular standbys don't have
+ // knowledge of the namespaces, so we need
+ // to add an extra check
+ if !redirect && !core.PerfStandby() {
+ for _, websocketPath := range websocketRawPaths {
+ if strings.Contains(path, websocketPath) {
+ redirect = true
+ break
+ }
+ }
+ }
+ if redirect {
+ core.Logger().Trace("cannot forward request (path included in always redirect paths), falling back to redirection to standby")
+ respondStandby(core, w, r)
return
}
@@ -973,16 +987,18 @@ func forwardRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) {
statusCode, header, retBytes, err := core.ForwardRequest(r)
if err != nil {
if err == vault.ErrCannotForward {
- core.Logger().Debug("cannot forward request (possibly disabled on active node), falling back")
+ core.Logger().Trace("cannot forward request (possibly disabled on active node), falling back to redirection to standby")
} else {
core.Logger().Error("forward request error", "error", err)
}
// Fall back to redirection
- respondStandby(core, w, r.URL)
+ respondStandby(core, w, r)
return
}
+ core.Logger().Trace("request forwarded", "statusCode", statusCode)
+
for k, v := range header {
w.Header()[k] = v
}
@@ -1041,7 +1057,7 @@ func request(core *vault.Core, w http.ResponseWriter, rawReq *http.Request, r *l
return resp, false, false
}
if errwrap.Contains(err, consts.ErrStandby.Error()) {
- respondStandby(core, w, rawReq.URL)
+ respondStandby(core, w, rawReq)
return resp, false, false
}
if err != nil && errwrap.Contains(err, logical.ErrPerfStandbyPleaseForward.Error()) {
@@ -1090,7 +1106,8 @@ func request(core *vault.Core, w http.ResponseWriter, rawReq *http.Request, r *l
}
// respondStandby is used to trigger a redirect in the case that this Vault is currently a hot standby
-func respondStandby(core *vault.Core, w http.ResponseWriter, reqURL *url.URL) {
+func respondStandby(core *vault.Core, w http.ResponseWriter, r *http.Request) {
+ reqURL := r.URL
// Request the leader address
_, redirectAddr, _, err := core.Leader()
if err != nil {
@@ -1127,8 +1144,13 @@ func respondStandby(core *vault.Core, w http.ResponseWriter, reqURL *url.URL) {
RawQuery: reqURL.RawQuery,
}
+ ctx := r.Context()
+ ns, err := namespace.FromContext(ctx)
+ if err != nil {
+ respondError(w, http.StatusBadRequest, err)
+ }
// WebSockets schemas are ws or wss
- if websocketPaths.HasPath(reqURL.Path) {
+ if websocketPaths.HasPath(trimPath(ns, reqURL.Path)) {
if finalURL.Scheme == "http" {
finalURL.Scheme = "ws"
} else {
@@ -1136,6 +1158,11 @@ func respondStandby(core *vault.Core, w http.ResponseWriter, reqURL *url.URL) {
}
}
+ originalPath, ok := logical.ContextOriginalRequestPathValue(ctx)
+ if ok {
+ finalURL.Path = originalPath
+ }
+
// Ensure there is a scheme, default to https
if finalURL.Scheme == "" {
finalURL.Scheme = "https"
@@ -1387,3 +1414,8 @@ func respondOIDCPermissionDenied(w http.ResponseWriter) {
enc := json.NewEncoder(w)
enc.Encode(oidcResponse)
}
+
+// trimPath removes the /v1/ prefix and the namespace from the path
+func trimPath(ns *namespace.Namespace, path string) string {
+ return ns.TrimmedPath(path[len("/v1/"):])
+}
diff --git a/http/handler_test.go b/http/handler_test.go
index ebfee04016..dde4acd3a8 100644
--- a/http/handler_test.go
+++ b/http/handler_test.go
@@ -9,7 +9,7 @@ import (
"crypto/tls"
"encoding/json"
"errors"
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"net/textproto"
@@ -885,7 +885,7 @@ func TestHandler_Parse_Form(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- req.Body = ioutil.NopCloser(strings.NewReader(values.Encode()))
+ req.Body = io.NopCloser(strings.NewReader(values.Encode()))
req.Header.Set("x-vault-token", cluster.RootToken)
req.Header.Set("content-type", "application/x-www-form-urlencoded")
resp, err := c.Do(req)
diff --git a/http/help.go b/http/help.go
index e4d03b261c..24ff14a8e9 100644
--- a/http/help.go
+++ b/http/help.go
@@ -40,7 +40,7 @@ func handleHelp(core *vault.Core, w http.ResponseWriter, r *http.Request) {
respondError(w, http.StatusNotFound, errors.New("Missing /v1/ prefix in path. Use vault path-help command to retrieve API help for paths"))
return
}
- path := ns.TrimmedPath(r.URL.Path[len("/v1/"):])
+ path := trimPath(ns, r.URL.Path)
req := &logical.Request{
Operation: logical.HelpOperation,
diff --git a/http/logical.go b/http/logical.go
index 089a24b9c9..20076ae29c 100644
--- a/http/logical.go
+++ b/http/logical.go
@@ -50,8 +50,7 @@ func buildLogicalRequestNoAuth(perfStandby bool, ra *vault.RouterAccess, w http.
if err != nil {
return nil, nil, http.StatusBadRequest, nil
}
- path := ns.TrimmedPath(r.URL.Path[len("/v1/"):])
-
+ path := trimPath(ns, r.URL.Path)
var data map[string]interface{}
var origBody io.ReadCloser
var passHTTPReq bool
@@ -361,11 +360,13 @@ func handleLogicalInternal(core *vault.Core, injectDataIntoTopLevel bool, noForw
respondError(w, http.StatusInternalServerError, err)
return
}
+ trimmedPath := trimPath(ns, r.URL.Path)
+
nsPath := ns.Path
if ns.ID == namespace.RootNamespaceID {
nsPath = ""
}
- if strings.HasPrefix(r.URL.Path, fmt.Sprintf("/v1/%ssys/events/subscribe/", nsPath)) {
+ if websocketPaths.HasPath(trimmedPath) {
handler := entHandleEventsSubscribe(core, req)
if handler != nil {
handler.ServeHTTP(w, r)
diff --git a/http/logical_test.go b/http/logical_test.go
index 682b8f6dea..6550128185 100644
--- a/http/logical_test.go
+++ b/http/logical_test.go
@@ -34,6 +34,7 @@ import (
"github.com/hashicorp/vault/sdk/physical"
"github.com/hashicorp/vault/sdk/physical/inmem"
"github.com/hashicorp/vault/vault"
+ "github.com/stretchr/testify/require"
)
func TestLogical(t *testing.T) {
@@ -744,9 +745,12 @@ func TestLogical_AuditPort(t *testing.T) {
decoder := json.NewDecoder(auditLogFile)
- var auditRecord map[string]interface{}
count := 0
- for decoder.Decode(&auditRecord) == nil {
+ for decoder.More() {
+ var auditRecord map[string]interface{}
+ err := decoder.Decode(&auditRecord)
+ require.NoError(t, err)
+
count += 1
// Skip the first line
@@ -851,14 +855,25 @@ func TestLogical_ErrRelativePath(t *testing.T) {
}
func testBuiltinPluginMetadataAuditLog(t *testing.T, log map[string]interface{}, expectedMountClass string) {
+ t.Helper()
+
if mountClass, ok := log["mount_class"].(string); !ok {
t.Fatalf("mount_class should be a string, not %T", log["mount_class"])
} else if mountClass != expectedMountClass {
t.Fatalf("bad: mount_class should be %s, not %s", expectedMountClass, mountClass)
}
- if _, ok := log["mount_running_version"].(string); !ok {
- t.Fatalf("mount_running_version should be a string, not %T", log["mount_running_version"])
+ // Requests have 'mount_running_version' but Responses have 'mount_running_plugin_version'
+ runningVersionRaw, runningVersionRawOK := log["mount_running_version"]
+ runningPluginVersionRaw, runningPluginVersionRawOK := log["mount_running_plugin_version"]
+ if !runningVersionRawOK && !runningPluginVersionRawOK {
+ t.Fatalf("mount_running_version/mount_running_plugin_version should be present")
+ } else if runningVersionRawOK {
+ if _, ok := runningVersionRaw.(string); !ok {
+ t.Fatalf("mount_running_version should be string, not %T", runningVersionRaw)
+ }
+ } else if _, ok := runningPluginVersionRaw.(string); !ok {
+ t.Fatalf("mount_running_plugin_version should be string, not %T", runningPluginVersionRaw)
}
if _, ok := log["mount_running_sha256"].(string); ok {
@@ -905,38 +920,45 @@ func TestLogical_AuditEnabled_ShouldLogPluginMetadata_Auth(t *testing.T) {
"file_path": auditLogFile.Name(),
},
})
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
_, err = c.Logical().Write("auth/token/create", map[string]interface{}{
"ttl": "10s",
})
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
+
+ // Disable audit now we're done performing operations
+ err = c.Sys().DisableAudit("file")
+ require.NoError(t, err)
// Check the audit trail on request and response
decoder := json.NewDecoder(auditLogFile)
- var auditRecord map[string]interface{}
- for decoder.Decode(&auditRecord) == nil {
- auditRequest := map[string]interface{}{}
- if req, ok := auditRecord["request"]; ok {
- auditRequest = req.(map[string]interface{})
- if auditRequest["path"] != "auth/token/create" {
- continue
- }
- }
- testBuiltinPluginMetadataAuditLog(t, auditRequest, consts.PluginTypeCredential.String())
+ for decoder.More() {
+ var auditRecord map[string]interface{}
+ err := decoder.Decode(&auditRecord)
+ require.NoError(t, err)
- auditResponse := map[string]interface{}{}
- if req, ok := auditRecord["response"]; ok {
- auditRequest = req.(map[string]interface{})
- if auditResponse["path"] != "auth/token/create" {
+ if req, ok := auditRecord["request"]; ok {
+ auditRequest, ok := req.(map[string]interface{})
+ require.True(t, ok)
+
+ path, ok := auditRequest["path"].(string)
+ require.True(t, ok)
+
+ if path != "auth/token/create" {
continue
}
+
+ testBuiltinPluginMetadataAuditLog(t, auditRequest, consts.PluginTypeCredential.String())
+ }
+
+ // Should never have a response without a corresponding request.
+ if resp, ok := auditRecord["response"]; ok {
+ auditResponse, ok := resp.(map[string]interface{})
+ require.True(t, ok)
+
+ testBuiltinPluginMetadataAuditLog(t, auditResponse, consts.PluginTypeCredential.String())
}
- testBuiltinPluginMetadataAuditLog(t, auditResponse, consts.PluginTypeCredential.String())
}
}
@@ -974,9 +996,7 @@ func TestLogical_AuditEnabled_ShouldLogPluginMetadata_Secret(t *testing.T) {
// Enable the audit backend
tempDir := t.TempDir()
auditLogFile, err := os.CreateTemp(tempDir, "")
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
err = c.Sys().EnableAuditWithOptions("file", &api.EnableAuditOptions{
Type: "file",
@@ -984,9 +1004,7 @@ func TestLogical_AuditEnabled_ShouldLogPluginMetadata_Secret(t *testing.T) {
"file_path": auditLogFile.Name(),
},
})
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
{
writeData := map[string]interface{}{
@@ -1003,26 +1021,36 @@ func TestLogical_AuditEnabled_ShouldLogPluginMetadata_Secret(t *testing.T) {
})
}
+ // Disable audit now we're done performing operations
+ err = c.Sys().DisableAudit("file")
+ require.NoError(t, err)
+
// Check the audit trail on request and response
decoder := json.NewDecoder(auditLogFile)
- var auditRecord map[string]interface{}
- for decoder.Decode(&auditRecord) == nil {
- auditRequest := map[string]interface{}{}
- if req, ok := auditRecord["request"]; ok {
- auditRequest = req.(map[string]interface{})
- if auditRequest["path"] != "kv/data/foo" {
- continue
- }
- }
- testBuiltinPluginMetadataAuditLog(t, auditRequest, consts.PluginTypeSecrets.String())
+ for decoder.More() {
+ var auditRecord map[string]interface{}
+ err := decoder.Decode(&auditRecord)
+ require.NoError(t, err)
- auditResponse := map[string]interface{}{}
- if req, ok := auditRecord["response"]; ok {
- auditRequest = req.(map[string]interface{})
- if auditResponse["path"] != "kv/data/foo" {
+ if req, ok := auditRecord["request"]; ok {
+ auditRequest, ok := req.(map[string]interface{})
+ require.True(t, ok)
+
+ path, ok := auditRequest["path"]
+ require.True(t, ok)
+
+ if path != "kv/data/foo" {
continue
}
+
+ testBuiltinPluginMetadataAuditLog(t, auditRequest, consts.PluginTypeSecrets.String())
+ }
+
+ if resp, ok := auditRecord["response"]; ok {
+ auditResponse, ok := resp.(map[string]interface{})
+ require.True(t, ok)
+
+ testBuiltinPluginMetadataAuditLog(t, auditResponse, consts.PluginTypeSecrets.String())
}
- testBuiltinPluginMetadataAuditLog(t, auditResponse, consts.PluginTypeSecrets.String())
}
}
diff --git a/http/plugin_test.go b/http/plugin_test.go
index b215a6b1c6..8a1b35d98d 100644
--- a/http/plugin_test.go
+++ b/http/plugin_test.go
@@ -6,7 +6,7 @@ package http
import (
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"os"
"reflect"
"sync"
@@ -15,7 +15,6 @@ import (
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/api"
bplugin "github.com/hashicorp/vault/builtin/plugin"
- "github.com/hashicorp/vault/helper/benchhelpers"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
@@ -48,7 +47,7 @@ func getPluginClusterAndCore(t *testing.T, logger log.Logger) (*vault.TestCluste
PluginDirectory: pluginDir,
}
- cluster := vault.NewTestCluster(benchhelpers.TBtoT(t), coreConfig, &vault.TestClusterOptions{
+ cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
HandlerFunc: Handler,
})
cluster.Start()
@@ -56,8 +55,8 @@ func getPluginClusterAndCore(t *testing.T, logger log.Logger) (*vault.TestCluste
cores := cluster.Cores
core := cores[0]
- vault.TestWaitActive(benchhelpers.TBtoT(t), core.Core)
- vault.TestAddTestPlugin(benchhelpers.TBtoT(t), core.Core, "mock-plugin", consts.PluginTypeSecrets, "", "TestPlugin_PluginMain",
+ vault.TestWaitActive(t, core.Core)
+ vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeSecrets, "", "TestPlugin_PluginMain",
[]string{fmt.Sprintf("%s=%s", pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)})
// Mount the mock plugin
@@ -148,7 +147,7 @@ func TestPlugin_MockRawResponse(t *testing.T) {
t.Fatal(err)
}
defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
diff --git a/http/sys_health_test.go b/http/sys_health_test.go
index bd64ea8532..dcc3473b06 100644
--- a/http/sys_health_test.go
+++ b/http/sys_health_test.go
@@ -4,7 +4,7 @@
package http
import (
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"testing"
@@ -206,7 +206,7 @@ func TestSysHealth_head(t *testing.T) {
t.Fatalf("HEAD %v expected code %d, got %d.", queryurl, tt.code, resp.StatusCode)
}
- data, err := ioutil.ReadAll(resp.Body)
+ data, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("err on %v: %s", queryurl, err)
}
diff --git a/http/sys_rekey.go b/http/sys_rekey.go
index 0968076246..a43da4f1df 100644
--- a/http/sys_rekey.go
+++ b/http/sys_rekey.go
@@ -20,7 +20,7 @@ func handleSysRekeyInit(core *vault.Core, recovery bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
standby, _ := core.Standby()
if standby {
- respondStandby(core, w, r.URL)
+ respondStandby(core, w, r)
return
}
@@ -155,7 +155,7 @@ func handleSysRekeyUpdate(core *vault.Core, recovery bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
standby, _ := core.Standby()
if standby {
- respondStandby(core, w, r.URL)
+ respondStandby(core, w, r)
return
}
@@ -228,7 +228,7 @@ func handleSysRekeyVerify(core *vault.Core, recovery bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
standby, _ := core.Standby()
if standby {
- respondStandby(core, w, r.URL)
+ respondStandby(core, w, r)
return
}
diff --git a/internal/observability/event/options.go b/internal/observability/event/options.go
index 62fb426595..7e419d5595 100644
--- a/internal/observability/event/options.go
+++ b/internal/observability/event/options.go
@@ -6,10 +6,12 @@ package event
import (
"fmt"
"os"
+ "reflect"
"strconv"
"strings"
"time"
+ "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/go-uuid"
)
@@ -26,6 +28,7 @@ type options struct {
withSocketType string
withMaxDuration time.Duration
withFileMode *os.FileMode
+ withLogger hclog.Logger
}
// getDefaultOptions returns Options with their default values.
@@ -201,3 +204,15 @@ func WithFileMode(mode string) Option {
return nil
}
}
+
+// WithLogger provides an Option to supply a logger which will be used to write logs.
+// NOTE: If no logger is supplied then logging may not be possible.
+func WithLogger(l hclog.Logger) Option {
+ return func(o *options) error {
+ if l != nil && !reflect.ValueOf(l).IsNil() {
+ o.withLogger = l
+ }
+
+ return nil
+ }
+}
diff --git a/internal/observability/event/options_test.go b/internal/observability/event/options_test.go
index a3e47a2c48..2b6a1fe3ae 100644
--- a/internal/observability/event/options_test.go
+++ b/internal/observability/event/options_test.go
@@ -8,6 +8,7 @@ import (
"testing"
"time"
+ "github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/require"
)
@@ -423,3 +424,37 @@ func TestOptions_WithFileMode(t *testing.T) {
})
}
}
+
+// TestOptions_WithLogger exercises WithLogger Option to ensure it performs as expected.
+func TestOptions_WithLogger(t *testing.T) {
+ t.Parallel()
+
+ tests := map[string]struct {
+ value hclog.Logger
+ isNilExpected bool
+ }{
+ "nil-pointer": {
+ value: nil,
+ isNilExpected: true,
+ },
+ "logger": {
+ value: hclog.NewNullLogger(),
+ },
+ }
+
+ for name, tc := range tests {
+ t.Run(name, func(t *testing.T) {
+ t.Parallel()
+
+ opts := &options{}
+ applyOption := WithLogger(tc.value)
+ err := applyOption(opts)
+ require.NoError(t, err)
+ if tc.isNilExpected {
+ require.Nil(t, opts.withLogger)
+ } else {
+ require.NotNil(t, opts.withLogger)
+ }
+ })
+ }
+}
diff --git a/internal/observability/event/sink_file.go b/internal/observability/event/sink_file.go
index 0f5e22e4c8..5385eac1df 100644
--- a/internal/observability/event/sink_file.go
+++ b/internal/observability/event/sink_file.go
@@ -14,6 +14,7 @@ import (
"sync"
"github.com/hashicorp/eventlogger"
+ "github.com/hashicorp/go-hclog"
)
// defaultFileMode is the default file permissions (read/write for everyone).
@@ -31,6 +32,7 @@ type FileSink struct {
fileMode os.FileMode
path string
requiredFormat string
+ logger hclog.Logger
}
// NewFileSink should be used to create a new FileSink.
@@ -69,6 +71,7 @@ func NewFileSink(path string, format string, opt ...Option) (*FileSink, error) {
fileMode: mode,
requiredFormat: format,
path: p,
+ logger: opts.withLogger,
}
// Ensure that the file can be successfully opened for writing;
@@ -82,13 +85,22 @@ func NewFileSink(path string, format string, opt ...Option) (*FileSink, error) {
}
// Process handles writing the event to the file sink.
-func (s *FileSink) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
+func (s *FileSink) Process(ctx context.Context, e *eventlogger.Event) (_ *eventlogger.Event, retErr error) {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
+ defer func() {
+ // If the context is errored (cancelled), and we were planning to return
+ // an error, let's also log (if we have a logger) in case the eventlogger's
+ // status channel and errors propagated.
+ if err := ctx.Err(); err != nil && retErr != nil && s.logger != nil {
+ s.logger.Error("file sink error", "context", err, "error", retErr)
+ }
+ }()
+
if e == nil {
return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
}
@@ -103,7 +115,7 @@ func (s *FileSink) Process(ctx context.Context, e *eventlogger.Event) (*eventlog
return nil, fmt.Errorf("unable to retrieve event formatted as %q: %w", s.requiredFormat, ErrInvalidParameter)
}
- err := s.log(formatted)
+ err := s.log(ctx, formatted)
if err != nil {
return nil, fmt.Errorf("error writing file for sink %q: %w", s.path, err)
}
@@ -177,10 +189,18 @@ func (s *FileSink) open() error {
}
// log writes the buffer to the file.
-// It acquires a lock on the file to do this.
-func (s *FileSink) log(data []byte) error {
+// NOTE: We attempt to acquire a lock on the file in order to write, but will
+// yield if the context is 'done'.
+func (s *FileSink) log(ctx context.Context, data []byte) error {
+ // Wait for the lock, but ensure we check for a cancelled context as soon as
+ // we have it, as there's no point in continuing if we're cancelled.
s.fileLock.Lock()
defer s.fileLock.Unlock()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
reader := bytes.NewReader(data)
diff --git a/internal/observability/event/sink_file_test.go b/internal/observability/event/sink_file_test.go
index 4018bfd474..6f4b721b07 100644
--- a/internal/observability/event/sink_file_test.go
+++ b/internal/observability/event/sink_file_test.go
@@ -4,13 +4,18 @@
package event
import (
+ "context"
+ "errors"
+ "fmt"
"os"
"path/filepath"
+ "sync/atomic"
"testing"
"time"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/vault/helper/namespace"
+ "github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/stretchr/testify/require"
)
@@ -236,6 +241,13 @@ func TestFileSink_Process(t *testing.T) {
IsErrorExpected: true,
ExpectedErrorMessage: "event is nil: invalid parameter",
},
+ "happy-path": {
+ Path: "juan.log",
+ ShouldCreateFile: true,
+ Format: "json",
+ Data: "{\"foo\": \"bar\"}",
+ IsErrorExpected: false,
+ },
}
for name, tc := range tests {
@@ -297,3 +309,46 @@ func TestFileSink_Process(t *testing.T) {
})
}
}
+
+// TestFileSink_log_cancelledContext tests that 'log' is context aware and won't
+// just wait for the lock on the file sink forever.
+func TestFileSink_log_cancelledContext(t *testing.T) {
+ tempDir := t.TempDir()
+ tempPath := filepath.Join(tempDir, "juan.log")
+ data := []byte("{\"foo\": \"bar\"}")
+
+ sink, err := NewFileSink(tempPath, "json")
+ require.NoError(t, err)
+ require.NotNil(t, sink)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ t.Cleanup(func() { cancel() })
+
+ // Manually acquire the lock so that the 'log' method cannot.
+ sink.fileLock.Lock()
+
+ var done atomic.Bool
+ go func() {
+ err = sink.log(ctx, data)
+ done.Store(true)
+ }()
+
+ // We shouldn't have an error as 'log' will be trying to acquire the lock.
+ require.NoError(t, err)
+
+ // Manually cancel the context and unlock to let the waiting 'log' in.
+ cancel()
+ sink.fileLock.Unlock()
+
+ // Just a little bit of time to make sure that 'log' returned and err was set.
+ corehelpers.RetryUntil(t, 3*time.Second, func() error {
+ if done.Load() {
+ return nil
+ }
+
+ return fmt.Errorf("logging still not done")
+ })
+
+ // We expect that the error now has context cancelled in it.
+ require.True(t, errors.Is(err, context.Canceled))
+}
diff --git a/internal/observability/event/sink_socket.go b/internal/observability/event/sink_socket.go
index 7d75023060..dc88a78b71 100644
--- a/internal/observability/event/sink_socket.go
+++ b/internal/observability/event/sink_socket.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/hashicorp/eventlogger"
+ "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror"
)
@@ -25,6 +26,7 @@ type SocketSink struct {
maxDuration time.Duration
socketLock sync.RWMutex
connection net.Conn
+ logger hclog.Logger
}
// NewSocketSink should be used to create a new SocketSink.
@@ -52,21 +54,28 @@ func NewSocketSink(address string, format string, opt ...Option) (*SocketSink, e
maxDuration: opts.withMaxDuration,
socketLock: sync.RWMutex{},
connection: nil,
+ logger: opts.withLogger,
}
return sink, nil
}
// Process handles writing the event to the socket.
-func (s *SocketSink) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
+func (s *SocketSink) Process(ctx context.Context, e *eventlogger.Event) (_ *eventlogger.Event, retErr error) {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
- s.socketLock.Lock()
- defer s.socketLock.Unlock()
+ defer func() {
+ // If the context is errored (cancelled), and we were planning to return
+ // an error, let's also log (if we have a logger) in case the eventlogger's
+ // status channel and errors propagated.
+ if err := ctx.Err(); err != nil && retErr != nil && s.logger != nil {
+ s.logger.Error("socket sink error", "context", err, "error", retErr)
+ }
+ }()
if e == nil {
return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
@@ -77,6 +86,16 @@ func (s *SocketSink) Process(ctx context.Context, e *eventlogger.Event) (*eventl
return nil, fmt.Errorf("unable to retrieve event formatted as %q: %w", s.requiredFormat, ErrInvalidParameter)
}
+ // Wait for the lock, but ensure we check for a cancelled context as soon as
+ // we have it, as there's no point in continuing if we're cancelled.
+ s.socketLock.Lock()
+ defer s.socketLock.Unlock()
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+ }
+
// Try writing and return early if successful.
err := s.write(ctx, formatted)
if err == nil {
@@ -121,7 +140,14 @@ func (_ *SocketSink) Type() eventlogger.NodeType {
}
// connect attempts to establish a connection using the socketType and address.
+// NOTE: connect is context aware and will not attempt to connect if the context is 'done'.
func (s *SocketSink) connect(ctx context.Context) error {
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
+
// If we're already connected, we should have disconnected first.
if s.connection != nil {
return nil
diff --git a/internal/observability/event/sink_syslog.go b/internal/observability/event/sink_syslog.go
index 6d6b6b6aee..147b870890 100644
--- a/internal/observability/event/sink_syslog.go
+++ b/internal/observability/event/sink_syslog.go
@@ -9,6 +9,7 @@ import (
"strings"
"github.com/hashicorp/eventlogger"
+ "github.com/hashicorp/go-hclog"
gsyslog "github.com/hashicorp/go-syslog"
)
@@ -17,7 +18,8 @@ var _ eventlogger.Node = (*SyslogSink)(nil)
// SyslogSink is a sink node which handles writing events to syslog.
type SyslogSink struct {
requiredFormat string
- logger gsyslog.Syslogger
+ syslogger gsyslog.Syslogger
+ logger hclog.Logger
}
// NewSyslogSink should be used to create a new SyslogSink.
@@ -38,17 +40,32 @@ func NewSyslogSink(format string, opt ...Option) (*SyslogSink, error) {
return nil, fmt.Errorf("error creating syslogger: %w", err)
}
- return &SyslogSink{requiredFormat: format, logger: logger}, nil
+ syslog := &SyslogSink{
+ requiredFormat: format,
+ syslogger: logger,
+ logger: opts.withLogger,
+ }
+
+ return syslog, nil
}
// Process handles writing the event to the syslog.
-func (s *SyslogSink) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
+func (s *SyslogSink) Process(ctx context.Context, e *eventlogger.Event) (_ *eventlogger.Event, retErr error) {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
+ defer func() {
+ // If the context is errored (cancelled), and we were planning to return
+ // an error, let's also log (if we have a logger) in case the eventlogger's
+ // status channel and errors propagated.
+ if err := ctx.Err(); err != nil && retErr != nil && s.logger != nil {
+ s.logger.Error("syslog sink error", "context", err, "error", retErr)
+ }
+ }()
+
if e == nil {
return nil, fmt.Errorf("event is nil: %w", ErrInvalidParameter)
}
@@ -58,7 +75,7 @@ func (s *SyslogSink) Process(ctx context.Context, e *eventlogger.Event) (*eventl
return nil, fmt.Errorf("unable to retrieve event formatted as %q: %w", s.requiredFormat, ErrInvalidParameter)
}
- _, err := s.logger.Write(formatted)
+ _, err := s.syslogger.Write(formatted)
if err != nil {
return nil, fmt.Errorf("error writing to syslog: %w", err)
}
diff --git a/internalshared/configutil/listener.go b/internalshared/configutil/listener.go
index 0504702028..1e959b5c86 100644
--- a/internalshared/configutil/listener.go
+++ b/internalshared/configutil/listener.go
@@ -562,9 +562,9 @@ func (l *Listener) parseProxySettings() error {
// Validation/sanity check on allowed settings for behavior.
switch l.ProxyProtocolBehavior {
- case "allow_authorized", "deny_authorized", "use_always", "":
+ case "allow_authorized", "deny_unauthorized", "use_always", "":
// Ignore these cases, they're all valid values.
- // In the case of 'allow_authorized' and 'deny_authorized', we don't need
+ // In the case of 'allow_authorized' and 'deny_unauthorized', we don't need
// to check how many addresses we have in ProxyProtocolAuthorizedAddrs
// as parseutil.ParseAddrs returns "one or more addresses" (or an error)
// so we'd have returned earlier.
diff --git a/internalshared/configutil/listener_test.go b/internalshared/configutil/listener_test.go
index bfd922faa8..51d0c094ed 100644
--- a/internalshared/configutil/listener_test.go
+++ b/internalshared/configutil/listener_test.go
@@ -529,7 +529,7 @@ func TestListener_parseProxySettings(t *testing.T) {
"behavior-deny": {
rawProxyProtocolAuthorizedAddrs: "10.0.0.1,10.0.2.1",
expectedNumAddrs: 2,
- proxyBehavior: "deny_authorized",
+ proxyBehavior: "deny_unauthorized",
isErrorExpected: false,
},
}
diff --git a/physical/azure/azure.go b/physical/azure/azure.go
index a4eb29f899..e941af1611 100644
--- a/physical/azure/azure.go
+++ b/physical/azure/azure.go
@@ -7,7 +7,7 @@ import (
"context"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net/url"
"os"
"regexp"
@@ -68,8 +68,8 @@ func NewAzureBackend(conf map[string]string, logger log.Logger) (physical.Backen
return nil, fmt.Errorf("'accountName' must be set")
}
}
- if err := validateAccountName(name); err != nil {
- return nil, fmt.Errorf("invalid account name %s: %w", name, err)
+ if err := validateAccountName(accountName); err != nil {
+ return nil, fmt.Errorf("invalid account name %s: %w", accountName, err)
}
accountKey := os.Getenv("AZURE_ACCOUNT_KEY")
@@ -271,7 +271,7 @@ func (a *AzureBackend) Get(ctx context.Context, key string) (*physical.Entry, er
reader := res.Body(azblob.RetryReaderOptions{})
defer reader.Close()
- data, err := ioutil.ReadAll(reader)
+ data, err := io.ReadAll(reader)
ent := &physical.Entry{
Key: key,
@@ -344,7 +344,7 @@ func (a *AzureBackend) List(ctx context.Context, prefix string) ([]string, error
// getAuthTokenFromIMDS uses the Azure Instance Metadata Service to retrieve a short-lived credential using OAuth
// more info on this https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
func getAuthTokenFromIMDS(resource string) (*adal.ServicePrincipalToken, error) {
- msiEndpoint, err := adal.GetMSIVMEndpoint()
+ msiEndpoint, err := adal.GetMSIEndpoint()
if err != nil {
return nil, err
}
diff --git a/physical/azure/azure_test.go b/physical/azure/azure_test.go
index 22344a6bca..2e491bd9b8 100644
--- a/physical/azure/azure_test.go
+++ b/physical/azure/azure_test.go
@@ -35,7 +35,7 @@ func testFixture(t *testing.T) (*AzureBackend, func()) {
t.Helper()
ts := time.Now().UnixNano()
- name := fmt.Sprintf("vlt%d", ts)
+ name := fmt.Sprintf("vlt-%d", ts)
_ = os.Setenv("AZURE_BLOB_CONTAINER", name)
cleanup := func() {}
diff --git a/physical/cassandra/cassandra.go b/physical/cassandra/cassandra.go
index a7f22c468d..9e650f5ff8 100644
--- a/physical/cassandra/cassandra.go
+++ b/physical/cassandra/cassandra.go
@@ -150,6 +150,14 @@ func NewCassandraBackend(conf map[string]string, logger log.Logger) (physical.Ba
cluster.Timeout = time.Duration(connectionTimeout) * time.Second
}
+ if disableInitialHostLookupStr, ok := conf["disable_host_initial_lookup"]; ok {
+ disableInitialHostLookup, err := strconv.ParseBool(disableInitialHostLookupStr)
+ if err != nil {
+ return nil, fmt.Errorf("'disable_host_initial_lookup' must be a bool")
+ }
+ cluster.DisableInitialHostLookup = disableInitialHostLookup
+ }
+
if err := setupCassandraTLS(conf, cluster); err != nil {
return nil, err
}
diff --git a/physical/couchdb/couchdb.go b/physical/couchdb/couchdb.go
index 0a1c379c6e..cbb32e5609 100644
--- a/physical/couchdb/couchdb.go
+++ b/physical/couchdb/couchdb.go
@@ -8,7 +8,7 @@ import (
"context"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"os"
@@ -114,7 +114,7 @@ func (m *couchDBClient) get(key string) (*physical.Entry, error) {
} else if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("GET returned %q", resp.Status)
}
- bs, err := ioutil.ReadAll(resp.Body)
+ bs, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -143,7 +143,7 @@ func (m *couchDBClient) list(prefix string) ([]couchDBListItem, error) {
}
defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
+ data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
diff --git a/physical/couchdb/couchdb_test.go b/physical/couchdb/couchdb_test.go
index bc8f6b41df..0428d52d25 100644
--- a/physical/couchdb/couchdb_test.go
+++ b/physical/couchdb/couchdb_test.go
@@ -6,7 +6,7 @@ package couchdb
import (
"context"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"os"
@@ -145,7 +145,7 @@ func setupCouchDB(ctx context.Context, host string, port int) (docker.ServiceCon
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
- bs, _ := ioutil.ReadAll(resp.Body)
+ bs, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("failed to create database: %s %s\n", resp.Status, string(bs))
}
}
@@ -164,7 +164,7 @@ func setupCouchDB(ctx context.Context, host string, port int) (docker.ServiceCon
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
- bs, _ := ioutil.ReadAll(resp.Body)
+ bs, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("Failed to create admin user: %s %s\n", resp.Status, string(bs))
}
}
diff --git a/physical/dynamodb/dynamodb.go b/physical/dynamodb/dynamodb.go
index 7b6413f143..c4484d20d4 100644
--- a/physical/dynamodb/dynamodb.go
+++ b/physical/dynamodb/dynamodb.go
@@ -410,6 +410,11 @@ func (d *DynamoDBBackend) List(ctx context.Context, prefix string) ([]string, er
}},
},
},
+ ProjectionExpression: aws.String("#key, #path"),
+ ExpressionAttributeNames: map[string]*string{
+ "#key": aws.String("Key"),
+ "#path": aws.String("Path"),
+ },
}
d.permitPool.Acquire()
@@ -453,6 +458,11 @@ func (d *DynamoDBBackend) hasChildren(prefix string, exclude []string) (bool, er
}},
},
},
+ ProjectionExpression: aws.String("#key, #path"),
+ ExpressionAttributeNames: map[string]*string{
+ "#key": aws.String("Key"),
+ "#path": aws.String("Path"),
+ },
// Avoid fetching too many items from DynamoDB for performance reasons.
// We want to know if there are any children we don't expect to see.
// Answering that question requires fetching a minimum of one more item
diff --git a/physical/gcs/gcs.go b/physical/gcs/gcs.go
index eea7a515ac..51b1f926ff 100644
--- a/physical/gcs/gcs.go
+++ b/physical/gcs/gcs.go
@@ -8,7 +8,7 @@ import (
"crypto/md5"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"os"
"sort"
"strconv"
@@ -230,7 +230,7 @@ func (b *Backend) Get(ctx context.Context, key string) (retEntry *physical.Entry
}
}()
- value, err := ioutil.ReadAll(r)
+ value, err := io.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("failed to read value into a string: %w", err)
}
diff --git a/physical/oci/oci.go b/physical/oci/oci.go
index 3665813d04..628f310491 100644
--- a/physical/oci/oci.go
+++ b/physical/oci/oci.go
@@ -5,7 +5,7 @@ import (
"bytes"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"sort"
"strconv"
@@ -172,7 +172,7 @@ func (o *Backend) Put(ctx context.Context, entry *physical.Entry) error {
BucketName: &o.bucketName,
ObjectName: &entry.Key,
ContentLength: &size,
- PutObjectBody: ioutil.NopCloser(bytes.NewReader(entry.Value)),
+ PutObjectBody: io.NopCloser(bytes.NewReader(entry.Value)),
OpcMeta: nil,
OpcClientRequestId: &opcClientRequestId,
}
@@ -230,7 +230,7 @@ func (o *Backend) Get(ctx context.Context, key string) (*physical.Entry, error)
return nil, fmt.Errorf("failed to read Value: %w", err)
}
- body, err := ioutil.ReadAll(resp.Content)
+ body, err := io.ReadAll(resp.Content)
if err != nil {
metrics.IncrCounter(metricGetFailed, 1)
return nil, fmt.Errorf("failed to decode Value into bytes: %w", err)
diff --git a/physical/oci/oci_ha.go b/physical/oci/oci_ha.go
index a4c6ad52ea..cc0e0edc62 100644
--- a/physical/oci/oci_ha.go
+++ b/physical/oci/oci_ha.go
@@ -7,7 +7,7 @@ import (
"encoding/json"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"sync"
"sync/atomic"
@@ -398,7 +398,7 @@ func (l *Lock) get(ctx context.Context) (*LockRecord, string, error) {
defer response.RawResponse.Body.Close()
- body, err := ioutil.ReadAll(response.Content)
+ body, err := io.ReadAll(response.Content)
if err != nil {
metrics.IncrCounter(metricGetFailed, 1)
l.backend.logger.Error("Error reading content", "err", err)
@@ -487,7 +487,7 @@ func (l *Lock) writeLock() (bool, error) {
BucketName: &l.backend.lockBucketName,
ObjectName: &l.key,
ContentLength: &size,
- PutObjectBody: ioutil.NopCloser(bytes.NewReader(newLockRecordJson)),
+ PutObjectBody: io.NopCloser(bytes.NewReader(newLockRecordJson)),
OpcMeta: nil,
OpcClientRequestId: &opcClientRequestId,
}
diff --git a/physical/postgresql/postgresql_test.go b/physical/postgresql/postgresql_test.go
index 301fc15ec2..0dc0ce9486 100644
--- a/physical/postgresql/postgresql_test.go
+++ b/physical/postgresql/postgresql_test.go
@@ -22,7 +22,7 @@ func TestPostgreSQLBackend(t *testing.T) {
// Use docker as pg backend if no url is provided via environment variables
connURL := os.Getenv("PGURL")
if connURL == "" {
- cleanup, u := postgresql.PrepareTestContainer(t, "11.1")
+ cleanup, u := postgresql.PrepareTestContainer(t)
defer cleanup()
connURL = u
}
diff --git a/physical/raft/raft.go b/physical/raft/raft.go
index 8a874903ee..d07dedea40 100644
--- a/physical/raft/raft.go
+++ b/physical/raft/raft.go
@@ -39,6 +39,7 @@ import (
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/physical"
"github.com/hashicorp/vault/vault/cluster"
+ "github.com/hashicorp/vault/version"
etcdbolt "go.etcd.io/bbolt"
)
@@ -582,6 +583,7 @@ func NewRaftBackend(conf map[string]string, logger log.Logger) (physical.Backend
failGetInTxn: new(uint32),
raftLogVerifierEnabled: backendConfig.RaftLogVerifierEnabled,
raftLogVerificationInterval: backendConfig.RaftLogVerificationInterval,
+ effectiveSDKVersion: version.GetVersion().Version,
}, nil
}
@@ -660,12 +662,6 @@ func (b *RaftBackend) FailGetInTxn(fail bool) {
atomic.StoreUint32(b.failGetInTxn, val)
}
-func (b *RaftBackend) SetEffectiveSDKVersion(sdkVersion string) {
- b.l.Lock()
- b.effectiveSDKVersion = sdkVersion
- b.l.Unlock()
-}
-
func (b *RaftBackend) RedundancyZone() string {
b.l.RLock()
defer b.l.RUnlock()
@@ -1089,6 +1085,11 @@ type SetupOpts struct {
// RecoveryModeConfig is the configuration for the raft cluster in recovery
// mode.
RecoveryModeConfig *raft.Configuration
+
+ // EffectiveSDKVersion is typically the version string baked into the binary.
+ // We pass it in though because it can be overridden in tests or via ENV in
+ // core.
+ EffectiveSDKVersion string
}
func (b *RaftBackend) StartRecoveryCluster(ctx context.Context, peer Peer) error {
@@ -1132,6 +1133,11 @@ func (b *RaftBackend) SetupCluster(ctx context.Context, opts SetupOpts) error {
return errors.New("no local node id configured")
}
+ if opts.EffectiveSDKVersion != "" {
+ // Override the SDK version
+ b.effectiveSDKVersion = opts.EffectiveSDKVersion
+ }
+
// Setup the raft config
raftConfig := raft.DefaultConfig()
if err := b.applyConfigSettings(raftConfig); err != nil {
diff --git a/physical/raft/raft_autopilot.go b/physical/raft/raft_autopilot.go
index 1acd85cefc..6a5edf9703 100644
--- a/physical/raft/raft_autopilot.go
+++ b/physical/raft/raft_autopilot.go
@@ -89,6 +89,27 @@ type AutopilotConfig struct {
UpgradeVersionTag string `mapstructure:"upgrade_version_tag"`
}
+func (ac *AutopilotConfig) String() string {
+ s := "CleanupDeadServers:%t " +
+ "LastContactThreshold:%s " +
+ "DeadServerLastContactThreshold:%s " +
+ "MaxTrailingLogs:%d " +
+ "MinQuorum:%d " +
+ "ServerStabilizationTime:%s " +
+ "DisableUpgradeMigration:%t " +
+ "RedundancyZoneTag:%s " +
+ "UpgradeVersionTag:%s"
+ return fmt.Sprintf(s, ac.CleanupDeadServers,
+ ac.LastContactThreshold,
+ ac.DeadServerLastContactThreshold,
+ ac.MaxTrailingLogs,
+ ac.MinQuorum,
+ ac.ServerStabilizationTime,
+ ac.DisableUpgradeMigration,
+ ac.RedundancyZoneTag,
+ ac.UpgradeVersionTag)
+}
+
// Merge combines the supplied config with the receiver. Supplied ones take
// priority.
func (to *AutopilotConfig) Merge(from *AutopilotConfig) {
@@ -421,7 +442,10 @@ func (d *Delegate) KnownServers() map[raft.ServerID]*autopilot.Server {
}
followerVersion = leaderVersion
} else {
- delete(d.emptyVersionLogs, currentServerID)
+ if _, ok := d.emptyVersionLogs[currentServerID]; ok {
+ d.logger.Trace("received non-empty version in heartbeat state. no longer need to fake it", "id", id, "update_version", followerVersion)
+ delete(d.emptyVersionLogs, currentServerID)
+ }
}
d.dl.Unlock()
@@ -612,7 +636,8 @@ func (b *RaftBackend) StopAutopilot() {
if b.autopilot == nil {
return
}
- b.autopilot.Stop()
+ stopCh := b.autopilot.Stop()
+ <-stopCh
b.autopilot = nil
b.followerHeartbeatTicker.Stop()
}
@@ -829,6 +854,8 @@ func (b *RaftBackend) SetupAutopilot(ctx context.Context, storageConfig *Autopil
// Merge the setting provided over the API
b.autopilotConfig.Merge(storageConfig)
+ infoArgs := []interface{}{"config", b.autopilotConfig}
+
// Create the autopilot instance
options := []autopilot.Option{
autopilot.WithLogger(b.logger),
@@ -836,17 +863,18 @@ func (b *RaftBackend) SetupAutopilot(ctx context.Context, storageConfig *Autopil
}
if b.autopilotReconcileInterval != 0 {
options = append(options, autopilot.WithReconcileInterval(b.autopilotReconcileInterval))
+ infoArgs = append(infoArgs, []interface{}{"reconcile_interval", b.autopilotReconcileInterval}...)
}
if b.autopilotUpdateInterval != 0 {
options = append(options, autopilot.WithUpdateInterval(b.autopilotUpdateInterval))
+ infoArgs = append(infoArgs, []interface{}{"update_interval", b.autopilotUpdateInterval}...)
}
b.autopilot = autopilot.New(b.raft, NewDelegate(b), options...)
b.followerStates = followerStates
b.followerHeartbeatTicker = time.NewTicker(1 * time.Second)
-
b.l.Unlock()
- b.logger.Info("starting autopilot", "config", b.autopilotConfig, "reconcile_interval", b.autopilotReconcileInterval)
+ b.logger.Info("starting autopilot", infoArgs...)
b.autopilot.Start(ctx)
go b.startFollowerHeartbeatTracker()
diff --git a/physical/raft/snapshot.go b/physical/raft/snapshot.go
index 8a016f2b12..e44769bf6d 100644
--- a/physical/raft/snapshot.go
+++ b/physical/raft/snapshot.go
@@ -267,7 +267,7 @@ func (f *BoltSnapshotStore) openFromFile(id string) (*raft.SnapshotMeta, io.Read
filename := filepath.Join(f.path, id, databaseFilename)
installer := &boltSnapshotInstaller{
meta: meta,
- ReadCloser: ioutil.NopCloser(strings.NewReader(filename)),
+ ReadCloser: io.NopCloser(strings.NewReader(filename)),
filename: filename,
}
diff --git a/physical/raft/snapshot_test.go b/physical/raft/snapshot_test.go
index d85af4da5f..fe7fafd3fc 100644
--- a/physical/raft/snapshot_test.go
+++ b/physical/raft/snapshot_test.go
@@ -495,7 +495,7 @@ func TestRaft_Snapshot_Take_Restore(t *testing.T) {
}
}
- snapFile, cleanup, metadata, err := raft1.WriteSnapshotToTemp(ioutil.NopCloser(recorder.Body), nil)
+ snapFile, cleanup, metadata, err := raft1.WriteSnapshotToTemp(io.NopCloser(recorder.Body), nil)
if err != nil {
t.Fatal(err)
}
diff --git a/physical/raft/testing.go b/physical/raft/testing.go
index 5b2ea601be..0a72e3f13c 100644
--- a/physical/raft/testing.go
+++ b/physical/raft/testing.go
@@ -14,25 +14,32 @@ import (
)
func GetRaft(t testing.TB, bootstrap bool, noStoreState bool) (*RaftBackend, string) {
- return getRaftInternal(t, bootstrap, defaultRaftConfig(t, bootstrap, noStoreState), nil, nil)
+ return getRaftInternal(t, bootstrap, defaultRaftConfig(t, bootstrap, noStoreState), nil, nil, nil)
}
func GetRaftWithConfig(t testing.TB, bootstrap bool, noStoreState bool, conf map[string]string) (*RaftBackend, string) {
defaultConf := defaultRaftConfig(t, bootstrap, noStoreState)
conf["path"] = defaultConf["path"]
conf["doNotStoreLatestState"] = defaultConf["doNotStoreLatestState"]
- return getRaftInternal(t, bootstrap, conf, nil, nil)
+ return getRaftInternal(t, bootstrap, conf, nil, nil, nil)
+}
+
+func GetRaftWithConfigAndSetupOpts(t testing.TB, bootstrap bool, noStoreState bool, conf map[string]string, setupOpts *SetupOpts) (*RaftBackend, string) {
+ defaultConf := defaultRaftConfig(t, bootstrap, noStoreState)
+ conf["path"] = defaultConf["path"]
+ conf["doNotStoreLatestState"] = defaultConf["doNotStoreLatestState"]
+ return getRaftInternal(t, bootstrap, conf, setupOpts, nil, nil)
}
func GetRaftWithConfigAndInitFn(t testing.TB, bootstrap bool, noStoreState bool, conf map[string]string, initFn func(b *RaftBackend)) (*RaftBackend, string) {
defaultConf := defaultRaftConfig(t, bootstrap, noStoreState)
conf["path"] = defaultConf["path"]
conf["doNotStoreLatestState"] = defaultConf["doNotStoreLatestState"]
- return getRaftInternal(t, bootstrap, conf, nil, initFn)
+ return getRaftInternal(t, bootstrap, conf, nil, nil, initFn)
}
func GetRaftWithLogOutput(t testing.TB, bootstrap bool, noStoreState bool, logOutput io.Writer) (*RaftBackend, string) {
- return getRaftInternal(t, bootstrap, defaultRaftConfig(t, bootstrap, noStoreState), logOutput, nil)
+ return getRaftInternal(t, bootstrap, defaultRaftConfig(t, bootstrap, noStoreState), nil, logOutput, nil)
}
func defaultRaftConfig(t testing.TB, bootstrap bool, noStoreState bool) map[string]string {
@@ -51,7 +58,7 @@ func defaultRaftConfig(t testing.TB, bootstrap bool, noStoreState bool) map[stri
return conf
}
-func getRaftInternal(t testing.TB, bootstrap bool, conf map[string]string, logOutput io.Writer, initFn func(b *RaftBackend)) (*RaftBackend, string) {
+func getRaftInternal(t testing.TB, bootstrap bool, conf map[string]string, setupOpts *SetupOpts, logOutput io.Writer, initFn func(b *RaftBackend)) (*RaftBackend, string) {
id, err := uuid.GenerateUUID()
if err != nil {
t.Fatal(err)
@@ -85,7 +92,12 @@ func getRaftInternal(t testing.TB, bootstrap bool, conf map[string]string, logOu
t.Fatal(err)
}
- err = backend.SetupCluster(context.Background(), SetupOpts{})
+ so := SetupOpts{}
+ if setupOpts != nil {
+ so = *setupOpts
+ }
+
+ err = backend.SetupCluster(context.Background(), so)
if err != nil {
t.Fatal(err)
}
diff --git a/physical/raft/types.pb.go b/physical/raft/types.pb.go
index cd3230ddfd..9790739d7c 100644
--- a/physical/raft/types.pb.go
+++ b/physical/raft/types.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: physical/raft/types.proto
@@ -417,7 +417,7 @@ func file_physical_raft_types_proto_rawDescGZIP() []byte {
}
var file_physical_raft_types_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
-var file_physical_raft_types_proto_goTypes = []interface{}{
+var file_physical_raft_types_proto_goTypes = []any{
(*LogOperation)(nil), // 0: raft.LogOperation
(*LogData)(nil), // 1: raft.LogData
(*IndexValue)(nil), // 2: raft.IndexValue
@@ -441,7 +441,7 @@ func file_physical_raft_types_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_physical_raft_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_physical_raft_types_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*LogOperation); i {
case 0:
return &v.state
@@ -453,7 +453,7 @@ func file_physical_raft_types_proto_init() {
return nil
}
}
- file_physical_raft_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_physical_raft_types_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*LogData); i {
case 0:
return &v.state
@@ -465,7 +465,7 @@ func file_physical_raft_types_proto_init() {
return nil
}
}
- file_physical_raft_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_physical_raft_types_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*IndexValue); i {
case 0:
return &v.state
@@ -477,7 +477,7 @@ func file_physical_raft_types_proto_init() {
return nil
}
}
- file_physical_raft_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_physical_raft_types_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*Server); i {
case 0:
return &v.state
@@ -489,7 +489,7 @@ func file_physical_raft_types_proto_init() {
return nil
}
}
- file_physical_raft_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_physical_raft_types_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*ConfigurationValue); i {
case 0:
return &v.state
@@ -501,7 +501,7 @@ func file_physical_raft_types_proto_init() {
return nil
}
}
- file_physical_raft_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_physical_raft_types_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*LocalNodeConfigValue); i {
case 0:
return &v.state
diff --git a/plugins/database/mssql/mssql.go b/plugins/database/mssql/mssql.go
index 833202b8d4..488d7f3922 100644
--- a/plugins/database/mssql/mssql.go
+++ b/plugins/database/mssql/mssql.go
@@ -285,7 +285,7 @@ func (m *MSSQL) revokeUserDefault(ctx context.Context, username string) error {
rows, err := stmt.QueryContext(ctx, username)
if err != nil {
- return err
+ return fmt.Errorf("failed to query users: %w", err)
}
defer rows.Close()
diff --git a/plugins/database/mssql/mssql_test.go b/plugins/database/mssql/mssql_test.go
index 6e866fea95..d549d52cd1 100644
--- a/plugins/database/mssql/mssql_test.go
+++ b/plugins/database/mssql/mssql_test.go
@@ -294,7 +294,7 @@ func TestUpdateUser_password(t *testing.T) {
Username: dbUser,
}
- ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
+ ctx, cancel = context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
deleteResp, err := db.DeleteUser(ctx, deleteReq)
if err != nil {
@@ -342,7 +342,7 @@ func TestDeleteUser(t *testing.T) {
Username: dbUser,
}
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
deleteResp, err := db.DeleteUser(ctx, deleteReq)
if err != nil {
diff --git a/plugins/database/mysql/connection_producer.go b/plugins/database/mysql/connection_producer.go
index 0fb027bb29..f35bfaf522 100644
--- a/plugins/database/mysql/connection_producer.go
+++ b/plugins/database/mysql/connection_producer.go
@@ -123,11 +123,8 @@ func (c *mySQLConnectionProducer) Init(ctx context.Context, conf map[string]inte
}
// validate auth_type if provided
- authType := c.AuthType
- if authType != "" {
- if ok := connutil.ValidateAuthType(authType); !ok {
- return nil, fmt.Errorf("invalid auth_type %s provided", authType)
- }
+ if ok := connutil.ValidateAuthType(c.AuthType); !ok {
+ return nil, fmt.Errorf("invalid auth_type: %s", c.AuthType)
}
if c.AuthType == connutil.AuthTypeGCPIAM {
@@ -322,7 +319,7 @@ func (c *mySQLConnectionProducer) rewriteProtocolForGCP(inDSN string) (string, e
}
func registerDriverMySQL(driverName, credentials string) (cleanup func() error, err error) {
- opts, err := connutil.GetCloudSQLAuthOptions(credentials)
+ opts, err := connutil.GetCloudSQLAuthOptions(credentials, false)
if err != nil {
return nil, err
}
diff --git a/plugins/database/postgresql/postgresql.go b/plugins/database/postgresql/postgresql.go
index 0bdd916412..3a9bf7ae7c 100644
--- a/plugins/database/postgresql/postgresql.go
+++ b/plugins/database/postgresql/postgresql.go
@@ -5,7 +5,11 @@ package postgresql
import (
"context"
+ "crypto/tls"
+ "crypto/x509"
"database/sql"
+ "encoding/pem"
+ "errors"
"fmt"
"regexp"
"strings"
@@ -79,11 +83,65 @@ func new() *PostgreSQL {
type PostgreSQL struct {
*connutil.SQLConnectionProducer
+ TLSCertificateData []byte `json:"tls_certificate" structs:"-" mapstructure:"tls_certificate"`
+ TLSPrivateKey []byte `json:"private_key" structs:"-" mapstructure:"private_key"`
+ TLSCAData []byte `json:"tls_ca" structs:"-" mapstructure:"tls_ca"`
+
usernameProducer template.StringTemplate
passwordAuthentication passwordAuthentication
}
func (p *PostgreSQL) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
+ sslcert, err := strutil.GetString(req.Config, "tls_certificate")
+ if err != nil {
+ return dbplugin.InitializeResponse{}, fmt.Errorf("failed to retrieve tls_certificate: %w", err)
+ }
+
+ sslkey, err := strutil.GetString(req.Config, "private_key")
+ if err != nil {
+ return dbplugin.InitializeResponse{}, fmt.Errorf("failed to retrieve private_key: %w", err)
+ }
+
+ sslrootcert, err := strutil.GetString(req.Config, "tls_ca")
+ if err != nil {
+ return dbplugin.InitializeResponse{}, fmt.Errorf("failed to retrieve tls_ca: %w", err)
+ }
+
+ useTLS := false
+ tlsConfig := &tls.Config{}
+ if sslrootcert != "" {
+ caCertPool := x509.NewCertPool()
+ if !caCertPool.AppendCertsFromPEM([]byte(sslrootcert)) {
+ return dbplugin.InitializeResponse{}, errors.New("unable to add CA to cert pool")
+ }
+
+ tlsConfig.RootCAs = caCertPool
+ tlsConfig.ClientCAs = caCertPool
+ p.TLSConfig = tlsConfig
+ useTLS = true
+ }
+
+ if (sslcert != "" && sslkey == "") || (sslcert == "" && sslkey != "") {
+ return dbplugin.InitializeResponse{}, errors.New(`both "sslcert" and "sslkey" are required`)
+ }
+
+ if sslcert != "" && sslkey != "" {
+ block, _ := pem.Decode([]byte(sslkey))
+
+ cert, err := tls.X509KeyPair([]byte(sslcert), pem.EncodeToMemory(block))
+ if err != nil {
+ return dbplugin.InitializeResponse{}, fmt.Errorf("unable to load cert: %w", err)
+ }
+ tlsConfig.Certificates = []tls.Certificate{cert}
+ p.TLSConfig = tlsConfig
+ useTLS = true
+ }
+
+ if !useTLS {
+ // set to nil to flag that this connection does not use a custom TLS config
+ p.TLSConfig = nil
+ }
+
newConf, err := p.SQLConnectionProducer.Init(ctx, req.Config, req.VerifyConnection)
if err != nil {
return dbplugin.InitializeResponse{}, err
diff --git a/plugins/database/postgresql/postgresql_test.go b/plugins/database/postgresql/postgresql_test.go
index 90184e10a3..ba150870c7 100644
--- a/plugins/database/postgresql/postgresql_test.go
+++ b/plugins/database/postgresql/postgresql_test.go
@@ -12,19 +12,20 @@ import (
"testing"
"time"
+ "github.com/hashicorp/vault/helper/testhelpers/certhelpers"
"github.com/hashicorp/vault/helper/testhelpers/postgresql"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing"
"github.com/hashicorp/vault/sdk/database/helper/connutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
- "github.com/hashicorp/vault/sdk/helper/docker"
+ "github.com/hashicorp/vault/sdk/helper/pluginutil"
"github.com/hashicorp/vault/sdk/helper/template"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func getPostgreSQL(t *testing.T, options map[string]interface{}) (*PostgreSQL, func()) {
- cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgresql.PrepareTestContainer(t)
connectionDetails := map[string]interface{}{
"connection_url": connURL,
@@ -58,6 +59,463 @@ func TestPostgreSQL_Initialize(t *testing.T) {
}
}
+// TestPostgreSQL_InitializeMultiHost tests the functionality of Postgres's
+// multi-host connection strings.
+func TestPostgreSQL_InitializeMultiHost(t *testing.T) {
+ cleanup, connURL := postgresql.PrepareTestContainerMultiHost(t)
+ defer cleanup()
+
+ connectionDetails := map[string]interface{}{
+ "connection_url": connURL,
+ "max_open_connections": 5,
+ }
+
+ req := dbplugin.InitializeRequest{
+ Config: connectionDetails,
+ VerifyConnection: true,
+ }
+
+ db := new()
+ dbtesting.AssertInitialize(t, db, req)
+
+ if !db.Initialized {
+ t.Fatal("Database should be initialized")
+ }
+
+ if err := db.Close(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+}
+
+// TestPostgreSQL_InitializeSSLInlineFeatureFlag tests that the VAULT_PLUGIN_USE_POSTGRES_SSLINLINE
+// flag guards against unwanted usage of the deprecated SSL client authentication path.
+// TODO: remove this when we remove the underlying feature in a future SDK version
+func TestPostgreSQL_InitializeSSLInlineFeatureFlag(t *testing.T) {
+ // set the flag to true so we can call PrepareTestContainerWithSSL
+ // which does a validation check on the connection
+ t.Setenv(pluginutil.PluginUsePostgresSSLInline, "true")
+
+ // Create certificates for postgres authentication
+ caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign())
+ clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert))
+ cleanup, connURL := postgresql.PrepareTestContainerWithSSL(t, "verify-ca", caCert, clientCert, false)
+ t.Cleanup(cleanup)
+
+ type testCase struct {
+ env string
+ wantErr bool
+ expectedError string
+ }
+
+ tests := map[string]testCase{
+ "feature flag is true": {
+ env: "true",
+ wantErr: false,
+ expectedError: "",
+ },
+ "feature flag is unset or empty": {
+ env: "",
+ wantErr: true,
+ // this error is expected because the env var unset means we are
+ // using pgx's native connection string parsing which does not
+ // support inlining of the certificate material in the sslrootcert,
+ // sslcert, and sslkey fields
+ expectedError: "error verifying connection",
+ },
+ "feature flag is false": {
+ env: "false",
+ wantErr: true,
+ expectedError: "failed to open postgres connection with deprecated funtion",
+ },
+ "feature flag is invalid": {
+ env: "foo",
+ wantErr: true,
+ expectedError: "failed to open postgres connection with deprecated funtion",
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ // update the env var with the value we are testing
+ t.Setenv(pluginutil.PluginUsePostgresSSLInline, test.env)
+
+ connectionDetails := map[string]interface{}{
+ "connection_url": connURL,
+ "max_open_connections": 5,
+ }
+
+ req := dbplugin.InitializeRequest{
+ Config: connectionDetails,
+ VerifyConnection: true,
+ }
+
+ db := new()
+ _, err := dbtesting.VerifyInitialize(t, db, req)
+ if test.wantErr && err == nil {
+ t.Fatal("expected error, got nil")
+ } else if test.wantErr && !strings.Contains(err.Error(), test.expectedError) {
+ t.Fatalf("got: %s, want: %s", err.Error(), test.expectedError)
+ }
+
+ if !test.wantErr && !db.Initialized {
+ t.Fatal("Database should be initialized")
+ }
+
+ if err := db.Close(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ // unset for the next test case
+ os.Unsetenv(pluginutil.PluginUsePostgresSSLInline)
+ })
+ }
+}
+
+// TestPostgreSQL_InitializeSSLInline tests that we can successfully authenticate
+// with a postgres server via ssl with a URL connection string or DSN (key/value)
+// for each ssl mode.
+// TODO: remove this when we remove the underlying feature in a future SDK version
+func TestPostgreSQL_InitializeSSLInline(t *testing.T) {
+ // required to enable the sslinline custom parsing
+ t.Setenv(pluginutil.PluginUsePostgresSSLInline, "true")
+
+ type testCase struct {
+ sslMode string
+ useDSN bool
+ useFallback bool
+ wantErr bool
+ expectedError string
+ }
+
+ tests := map[string]testCase{
+ "disable sslmode": {
+ sslMode: "disable",
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode": {
+ sslMode: "allow",
+ wantErr: false,
+ },
+ "prefer sslmode": {
+ sslMode: "prefer",
+ wantErr: false,
+ },
+ "require sslmode": {
+ sslMode: "require",
+ wantErr: false,
+ },
+ "verify-ca sslmode": {
+ sslMode: "verify-ca",
+ wantErr: false,
+ },
+ "disable sslmode with DSN": {
+ sslMode: "disable",
+ useDSN: true,
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode with DSN": {
+ sslMode: "allow",
+ useDSN: true,
+ wantErr: false,
+ },
+ "prefer sslmode with DSN": {
+ sslMode: "prefer",
+ useDSN: true,
+ wantErr: false,
+ },
+ "require sslmode with DSN": {
+ sslMode: "require",
+ useDSN: true,
+ wantErr: false,
+ },
+ "verify-ca sslmode with DSN": {
+ sslMode: "verify-ca",
+ useDSN: true,
+ wantErr: false,
+ },
+ "disable sslmode with fallback": {
+ sslMode: "disable",
+ useFallback: true,
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode with fallback": {
+ sslMode: "allow",
+ useFallback: true,
+ },
+ "prefer sslmode with fallback": {
+ sslMode: "prefer",
+ useFallback: true,
+ },
+ "require sslmode with fallback": {
+ sslMode: "require",
+ useFallback: true,
+ },
+ "verify-ca sslmode with fallback": {
+ sslMode: "verify-ca",
+ useFallback: true,
+ },
+ "disable sslmode with DSN with fallback": {
+ sslMode: "disable",
+ useDSN: true,
+ useFallback: true,
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode with DSN with fallback": {
+ sslMode: "allow",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ "prefer sslmode with DSN with fallback": {
+ sslMode: "prefer",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ "require sslmode with DSN with fallback": {
+ sslMode: "require",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ "verify-ca sslmode with DSN with fallback": {
+ sslMode: "verify-ca",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ }
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ t.Parallel()
+
+ // Create certificates for postgres authentication
+ caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign())
+ clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert))
+ cleanup, connURL := postgresql.PrepareTestContainerWithSSL(t, test.sslMode, caCert, clientCert, test.useFallback)
+ t.Cleanup(cleanup)
+
+ if test.useDSN {
+ var err error
+ connURL, err = dbutil.ParseURL(connURL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ connectionDetails := map[string]interface{}{
+ "connection_url": connURL,
+ "max_open_connections": 5,
+ }
+
+ req := dbplugin.InitializeRequest{
+ Config: connectionDetails,
+ VerifyConnection: true,
+ }
+
+ db := new()
+ _, err := dbtesting.VerifyInitialize(t, db, req)
+ if test.wantErr && err == nil {
+ t.Fatal("expected error, got nil")
+ } else if test.wantErr && !strings.Contains(err.Error(), test.expectedError) {
+ t.Fatalf("got: %s, want: %s", err.Error(), test.expectedError)
+ }
+
+ if !test.wantErr && !db.Initialized {
+ t.Fatal("Database should be initialized")
+ }
+
+ if err := db.Close(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ })
+ }
+}
+
+// TestPostgreSQL_InitializeSSL tests that we can successfully authenticate
+// with a postgres server via ssl with a URL connection string or DSN (key/value)
+// for each ssl mode.
+func TestPostgreSQL_InitializeSSL(t *testing.T) {
+ type testCase struct {
+ sslMode string
+ useDSN bool
+ useFallback bool
+ wantErr bool
+ expectedError string
+ }
+
+ tests := map[string]testCase{
+ "disable sslmode": {
+ sslMode: "disable",
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode": {
+ sslMode: "allow",
+ wantErr: false,
+ },
+ "prefer sslmode": {
+ sslMode: "prefer",
+ wantErr: false,
+ },
+ "require sslmode": {
+ sslMode: "require",
+ wantErr: false,
+ },
+ "verify-ca sslmode": {
+ sslMode: "verify-ca",
+ wantErr: false,
+ },
+ "verify-full sslmode": {
+ sslMode: "verify-full",
+ wantErr: false,
+ },
+ "disable sslmode with DSN": {
+ sslMode: "disable",
+ useDSN: true,
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode with DSN": {
+ sslMode: "allow",
+ useDSN: true,
+ wantErr: false,
+ },
+ "prefer sslmode with DSN": {
+ sslMode: "prefer",
+ useDSN: true,
+ wantErr: false,
+ },
+ "require sslmode with DSN": {
+ sslMode: "require",
+ useDSN: true,
+ wantErr: false,
+ },
+ "verify-ca sslmode with DSN": {
+ sslMode: "verify-ca",
+ useDSN: true,
+ wantErr: false,
+ },
+ "verify-full sslmode with DSN": {
+ sslMode: "verify-full",
+ useDSN: true,
+ wantErr: false,
+ },
+ "disable sslmode with fallback": {
+ sslMode: "disable",
+ useFallback: true,
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode with fallback": {
+ sslMode: "allow",
+ useFallback: true,
+ },
+ "prefer sslmode with fallback": {
+ sslMode: "prefer",
+ useFallback: true,
+ },
+ "require sslmode with fallback": {
+ sslMode: "require",
+ useFallback: true,
+ },
+ "verify-ca sslmode with fallback": {
+ sslMode: "verify-ca",
+ useFallback: true,
+ },
+ "verify-full sslmode with fallback": {
+ sslMode: "verify-full",
+ useFallback: true,
+ },
+ "disable sslmode with DSN with fallback": {
+ sslMode: "disable",
+ useDSN: true,
+ useFallback: true,
+ wantErr: true,
+ expectedError: "error verifying connection",
+ },
+ "allow sslmode with DSN with fallback": {
+ sslMode: "allow",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ "prefer sslmode with DSN with fallback": {
+ sslMode: "prefer",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ "require sslmode with DSN with fallback": {
+ sslMode: "require",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ "verify-ca sslmode with DSN with fallback": {
+ sslMode: "verify-ca",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ "verify-full sslmode with DSN with fallback": {
+ sslMode: "verify-full",
+ useDSN: true,
+ useFallback: true,
+ wantErr: false,
+ },
+ }
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ t.Parallel()
+
+ // Create certificates for postgres authentication
+ caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign())
+ clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert))
+ cleanup, connURL := postgresql.PrepareTestContainerWithSSL(t, test.sslMode, caCert, clientCert, test.useFallback)
+ t.Cleanup(cleanup)
+
+ if test.useDSN {
+ var err error
+ connURL, err = dbutil.ParseURL(connURL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ connectionDetails := map[string]interface{}{
+ "connection_url": connURL,
+ "max_open_connections": 5,
+ "tls_certificate": string(clientCert.CombinedPEM()),
+ "private_key": string(clientCert.PrivateKeyPEM()),
+ "tls_ca": string(caCert.CombinedPEM()),
+ }
+
+ req := dbplugin.InitializeRequest{
+ Config: connectionDetails,
+ VerifyConnection: true,
+ }
+
+ db := new()
+ _, err := dbtesting.VerifyInitialize(t, db, req)
+ if test.wantErr && err == nil {
+ t.Fatal("expected error, got nil")
+ } else if test.wantErr && !strings.Contains(err.Error(), test.expectedError) {
+ t.Fatalf("got: %s, want: %s", err.Error(), test.expectedError)
+ }
+
+ if !test.wantErr && !db.Initialized {
+ t.Fatal("Database should be initialized")
+ }
+
+ if err := db.Close(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ })
+ }
+}
+
func TestPostgreSQL_InitializeWithStringVals(t *testing.T) {
db, cleanup := getPostgreSQL(t, map[string]interface{}{
"max_open_connections": "5",
@@ -70,7 +528,7 @@ func TestPostgreSQL_InitializeWithStringVals(t *testing.T) {
}
func TestPostgreSQL_Initialize_ConnURLWithDSNFormat(t *testing.T) {
- cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgresql.PrepareTestContainer(t)
defer cleanup()
dsnConnURL, err := dbutil.ParseURL(connURL)
@@ -185,7 +643,7 @@ func TestPostgreSQL_Initialize_CloudGCP(t *testing.T) {
// TestPostgreSQL_PasswordAuthentication tests that the default "password_authentication" is "none", and that
// an error is returned if an invalid "password_authentication" is provided.
func TestPostgreSQL_PasswordAuthentication(t *testing.T) {
- cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgresql.PrepareTestContainer(t)
defer cleanup()
dsnConnURL, err := dbutil.ParseURL(connURL)
@@ -227,7 +685,7 @@ func TestPostgreSQL_PasswordAuthentication(t *testing.T) {
// TestPostgreSQL_PasswordAuthentication_SCRAMSHA256 tests that password_authentication works when set to scram-sha-256.
// When sending an encrypted password, the raw password should still successfully authenticate the user.
func TestPostgreSQL_PasswordAuthentication_SCRAMSHA256(t *testing.T) {
- cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgresql.PrepareTestContainer(t)
defer cleanup()
dsnConnURL, err := dbutil.ParseURL(connURL)
@@ -1092,7 +1550,7 @@ func TestUsernameGeneration(t *testing.T) {
}
func TestNewUser_CustomUsername(t *testing.T) {
- cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster")
+ cleanup, connURL := postgresql.PrepareTestContainer(t)
defer cleanup()
type testCase struct {
@@ -1268,139 +1726,6 @@ func TestNewUser_CloudGCP(t *testing.T) {
}
}
-// This is a long-running integration test which tests the functionality of Postgres's multi-host
-// connection strings. It uses two Postgres containers preconfigured with Replication Manager
-// provided by Bitnami. This test currently does not run in CI and must be run manually. This is
-// due to the test length, as it requires multiple sleep calls to ensure cluster setup and
-// primary node failover occurs before the test steps continue.
-//
-// To run the test, set the environment variable POSTGRES_MULTIHOST_NET to the value of
-// a docker network you've preconfigured, e.g.
-// 'docker network create -d bridge postgres-repmgr'
-// 'export POSTGRES_MULTIHOST_NET=postgres-repmgr'
-func TestPostgreSQL_Repmgr(t *testing.T) {
- _, exists := os.LookupEnv("POSTGRES_MULTIHOST_NET")
- if !exists {
- t.Skipf("POSTGRES_MULTIHOST_NET not set, skipping test")
- }
-
- // Run two postgres-repmgr containers in a replication cluster
- db0, runner0, url0, container0 := testPostgreSQL_Repmgr_Container(t, "psql-repl-node-0")
- _, _, url1, _ := testPostgreSQL_Repmgr_Container(t, "psql-repl-node-1")
-
- ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second)
- defer cancel()
-
- time.Sleep(10 * time.Second)
-
- // Write a read role to the cluster
- _, err := db0.NewUser(ctx, dbplugin.NewUserRequest{
- Statements: dbplugin.Statements{
- Commands: []string{
- `CREATE ROLE "ro" NOINHERIT;
- GRANT SELECT ON ALL TABLES IN SCHEMA public TO "ro";`,
- },
- },
- })
- if err != nil {
- t.Fatalf("no error expected, got: %s", err)
- }
-
- // Open a connection to both databases using the multihost connection string
- connectionDetails := map[string]interface{}{
- "connection_url": fmt.Sprintf("postgresql://{{username}}:{{password}}@%s,%s/postgres?target_session_attrs=read-write", getHost(url0), getHost(url1)),
- "username": "postgres",
- "password": "secret",
- }
- req := dbplugin.InitializeRequest{
- Config: connectionDetails,
- VerifyConnection: true,
- }
-
- db := new()
- dbtesting.AssertInitialize(t, db, req)
- if !db.Initialized {
- t.Fatal("Database should be initialized")
- }
- defer db.Close()
-
- // Add a user to the cluster, then stop the primary container
- if err = testPostgreSQL_Repmgr_AddUser(ctx, db); err != nil {
- t.Fatalf("no error expected, got: %s", err)
- }
- postgresql.StopContainer(t, ctx, runner0, container0)
-
- // Try adding a new user immediately - expect failure as the database
- // cluster is still switching primaries
- err = testPostgreSQL_Repmgr_AddUser(ctx, db)
- if !strings.HasSuffix(err.Error(), "ValidateConnect failed (read only connection)") {
- t.Fatalf("expected error was not received, got: %s", err)
- }
-
- time.Sleep(20 * time.Second)
-
- // Try adding a new user again which should succeed after the sleep
- // as the primary failover should have finished. Then, restart
- // the first container which should become a secondary DB.
- if err = testPostgreSQL_Repmgr_AddUser(ctx, db); err != nil {
- t.Fatalf("no error expected, got: %s", err)
- }
- postgresql.RestartContainer(t, ctx, runner0, container0)
-
- time.Sleep(10 * time.Second)
-
- // A final new user to add, which should succeed after the secondary joins.
- if err = testPostgreSQL_Repmgr_AddUser(ctx, db); err != nil {
- t.Fatalf("no error expected, got: %s", err)
- }
-
- if err := db.Close(); err != nil {
- t.Fatalf("err: %s", err)
- }
-}
-
-func testPostgreSQL_Repmgr_Container(t *testing.T, name string) (*PostgreSQL, *docker.Runner, string, string) {
- envVars := []string{
- "REPMGR_NODE_NAME=" + name,
- "REPMGR_NODE_NETWORK_NAME=" + name,
- }
-
- runner, cleanup, connURL, containerID := postgresql.PrepareTestContainerRepmgr(t, name, "13.4.0", envVars)
- t.Cleanup(cleanup)
-
- connectionDetails := map[string]interface{}{
- "connection_url": connURL,
- }
- req := dbplugin.InitializeRequest{
- Config: connectionDetails,
- VerifyConnection: true,
- }
- db := new()
- dbtesting.AssertInitialize(t, db, req)
- if !db.Initialized {
- t.Fatal("Database should be initialized")
- }
-
- if err := db.Close(); err != nil {
- t.Fatalf("err: %s", err)
- }
-
- return db, runner, connURL, containerID
-}
-
-func testPostgreSQL_Repmgr_AddUser(ctx context.Context, db *PostgreSQL) error {
- _, err := db.NewUser(ctx, dbplugin.NewUserRequest{
- Statements: dbplugin.Statements{
- Commands: []string{
- `CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' INHERIT;
- GRANT ro TO "{{name}}";`,
- },
- },
- })
-
- return err
-}
-
func getHost(url string) string {
splitCreds := strings.Split(url, "@")[1]
diff --git a/scripts/gen_openapi.sh b/scripts/gen_openapi.sh
index ef2acca0a0..b0c3bba1ee 100755
--- a/scripts/gen_openapi.sh
+++ b/scripts/gen_openapi.sh
@@ -54,7 +54,6 @@ vault auth enable "alicloud"
vault auth enable "approle"
vault auth enable "aws"
vault auth enable "azure"
-vault auth enable "centrify"
vault auth enable "cert"
vault auth enable "cf"
vault auth enable "gcp"
diff --git a/sdk/database/dbplugin/database.pb.go b/sdk/database/dbplugin/database.pb.go
index 978d35e25f..825813ec93 100644
--- a/sdk/database/dbplugin/database.pb.go
+++ b/sdk/database/dbplugin/database.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/database/dbplugin/database.proto
@@ -1180,7 +1180,7 @@ func file_sdk_database_dbplugin_database_proto_rawDescGZIP() []byte {
}
var file_sdk_database_dbplugin_database_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
-var file_sdk_database_dbplugin_database_proto_goTypes = []interface{}{
+var file_sdk_database_dbplugin_database_proto_goTypes = []any{
(*InitializeRequest)(nil), // 0: dbplugin.InitializeRequest
(*InitRequest)(nil), // 1: dbplugin.InitRequest
(*CreateUserRequest)(nil), // 2: dbplugin.CreateUserRequest
@@ -1242,7 +1242,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_database_dbplugin_database_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*InitializeRequest); i {
case 0:
return &v.state
@@ -1254,7 +1254,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*InitRequest); i {
case 0:
return &v.state
@@ -1266,7 +1266,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*CreateUserRequest); i {
case 0:
return &v.state
@@ -1278,7 +1278,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*RenewUserRequest); i {
case 0:
return &v.state
@@ -1290,7 +1290,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*RevokeUserRequest); i {
case 0:
return &v.state
@@ -1302,7 +1302,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*RotateRootCredentialsRequest); i {
case 0:
return &v.state
@@ -1314,7 +1314,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*Statements); i {
case 0:
return &v.state
@@ -1326,7 +1326,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*UsernameConfig); i {
case 0:
return &v.state
@@ -1338,7 +1338,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[8].Exporter = func(v any, i int) any {
switch v := v.(*InitResponse); i {
case 0:
return &v.state
@@ -1350,7 +1350,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[9].Exporter = func(v any, i int) any {
switch v := v.(*CreateUserResponse); i {
case 0:
return &v.state
@@ -1362,7 +1362,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[10].Exporter = func(v any, i int) any {
switch v := v.(*TypeResponse); i {
case 0:
return &v.state
@@ -1374,7 +1374,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[11].Exporter = func(v any, i int) any {
switch v := v.(*RotateRootCredentialsResponse); i {
case 0:
return &v.state
@@ -1386,7 +1386,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[12].Exporter = func(v any, i int) any {
switch v := v.(*Empty); i {
case 0:
return &v.state
@@ -1398,7 +1398,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[13].Exporter = func(v any, i int) any {
switch v := v.(*GenerateCredentialsResponse); i {
case 0:
return &v.state
@@ -1410,7 +1410,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[14].Exporter = func(v any, i int) any {
switch v := v.(*StaticUserConfig); i {
case 0:
return &v.state
@@ -1422,7 +1422,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[15].Exporter = func(v any, i int) any {
switch v := v.(*SetCredentialsRequest); i {
case 0:
return &v.state
@@ -1434,7 +1434,7 @@ func file_sdk_database_dbplugin_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_database_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_database_proto_msgTypes[16].Exporter = func(v any, i int) any {
switch v := v.(*SetCredentialsResponse); i {
case 0:
return &v.state
diff --git a/sdk/database/dbplugin/database_grpc.pb.go b/sdk/database/dbplugin/database_grpc.pb.go
index f62de0236b..57a0c059ad 100644
--- a/sdk/database/dbplugin/database_grpc.pb.go
+++ b/sdk/database/dbplugin/database_grpc.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
-// - protoc-gen-go-grpc v1.3.0
+// - protoc-gen-go-grpc v1.4.0
// - protoc (unknown)
// source: sdk/database/dbplugin/database.proto
@@ -18,8 +18,8 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
-// Requires gRPC-Go v1.32.0 or later.
-const _ = grpc.SupportPackageIsVersion7
+// Requires gRPC-Go v1.62.0 or later.
+const _ = grpc.SupportPackageIsVersion8
const (
Database_Type_FullMethodName = "/dbplugin.Database/Type"
@@ -60,8 +60,9 @@ func NewDatabaseClient(cc grpc.ClientConnInterface) DatabaseClient {
}
func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TypeResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TypeResponse)
- err := c.cc.Invoke(ctx, Database_Type_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_Type_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -69,8 +70,9 @@ func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallO
}
func (c *databaseClient) CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreateUserResponse)
- err := c.cc.Invoke(ctx, Database_CreateUser_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_CreateUser_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -78,8 +80,9 @@ func (c *databaseClient) CreateUser(ctx context.Context, in *CreateUserRequest,
}
func (c *databaseClient) RenewUser(ctx context.Context, in *RenewUserRequest, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Database_RenewUser_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_RenewUser_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -87,8 +90,9 @@ func (c *databaseClient) RenewUser(ctx context.Context, in *RenewUserRequest, op
}
func (c *databaseClient) RevokeUser(ctx context.Context, in *RevokeUserRequest, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Database_RevokeUser_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_RevokeUser_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -96,8 +100,9 @@ func (c *databaseClient) RevokeUser(ctx context.Context, in *RevokeUserRequest,
}
func (c *databaseClient) RotateRootCredentials(ctx context.Context, in *RotateRootCredentialsRequest, opts ...grpc.CallOption) (*RotateRootCredentialsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RotateRootCredentialsResponse)
- err := c.cc.Invoke(ctx, Database_RotateRootCredentials_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_RotateRootCredentials_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -105,8 +110,9 @@ func (c *databaseClient) RotateRootCredentials(ctx context.Context, in *RotateRo
}
func (c *databaseClient) Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*InitResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(InitResponse)
- err := c.cc.Invoke(ctx, Database_Init_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_Init_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -114,8 +120,9 @@ func (c *databaseClient) Init(ctx context.Context, in *InitRequest, opts ...grpc
}
func (c *databaseClient) Close(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Database_Close_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_Close_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -123,8 +130,9 @@ func (c *databaseClient) Close(ctx context.Context, in *Empty, opts ...grpc.Call
}
func (c *databaseClient) SetCredentials(ctx context.Context, in *SetCredentialsRequest, opts ...grpc.CallOption) (*SetCredentialsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SetCredentialsResponse)
- err := c.cc.Invoke(ctx, Database_SetCredentials_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_SetCredentials_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -132,8 +140,9 @@ func (c *databaseClient) SetCredentials(ctx context.Context, in *SetCredentialsR
}
func (c *databaseClient) GenerateCredentials(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GenerateCredentialsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GenerateCredentialsResponse)
- err := c.cc.Invoke(ctx, Database_GenerateCredentials_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_GenerateCredentials_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -142,8 +151,9 @@ func (c *databaseClient) GenerateCredentials(ctx context.Context, in *Empty, opt
// Deprecated: Do not use.
func (c *databaseClient) Initialize(ctx context.Context, in *InitializeRequest, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Database_Initialize_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_Initialize_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
diff --git a/sdk/database/dbplugin/v5/proto/database.pb.go b/sdk/database/dbplugin/v5/proto/database.pb.go
index fd76db7cef..745bd85334 100644
--- a/sdk/database/dbplugin/v5/proto/database.pb.go
+++ b/sdk/database/dbplugin/v5/proto/database.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/database/dbplugin/v5/proto/database.proto
@@ -1012,7 +1012,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP() []byte {
}
var file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
-var file_sdk_database_dbplugin_v5_proto_database_proto_goTypes = []interface{}{
+var file_sdk_database_dbplugin_v5_proto_database_proto_goTypes = []any{
(*InitializeRequest)(nil), // 0: dbplugin.v5.InitializeRequest
(*InitializeResponse)(nil), // 1: dbplugin.v5.InitializeResponse
(*NewUserRequest)(nil), // 2: dbplugin.v5.NewUserRequest
@@ -1071,7 +1071,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*InitializeRequest); i {
case 0:
return &v.state
@@ -1083,7 +1083,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*InitializeResponse); i {
case 0:
return &v.state
@@ -1095,7 +1095,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*NewUserRequest); i {
case 0:
return &v.state
@@ -1107,7 +1107,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*UsernameConfig); i {
case 0:
return &v.state
@@ -1119,7 +1119,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*NewUserResponse); i {
case 0:
return &v.state
@@ -1131,7 +1131,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*UpdateUserRequest); i {
case 0:
return &v.state
@@ -1143,7 +1143,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*ChangePassword); i {
case 0:
return &v.state
@@ -1155,7 +1155,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*ChangePublicKey); i {
case 0:
return &v.state
@@ -1167,7 +1167,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8].Exporter = func(v any, i int) any {
switch v := v.(*ChangeExpiration); i {
case 0:
return &v.state
@@ -1179,7 +1179,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9].Exporter = func(v any, i int) any {
switch v := v.(*UpdateUserResponse); i {
case 0:
return &v.state
@@ -1191,7 +1191,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10].Exporter = func(v any, i int) any {
switch v := v.(*DeleteUserRequest); i {
case 0:
return &v.state
@@ -1203,7 +1203,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11].Exporter = func(v any, i int) any {
switch v := v.(*DeleteUserResponse); i {
case 0:
return &v.state
@@ -1215,7 +1215,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12].Exporter = func(v any, i int) any {
switch v := v.(*TypeResponse); i {
case 0:
return &v.state
@@ -1227,7 +1227,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13].Exporter = func(v any, i int) any {
switch v := v.(*Statements); i {
case 0:
return &v.state
@@ -1239,7 +1239,7 @@ func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
return nil
}
}
- file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[14].Exporter = func(v any, i int) any {
switch v := v.(*Empty); i {
case 0:
return &v.state
diff --git a/sdk/database/dbplugin/v5/proto/database_grpc.pb.go b/sdk/database/dbplugin/v5/proto/database_grpc.pb.go
index 49610c3b04..28c8d77523 100644
--- a/sdk/database/dbplugin/v5/proto/database_grpc.pb.go
+++ b/sdk/database/dbplugin/v5/proto/database_grpc.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
-// - protoc-gen-go-grpc v1.3.0
+// - protoc-gen-go-grpc v1.4.0
// - protoc (unknown)
// source: sdk/database/dbplugin/v5/proto/database.proto
@@ -18,8 +18,8 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
-// Requires gRPC-Go v1.32.0 or later.
-const _ = grpc.SupportPackageIsVersion7
+// Requires gRPC-Go v1.62.0 or later.
+const _ = grpc.SupportPackageIsVersion8
const (
Database_Initialize_FullMethodName = "/dbplugin.v5.Database/Initialize"
@@ -51,8 +51,9 @@ func NewDatabaseClient(cc grpc.ClientConnInterface) DatabaseClient {
}
func (c *databaseClient) Initialize(ctx context.Context, in *InitializeRequest, opts ...grpc.CallOption) (*InitializeResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(InitializeResponse)
- err := c.cc.Invoke(ctx, Database_Initialize_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_Initialize_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -60,8 +61,9 @@ func (c *databaseClient) Initialize(ctx context.Context, in *InitializeRequest,
}
func (c *databaseClient) NewUser(ctx context.Context, in *NewUserRequest, opts ...grpc.CallOption) (*NewUserResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(NewUserResponse)
- err := c.cc.Invoke(ctx, Database_NewUser_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_NewUser_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -69,8 +71,9 @@ func (c *databaseClient) NewUser(ctx context.Context, in *NewUserRequest, opts .
}
func (c *databaseClient) UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*UpdateUserResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UpdateUserResponse)
- err := c.cc.Invoke(ctx, Database_UpdateUser_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_UpdateUser_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -78,8 +81,9 @@ func (c *databaseClient) UpdateUser(ctx context.Context, in *UpdateUserRequest,
}
func (c *databaseClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*DeleteUserResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeleteUserResponse)
- err := c.cc.Invoke(ctx, Database_DeleteUser_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_DeleteUser_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -87,8 +91,9 @@ func (c *databaseClient) DeleteUser(ctx context.Context, in *DeleteUserRequest,
}
func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TypeResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TypeResponse)
- err := c.cc.Invoke(ctx, Database_Type_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_Type_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -96,8 +101,9 @@ func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallO
}
func (c *databaseClient) Close(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Database_Close_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Database_Close_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
diff --git a/sdk/database/helper/connutil/cloudsql.go b/sdk/database/helper/connutil/cloudsql.go
index 5330c1cc22..f6cbba1d24 100644
--- a/sdk/database/helper/connutil/cloudsql.go
+++ b/sdk/database/helper/connutil/cloudsql.go
@@ -10,10 +10,6 @@ import (
"cloud.google.com/go/cloudsqlconn/postgres/pgxv4"
)
-var configurableAuthTypes = []string{
- AuthTypeGCPIAM,
-}
-
func (c *SQLConnectionProducer) getCloudSQLDriverType() (string, error) {
var driverType string
// using switch case for future extensibility
@@ -27,13 +23,13 @@ func (c *SQLConnectionProducer) getCloudSQLDriverType() (string, error) {
return driverType, nil
}
-func (c *SQLConnectionProducer) registerDrivers(driverName string, credentials string) (func() error, error) {
+func (c *SQLConnectionProducer) registerDrivers(driverName string, credentials string, usePrivateIP bool) (func() error, error) {
typ, err := c.getCloudSQLDriverType()
if err != nil {
return nil, err
}
- opts, err := GetCloudSQLAuthOptions(credentials)
+ opts, err := GetCloudSQLAuthOptions(credentials, usePrivateIP)
if err != nil {
return nil, err
}
@@ -49,24 +45,16 @@ func (c *SQLConnectionProducer) registerDrivers(driverName string, credentials s
// GetCloudSQLAuthOptions takes a credentials JSON and returns
// a set of GCP CloudSQL options - always WithIAMAUthN, and then the appropriate file/JSON option.
-func GetCloudSQLAuthOptions(credentials string) ([]cloudsqlconn.Option, error) {
+func GetCloudSQLAuthOptions(credentials string, usePrivateIP bool) ([]cloudsqlconn.Option, error) {
opts := []cloudsqlconn.Option{cloudsqlconn.WithIAMAuthN()}
if credentials != "" {
opts = append(opts, cloudsqlconn.WithCredentialsJSON([]byte(credentials)))
}
- return opts, nil
-}
-
-func ValidateAuthType(authType string) bool {
- var valid bool
- for _, typ := range configurableAuthTypes {
- if authType == typ {
- valid = true
- break
- }
+ if usePrivateIP {
+ opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP()))
}
- return valid
+ return opts, nil
}
diff --git a/sdk/database/helper/connutil/postgres.go b/sdk/database/helper/connutil/postgres.go
new file mode 100644
index 0000000000..f8ad876c5a
--- /dev/null
+++ b/sdk/database/helper/connutil/postgres.go
@@ -0,0 +1,466 @@
+// Copyright (c) 2019-2021 Jack Christensen
+
+// MIT License
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// Copied from https://github.com/jackc/pgconn/blob/1860f4e57204614f40d05a5c76a43e8d80fde9da/config.go
+
+package connutil
+
+import (
+ "context"
+ "crypto/tls"
+ "crypto/x509"
+ "database/sql"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "math"
+ "net"
+ "net/url"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/hashicorp/vault/sdk/helper/pluginutil"
+ "github.com/jackc/pgconn"
+ "github.com/jackc/pgx/v4"
+ "github.com/jackc/pgx/v4/stdlib"
+)
+
+// openPostgres parses the connection string and opens a connection to the database.
+//
+// If sslinline is set, strips the connection string of all ssl settings and
+// creates a TLS config based on the settings provided, then uses the
+// RegisterConnConfig function to create a new connection. This is necessary
+// because the pgx driver does not support the sslinline parameter and instead
+// expects to source ssl material from the file system.
+//
+// Deprecated: openPostgres will be removed in a future version of the Vault SDK.
+func openPostgres(driverName, connString string) (*sql.DB, error) {
+ if ok, _ := strconv.ParseBool(os.Getenv(pluginutil.PluginUsePostgresSSLInline)); !ok {
+ return nil, fmt.Errorf("failed to open postgres connection with deprecated funtion, set feature flag to enable")
+ }
+
+ var options pgconn.ParseConfigOptions
+
+ settings := make(map[string]string)
+ if connString != "" {
+ var err error
+ // connString may be a database URL or a DSN
+ if strings.HasPrefix(connString, "postgres://") || strings.HasPrefix(connString, "postgresql://") {
+ settings, err = parsePostgresURLSettings(connString)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse as URL: %w", err)
+ }
+ } else {
+ settings, err = parsePostgresDSNSettings(connString)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse as DSN: %w", err)
+ }
+ }
+ }
+
+ // get the inline flag
+ sslInline := settings["sslinline"] == "true"
+
+ // if sslinline is not set, open a regular connection
+ if !sslInline {
+ return sql.Open(driverName, connString)
+ }
+
+ // generate a new DSN without the ssl settings
+ newConnStr := []string{"sslmode=disable"}
+ for k, v := range settings {
+ switch k {
+ case "sslinline", "sslcert", "sslkey", "sslrootcert", "sslmode":
+ continue
+ }
+
+ newConnStr = append(newConnStr, fmt.Sprintf("%s='%s'", k, v))
+ }
+
+ // parse the updated config
+ config, err := pgx.ParseConfig(strings.Join(newConnStr, " "))
+ if err != nil {
+ return nil, err
+ }
+
+ // create a TLS config
+ fallbacks := []*pgconn.FallbackConfig{}
+
+ hosts := strings.Split(settings["host"], ",")
+ ports := strings.Split(settings["port"], ",")
+
+ for i, host := range hosts {
+ var portStr string
+ if i < len(ports) {
+ portStr = ports[i]
+ } else {
+ portStr = ports[0]
+ }
+
+ port, err := parsePort(portStr)
+ if err != nil {
+ return nil, fmt.Errorf("invalid port: %w", err)
+ }
+
+ var tlsConfigs []*tls.Config
+
+ // Ignore TLS settings if Unix domain socket like libpq
+ if network, _ := pgconn.NetworkAddress(host, port); network == "unix" {
+ tlsConfigs = append(tlsConfigs, nil)
+ } else {
+ var err error
+ tlsConfigs, err = configPostgresTLS(settings, host, options)
+ if err != nil {
+ return nil, fmt.Errorf("failed to configure TLS: %w", err)
+ }
+ }
+
+ for _, tlsConfig := range tlsConfigs {
+ fallbacks = append(fallbacks, &pgconn.FallbackConfig{
+ Host: host,
+ Port: port,
+ TLSConfig: tlsConfig,
+ })
+ }
+ }
+
+ config.Host = fallbacks[0].Host
+ config.Port = fallbacks[0].Port
+ config.TLSConfig = fallbacks[0].TLSConfig
+ config.Fallbacks = fallbacks[1:]
+
+ return sql.Open(driverName, stdlib.RegisterConnConfig(config))
+}
+
+// configPostgresTLS uses libpq's TLS parameters to construct []*tls.Config. It is
+// necessary to allow returning multiple TLS configs as sslmode "allow" and
+// "prefer" allow fallback.
+//
+// Copied from https://github.com/jackc/pgconn/blob/1860f4e57204614f40d05a5c76a43e8d80fde9da/config.go
+// and modified to read ssl material by value instead of file location.
+func configPostgresTLS(settings map[string]string, thisHost string, parseConfigOptions pgconn.ParseConfigOptions) ([]*tls.Config, error) {
+ host := thisHost
+ sslmode := settings["sslmode"]
+ sslrootcert := settings["sslrootcert"]
+ sslcert := settings["sslcert"]
+ sslkey := settings["sslkey"]
+ sslpassword := settings["sslpassword"]
+ sslsni := settings["sslsni"]
+
+ // Match libpq default behavior
+ if sslmode == "" {
+ sslmode = "prefer"
+ }
+ if sslsni == "" {
+ sslsni = "1"
+ }
+
+ tlsConfig := &tls.Config{}
+
+ switch sslmode {
+ case "disable":
+ return []*tls.Config{nil}, nil
+ case "allow", "prefer":
+ tlsConfig.InsecureSkipVerify = true
+ case "require":
+ // According to PostgreSQL documentation, if a root CA file exists,
+ // the behavior of sslmode=require should be the same as that of verify-ca
+ //
+ // See https://www.postgresql.org/docs/12/libpq-ssl.html
+ if sslrootcert != "" {
+ goto nextCase
+ }
+ tlsConfig.InsecureSkipVerify = true
+ break
+ nextCase:
+ fallthrough
+ case "verify-ca":
+ // Don't perform the default certificate verification because it
+ // will verify the hostname. Instead, verify the server's
+ // certificate chain ourselves in VerifyPeerCertificate and
+ // ignore the server name. This emulates libpq's verify-ca
+ // behavior.
+ //
+ // See https://github.com/golang/go/issues/21971#issuecomment-332693931
+ // and https://pkg.go.dev/crypto/tls?tab=doc#example-Config-VerifyPeerCertificate
+ // for more info.
+ tlsConfig.InsecureSkipVerify = true
+ tlsConfig.VerifyPeerCertificate = func(certificates [][]byte, _ [][]*x509.Certificate) error {
+ certs := make([]*x509.Certificate, len(certificates))
+ for i, asn1Data := range certificates {
+ cert, err := x509.ParseCertificate(asn1Data)
+ if err != nil {
+ return errors.New("failed to parse certificate from server: " + err.Error())
+ }
+ certs[i] = cert
+ }
+
+ // Leave DNSName empty to skip hostname verification.
+ opts := x509.VerifyOptions{
+ Roots: tlsConfig.RootCAs,
+ Intermediates: x509.NewCertPool(),
+ }
+ // Skip the first cert because it's the leaf. All others
+ // are intermediates.
+ for _, cert := range certs[1:] {
+ opts.Intermediates.AddCert(cert)
+ }
+ _, err := certs[0].Verify(opts)
+ return err
+ }
+ case "verify-full":
+ tlsConfig.ServerName = host
+ default:
+ return nil, errors.New("sslmode is invalid")
+ }
+
+ if sslrootcert != "" {
+ caCertPool := x509.NewCertPool()
+ if !caCertPool.AppendCertsFromPEM([]byte(sslrootcert)) {
+ return nil, errors.New("unable to add CA to cert pool")
+ }
+
+ tlsConfig.RootCAs = caCertPool
+ tlsConfig.ClientCAs = caCertPool
+ }
+
+ if (sslcert != "" && sslkey == "") || (sslcert == "" && sslkey != "") {
+ return nil, errors.New(`both "sslcert" and "sslkey" are required`)
+ }
+
+ if sslcert != "" && sslkey != "" {
+ block, _ := pem.Decode([]byte(sslkey))
+ var pemKey []byte
+ var decryptedKey []byte
+ var decryptedError error
+ // If PEM is encrypted, attempt to decrypt using pass phrase
+ if x509.IsEncryptedPEMBlock(block) {
+ // Attempt decryption with pass phrase
+ // NOTE: only supports RSA (PKCS#1)
+ if sslpassword != "" {
+ decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword))
+ }
+ // if sslpassword not provided or has decryption error when use it
+ // try to find sslpassword with callback function
+ if sslpassword == "" || decryptedError != nil {
+ if parseConfigOptions.GetSSLPassword != nil {
+ sslpassword = parseConfigOptions.GetSSLPassword(context.Background())
+ }
+ if sslpassword == "" {
+ return nil, fmt.Errorf("unable to find sslpassword")
+ }
+ }
+ decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword))
+ // Should we also provide warning for PKCS#1 needed?
+ if decryptedError != nil {
+ return nil, fmt.Errorf("unable to decrypt key: %w", decryptedError)
+ }
+
+ pemBytes := pem.Block{
+ Type: "RSA PRIVATE KEY",
+ Bytes: decryptedKey,
+ }
+ pemKey = pem.EncodeToMemory(&pemBytes)
+ } else {
+ pemKey = pem.EncodeToMemory(block)
+ }
+
+ cert, err := tls.X509KeyPair([]byte(sslcert), pemKey)
+ if err != nil {
+ return nil, fmt.Errorf("unable to load cert: %w", err)
+ }
+ tlsConfig.Certificates = []tls.Certificate{cert}
+ }
+
+ // Set Server Name Indication (SNI), if enabled by connection parameters.
+ // Per RFC 6066, do not set it if the host is a literal IP address (IPv4
+ // or IPv6).
+ if sslsni == "1" && net.ParseIP(host) == nil {
+ tlsConfig.ServerName = host
+ }
+
+ switch sslmode {
+ case "allow":
+ return []*tls.Config{nil, tlsConfig}, nil
+ case "prefer":
+ return []*tls.Config{tlsConfig, nil}, nil
+ case "require", "verify-ca", "verify-full":
+ return []*tls.Config{tlsConfig}, nil
+ default:
+ panic("BUG: bad sslmode should already have been caught")
+ }
+}
+
+func parsePort(s string) (uint16, error) {
+ port, err := strconv.ParseUint(s, 10, 16)
+ if err != nil {
+ return 0, err
+ }
+ if port < 1 || port > math.MaxUint16 {
+ return 0, errors.New("outside range")
+ }
+ return uint16(port), nil
+}
+
+var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
+
+func parsePostgresURLSettings(connString string) (map[string]string, error) {
+ settings := make(map[string]string)
+
+ url, err := url.Parse(connString)
+ if err != nil {
+ return nil, err
+ }
+
+ if url.User != nil {
+ settings["user"] = url.User.Username()
+ if password, present := url.User.Password(); present {
+ settings["password"] = password
+ }
+ }
+
+ // Handle multiple host:port's in url.Host by splitting them into host,host,host and port,port,port.
+ var hosts []string
+ var ports []string
+ for _, host := range strings.Split(url.Host, ",") {
+ if host == "" {
+ continue
+ }
+ if isIPOnly(host) {
+ hosts = append(hosts, strings.Trim(host, "[]"))
+ continue
+ }
+ h, p, err := net.SplitHostPort(host)
+ if err != nil {
+ return nil, fmt.Errorf("failed to split host:port in '%s', err: %w", host, err)
+ }
+ if h != "" {
+ hosts = append(hosts, h)
+ }
+ if p != "" {
+ ports = append(ports, p)
+ }
+ }
+ if len(hosts) > 0 {
+ settings["host"] = strings.Join(hosts, ",")
+ }
+ if len(ports) > 0 {
+ settings["port"] = strings.Join(ports, ",")
+ }
+
+ database := strings.TrimLeft(url.Path, "/")
+ if database != "" {
+ settings["database"] = database
+ }
+
+ nameMap := map[string]string{
+ "dbname": "database",
+ }
+
+ for k, v := range url.Query() {
+ if k2, present := nameMap[k]; present {
+ k = k2
+ }
+
+ settings[k] = v[0]
+ }
+
+ return settings, nil
+}
+
+func parsePostgresDSNSettings(s string) (map[string]string, error) {
+ settings := make(map[string]string)
+
+ nameMap := map[string]string{
+ "dbname": "database",
+ }
+
+ for len(s) > 0 {
+ var key, val string
+ eqIdx := strings.IndexRune(s, '=')
+ if eqIdx < 0 {
+ return nil, errors.New("invalid dsn")
+ }
+
+ key = strings.Trim(s[:eqIdx], " \t\n\r\v\f")
+ s = strings.TrimLeft(s[eqIdx+1:], " \t\n\r\v\f")
+ if len(s) == 0 {
+ } else if s[0] != '\'' {
+ end := 0
+ for ; end < len(s); end++ {
+ if asciiSpace[s[end]] == 1 {
+ break
+ }
+ if s[end] == '\\' {
+ end++
+ if end == len(s) {
+ return nil, errors.New("invalid backslash")
+ }
+ }
+ }
+ val = strings.Replace(strings.Replace(s[:end], "\\\\", "\\", -1), "\\'", "'", -1)
+ if end == len(s) {
+ s = ""
+ } else {
+ s = s[end+1:]
+ }
+ } else { // quoted string
+ s = s[1:]
+ end := 0
+ for ; end < len(s); end++ {
+ if s[end] == '\'' {
+ break
+ }
+ if s[end] == '\\' {
+ end++
+ }
+ }
+ if end == len(s) {
+ return nil, errors.New("unterminated quoted string in connection info string")
+ }
+ val = strings.Replace(strings.Replace(s[:end], "\\\\", "\\", -1), "\\'", "'", -1)
+ if end == len(s) {
+ s = ""
+ } else {
+ s = s[end+1:]
+ }
+ }
+
+ if k, ok := nameMap[key]; ok {
+ key = k
+ }
+
+ if key == "" {
+ return nil, errors.New("invalid dsn")
+ }
+
+ settings[key] = val
+ }
+
+ return settings, nil
+}
+
+func isIPOnly(host string) bool {
+ return net.ParseIP(strings.Trim(host, "[]")) != nil || !strings.Contains(host, ":")
+}
diff --git a/sdk/database/helper/connutil/sql.go b/sdk/database/helper/connutil/sql.go
index ca3cd489aa..bd19e77f6b 100644
--- a/sdk/database/helper/connutil/sql.go
+++ b/sdk/database/helper/connutil/sql.go
@@ -5,9 +5,11 @@ package connutil
import (
"context"
+ "crypto/tls"
"database/sql"
"fmt"
"net/url"
+ "os"
"strings"
"sync"
"time"
@@ -17,12 +19,19 @@ import (
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/sdk/database/dbplugin"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
+ "github.com/hashicorp/vault/sdk/helper/pluginutil"
+ "github.com/jackc/pgx/v4"
+ "github.com/jackc/pgx/v4/stdlib"
"github.com/mitchellh/mapstructure"
)
const (
- AuthTypeGCPIAM = "gcp_iam"
+ AuthTypeGCPIAM = "gcp_iam"
+ AuthTypeCert = "cert"
+ AuthTypeUsernamePassword = ""
+)
+const (
dbTypePostgres = "pgx"
cloudSQLPostgres = "cloudsql-postgres"
)
@@ -35,13 +44,19 @@ type SQLConnectionProducer struct {
MaxOpenConnections int `json:"max_open_connections" mapstructure:"max_open_connections" structs:"max_open_connections"`
MaxIdleConnections int `json:"max_idle_connections" mapstructure:"max_idle_connections" structs:"max_idle_connections"`
MaxConnectionLifetimeRaw interface{} `json:"max_connection_lifetime" mapstructure:"max_connection_lifetime" structs:"max_connection_lifetime"`
- Username string `json:"username" mapstructure:"username" structs:"username"`
- Password string `json:"password" mapstructure:"password" structs:"password"`
- AuthType string `json:"auth_type" mapstructure:"auth_type" structs:"auth_type"`
- ServiceAccountJSON string `json:"service_account_json" mapstructure:"service_account_json" structs:"service_account_json"`
DisableEscaping bool `json:"disable_escaping" mapstructure:"disable_escaping" structs:"disable_escaping"`
+ usePrivateIP bool `json:"use_private_ip" mapstructure:"use_private_ip" structs:"use_private_ip"`
- // cloud options here - cloudDriverName is globally unique, but only needs to be retained for the lifetime
+ // Username/Password is the default auth type when AuthType is not set
+ Username string `json:"username" mapstructure:"username" structs:"username"`
+ Password string `json:"password" mapstructure:"password" structs:"password"`
+
+ // AuthType defines the type of client authenticate used for this connection
+ AuthType string `json:"auth_type" mapstructure:"auth_type" structs:"auth_type"`
+ ServiceAccountJSON string `json:"service_account_json" mapstructure:"service_account_json" structs:"service_account_json"`
+ TLSConfig *tls.Config
+
+ // cloudDriverName is globally unique, but only needs to be retained for the lifetime
// of driver registration, not across plugin restarts.
cloudDriverName string
cloudDialerCleanup func() error
@@ -122,15 +137,11 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf
return nil, errwrap.Wrapf("invalid max_connection_lifetime: {{err}}", err)
}
- // validate auth_type if provided
- authType := c.AuthType
- if authType != "" {
- if ok := ValidateAuthType(authType); !ok {
- return nil, fmt.Errorf("invalid auth_type %s provided", authType)
- }
+ if ok := ValidateAuthType(c.AuthType); !ok {
+ return nil, fmt.Errorf("invalid auth_type: %s", c.AuthType)
}
- if authType == AuthTypeGCPIAM {
+ if c.AuthType == AuthTypeGCPIAM {
c.cloudDriverName, err = uuid.GenerateUUID()
if err != nil {
return nil, fmt.Errorf("unable to generate UUID for IAM configuration: %w", err)
@@ -140,7 +151,7 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf
// however, the driver might store a credentials file, in which case the state stored by the driver is in
// fact critical to the proper function of the connection. So it needs to be registered here inside the
// ConnectionProducer init.
- dialerCleanup, err := c.registerDrivers(c.cloudDriverName, c.ServiceAccountJSON)
+ dialerCleanup, err := c.registerDrivers(c.cloudDriverName, c.ServiceAccountJSON, c.usePrivateIP)
if err != nil {
return nil, err
}
@@ -158,7 +169,7 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf
}
if err := c.db.PingContext(ctx); err != nil {
- return nil, errwrap.Wrapf("error verifying connection: {{err}}", err)
+ return nil, errwrap.Wrapf("error verifying connection: ping failed: {{err}}", err)
}
}
@@ -216,10 +227,42 @@ func (c *SQLConnectionProducer) Connection(ctx context.Context) (interface{}, er
}
}
- var err error
- c.db, err = sql.Open(driverName, conn)
- if err != nil {
- return nil, err
+ if driverName == dbTypePostgres && c.TLSConfig != nil {
+ config, err := pgx.ParseConfig(conn)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse config: %w", err)
+ }
+ if config.TLSConfig == nil {
+ // handle sslmode=disable
+ config.TLSConfig = &tls.Config{}
+ }
+
+ config.TLSConfig.RootCAs = c.TLSConfig.RootCAs
+ config.TLSConfig.ClientCAs = c.TLSConfig.ClientCAs
+ config.TLSConfig.Certificates = c.TLSConfig.Certificates
+
+ // Ensure there are no stale fallbacks when manually setting TLSConfig
+ for _, fallback := range config.Fallbacks {
+ fallback.TLSConfig = config.TLSConfig
+ }
+
+ c.db = stdlib.OpenDB(*config)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open connection: %w", err)
+ }
+ } else if driverName == dbTypePostgres && os.Getenv(pluginutil.PluginUsePostgresSSLInline) != "" {
+ var err error
+ // TODO: remove this deprecated function call in a future SDK version
+ c.db, err = openPostgres(driverName, conn)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open connection: %w", err)
+ }
+ } else {
+ var err error
+ c.db, err = sql.Open(driverName, conn)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open connection: %w", err)
+ }
}
// Set some connection pool settings. We don't need much of this,
@@ -268,3 +311,13 @@ func (c *SQLConnectionProducer) Close() error {
func (c *SQLConnectionProducer) SetCredentials(ctx context.Context, statements dbplugin.Statements, staticUser dbplugin.StaticUserConfig) (username, password string, err error) {
return "", "", dbutil.Unimplemented()
}
+
+var configurableAuthTypes = map[string]bool{
+ AuthTypeUsernamePassword: true,
+ AuthTypeCert: true,
+ AuthTypeGCPIAM: true,
+}
+
+func ValidateAuthType(authType string) bool {
+ return configurableAuthTypes[authType]
+}
diff --git a/sdk/go.mod b/sdk/go.mod
index c9b8f7912b..d4dc9aed8f 100644
--- a/sdk/go.mod
+++ b/sdk/go.mod
@@ -1,13 +1,13 @@
module github.com/hashicorp/vault/sdk
-go 1.21
+go 1.22
require (
cloud.google.com/go/cloudsqlconn v1.4.3
github.com/armon/go-metrics v0.4.1
github.com/armon/go-radix v1.0.0
github.com/cenkalti/backoff/v3 v3.2.2
- github.com/docker/docker v25.0.5+incompatible
+ github.com/docker/docker v25.0.6+incompatible
github.com/docker/go-connections v0.4.0
github.com/evanphx/json-patch/v5 v5.6.0
github.com/fatih/structs v1.1.0
@@ -19,13 +19,13 @@ require (
github.com/hashicorp/cap/ldap v0.0.0-20240328153749-fcfe271d0227
github.com/hashicorp/errwrap v1.1.0
github.com/hashicorp/go-cleanhttp v0.5.2
- github.com/hashicorp/go-hclog v1.6.2
+ github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-immutable-radix v1.3.1
github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0
github.com/hashicorp/go-kms-wrapping/v2 v2.0.8
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-plugin v1.6.0
- github.com/hashicorp/go-retryablehttp v0.7.1
+ github.com/hashicorp/go-retryablehttp v0.7.7
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2
github.com/hashicorp/go-secure-stdlib/mlock v0.1.2
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8
@@ -40,22 +40,25 @@ require (
github.com/hashicorp/hcl v1.0.1-vault-5
github.com/hashicorp/vault/api v1.9.1
github.com/mitchellh/copystructure v1.2.0
- github.com/mitchellh/go-testing-interface v1.14.1
github.com/mitchellh/mapstructure v1.5.0
github.com/pierrec/lz4 v2.6.1+incompatible
github.com/ryanuber/go-glob v1.0.0
github.com/stretchr/testify v1.9.0
go.uber.org/atomic v1.9.0
- golang.org/x/crypto v0.23.0
- golang.org/x/net v0.25.0
- golang.org/x/text v0.15.0
- google.golang.org/grpc v1.60.1
- google.golang.org/protobuf v1.34.1
+ golang.org/x/crypto v0.26.0
+ golang.org/x/net v0.28.0
+ golang.org/x/text v0.17.0
+ google.golang.org/grpc v1.65.0
+ google.golang.org/protobuf v1.34.2
)
require (
- cloud.google.com/go/compute v1.23.0 // indirect
- cloud.google.com/go/compute/metadata v0.2.3 // indirect
+ go.opentelemetry.io/otel/sdk v1.22.0 // indirect
+ golang.org/x/sync v0.8.0 // indirect
+)
+
+require (
+ cloud.google.com/go/compute/metadata v0.3.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
@@ -65,32 +68,33 @@ require (
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fatih/color v1.16.0 // indirect
- github.com/felixge/httpsnoop v1.0.3 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/frankban/quicktest v1.14.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
- github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
- github.com/google/s2a-go v0.1.4 // indirect
+ github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
- github.com/googleapis/gax-go/v2 v2.12.0 // indirect
+ github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
+ github.com/googleapis/gax-go/v2 v2.12.2 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
- github.com/jackc/pgconn v1.14.3 // indirect
+ github.com/jackc/pgconn v1.14.3
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // 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.3 // indirect
+ github.com/jackc/pgx/v4 v4.18.3
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/patternmatcher v0.5.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
@@ -107,19 +111,18 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/stretchr/objx v0.5.2 // indirect
go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
- go.opentelemetry.io/otel v1.19.0 // indirect
- go.opentelemetry.io/otel/metric v1.19.0 // indirect
- go.opentelemetry.io/otel/trace v1.19.0 // indirect
- golang.org/x/mod v0.11.0 // indirect
- golang.org/x/oauth2 v0.18.0 // indirect
- golang.org/x/sys v0.20.0 // indirect
- golang.org/x/term v0.20.0 // indirect
- golang.org/x/time v0.3.0 // indirect
- golang.org/x/tools v0.10.0 // indirect
- google.golang.org/api v0.134.0 // indirect
- google.golang.org/appengine v1.6.8 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
+ go.opentelemetry.io/otel v1.24.0 // indirect
+ go.opentelemetry.io/otel/metric v1.24.0 // indirect
+ go.opentelemetry.io/otel/trace v1.24.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/oauth2 v0.20.0 // indirect
+ golang.org/x/sys v0.24.0 // indirect
+ golang.org/x/term v0.23.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
+ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
+ google.golang.org/api v0.169.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/sdk/go.sum b/sdk/go.sum
index fbf9ce0cf9..afd9f64d21 100644
--- a/sdk/go.sum
+++ b/sdk/go.sum
@@ -21,10 +21,8 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/cloudsqlconn v1.4.3 h1:/WYFbB1NtMtoMxCbqpzzTFPDkxxlLTPme390KEGaEPc=
cloud.google.com/go/cloudsqlconn v1.4.3/go.mod h1:QL3tuStVOO70txb3rs4G8j5uMfo5ztZii8K3oGD3VYA=
-cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
-cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
-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/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
+cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
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/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@@ -58,7 +56,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
@@ -87,11 +84,6 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
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/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0=
@@ -108,8 +100,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE=
-github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg=
+github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -117,8 +109,6 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
@@ -128,11 +118,10 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
-github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
-github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -148,8 +137,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
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=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
-github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
@@ -194,8 +183,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -212,10 +199,9 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -227,22 +213,20 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
-github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
+github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
+github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
-github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
+github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
+github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.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.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
-github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA=
+github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/hashicorp/cap/ldap v0.0.0-20240328153749-fcfe271d0227 h1:R5CMNyBNZqODw2DcGaSa2X96AgtLotXsH7aOa07zTTI=
@@ -256,9 +240,8 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
-github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
-github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I=
-github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
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=
@@ -274,8 +257,8 @@ github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDm
github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
-github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ=
-github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
@@ -490,7 +473,6 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
-github.com/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/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
@@ -545,21 +527,20 @@ 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/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
-go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
-go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
+go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
+go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
-go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
-go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
-go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
-go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
-go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
-go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
+go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
+go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw=
+go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
+go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
+go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -588,10 +569,9 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
+golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
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=
@@ -626,8 +606,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
-golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -660,20 +640,19 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
-golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
+golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
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-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
-golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
+golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
+golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
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=
@@ -685,8 +664,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
+golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -725,7 +704,6 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -739,16 +717,16 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
-golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
+golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
-golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
-golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
+golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
+golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
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=
@@ -758,17 +736,16 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
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.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
-golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -819,8 +796,8 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
-golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -844,16 +821,14 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.134.0 h1:ktL4Goua+UBgoP1eL1/60LwZJqa1sIzkLmvoR3hR6Gw=
-google.golang.org/api v0.134.0/go.mod h1:sjRL3UnjTx5UqNQS9EWr9N8p7xbHpy1k0XGRLCf3Spk=
+google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY=
+google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
-google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -878,7 +853,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
@@ -886,12 +860,11 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA=
-google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI=
-google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU=
-google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE=
+google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 h1:V71AcdLZr2p8dC9dbOIMCpqi4EmRl8wUwnJzXXLmbmc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -907,12 +880,9 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.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.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
-google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
-google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
+google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
+google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
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=
@@ -923,10 +893,8 @@ 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.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.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
-google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -941,7 +909,6 @@ gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/sdk/helper/certutil/certutil_test.go b/sdk/helper/certutil/certutil_test.go
index 8b55094612..4ebab01827 100644
--- a/sdk/helper/certutil/certutil_test.go
+++ b/sdk/helper/certutil/certutil_test.go
@@ -1006,6 +1006,101 @@ func TestBasicConstraintExtension(t *testing.T) {
})
}
+// TestIgnoreCSRSigning Make sure we validate the CSR by default and that we can override
+// the behavior disabling CSR signature checks
+func TestIgnoreCSRSigning(t *testing.T) {
+ t.Parallel()
+
+ caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatalf("failed generating ca key: %v", err)
+ }
+ subjKeyID, err := GetSubjKeyID(caKey)
+ if err != nil {
+ t.Fatalf("failed generating ca subject key id: %v", err)
+ }
+ caCertTemplate := &x509.Certificate{
+ Subject: pkix.Name{
+ CommonName: "root.localhost",
+ },
+ SubjectKeyId: subjKeyID,
+ DNSNames: []string{"root.localhost"},
+ KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
+ SerialNumber: big.NewInt(mathrand.Int63()),
+ NotBefore: time.Now().Add(-30 * time.Second),
+ NotAfter: time.Now().Add(262980 * time.Hour),
+ BasicConstraintsValid: true,
+ IsCA: true,
+ }
+ caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
+ if err != nil {
+ t.Fatalf("failed creating ca certificate: %v", err)
+ }
+ caCert, err := x509.ParseCertificate(caBytes)
+ if err != nil {
+ t.Fatalf("failed parsing ca certificate: %v", err)
+ }
+
+ signingBundle := &CAInfoBundle{
+ ParsedCertBundle: ParsedCertBundle{
+ PrivateKeyType: ECPrivateKey,
+ PrivateKey: caKey,
+ CertificateBytes: caBytes,
+ Certificate: caCert,
+ CAChain: nil,
+ },
+ URLs: &URLEntries{},
+ }
+
+ key := genEdDSA(t)
+ csr := &x509.CertificateRequest{
+ PublicKeyAlgorithm: x509.ECDSA,
+ PublicKey: key.Public(),
+ Subject: pkix.Name{
+ CommonName: "test.dadgarcorp.com",
+ },
+ }
+ t.Run(fmt.Sprintf("ignore-csr-disabled"), func(t *testing.T) {
+ params := &CreationParameters{
+ URLs: &URLEntries{},
+ }
+ data := &CreationBundle{
+ Params: params,
+ SigningBundle: signingBundle,
+ CSR: csr,
+ }
+
+ _, err := SignCertificate(data)
+ if err == nil {
+ t.Fatalf("should have failed signing csr with ignore csr signature disabled")
+ }
+ if !strings.Contains(err.Error(), "request signature invalid") {
+ t.Fatalf("expected error to contain 'request signature invalid': got: %v", err)
+ }
+ })
+
+ t.Run(fmt.Sprintf("ignore-csr-enabled"), func(t *testing.T) {
+ params := &CreationParameters{
+ IgnoreCSRSignature: true,
+ URLs: &URLEntries{},
+ }
+ data := &CreationBundle{
+ Params: params,
+ SigningBundle: signingBundle,
+ CSR: csr,
+ }
+
+ cert, err := SignCertificate(data)
+ if err != nil {
+ t.Fatalf("failed to sign certificate: %v", err)
+ }
+
+ if err := cert.Verify(); err != nil {
+ t.Fatalf("signature verification failed: %v", err)
+ }
+ })
+}
+
func genRsaKey(t *testing.T) *rsa.PrivateKey {
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
diff --git a/sdk/helper/certutil/helpers.go b/sdk/helper/certutil/helpers.go
index b7fc22db02..674878cbef 100644
--- a/sdk/helper/certutil/helpers.go
+++ b/sdk/helper/certutil/helpers.go
@@ -23,7 +23,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"math/big"
"net"
"net/url"
@@ -1187,9 +1186,10 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun
return nil, errutil.UserError{Err: "nil csr given to signCertificate"}
}
- err := data.CSR.CheckSignature()
- if err != nil {
- return nil, errutil.UserError{Err: "request signature invalid"}
+ if !data.Params.IgnoreCSRSignature {
+ if err := data.CSR.CheckSignature(); err != nil {
+ return nil, errutil.UserError{Err: "request signature invalid"}
+ }
}
result := &ParsedCertBundle{}
@@ -1315,7 +1315,7 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun
}
func NewCertPool(reader io.Reader) (*x509.CertPool, error) {
- pemBlock, err := ioutil.ReadAll(reader)
+ pemBlock, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
diff --git a/sdk/helper/certutil/types.go b/sdk/helper/certutil/types.go
index ca245d7d42..cdfc912e92 100644
--- a/sdk/helper/certutil/types.go
+++ b/sdk/helper/certutil/types.go
@@ -171,7 +171,7 @@ func GetPrivateKeyTypeFromPublicKey(pubKey crypto.PublicKey) PrivateKeyType {
return RSAPrivateKey
case *ecdsa.PublicKey:
return ECPrivateKey
- case *ed25519.PublicKey:
+ case ed25519.PublicKey:
return Ed25519PrivateKey
default:
return UnknownPrivateKey
@@ -819,6 +819,11 @@ type CreationParameters struct {
// The explicit SKID to use; especially useful for cross-signing.
SKID []byte
+
+ // Ignore validating the CSR's signature. This should only be enabled if the
+ // sender of the CSR has proven proof of possession of the associated
+ // private key by some other means, otherwise keep this set to false.
+ IgnoreCSRSignature bool
}
type CreationBundle struct {
diff --git a/sdk/helper/certutil/types_test.go b/sdk/helper/certutil/types_test.go
new file mode 100644
index 0000000000..2cf383afaa
--- /dev/null
+++ b/sdk/helper/certutil/types_test.go
@@ -0,0 +1,63 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package certutil
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/ed25519"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "testing"
+)
+
+func TestGetPrivateKeyTypeFromPublicKey(t *testing.T) {
+ rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ t.Fatalf("error generating rsa key: %s", err)
+ }
+
+ ecdsaKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+ if err != nil {
+ t.Fatalf("error generating ecdsa key: %s", err)
+ }
+
+ publicKey, _, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ t.Fatalf("error generating ed25519 key: %s", err)
+ }
+
+ testCases := map[string]struct {
+ publicKey crypto.PublicKey
+ expectedKeyType PrivateKeyType
+ }{
+ "rsa": {
+ publicKey: rsaKey.Public(),
+ expectedKeyType: RSAPrivateKey,
+ },
+ "ecdsa": {
+ publicKey: ecdsaKey.Public(),
+ expectedKeyType: ECPrivateKey,
+ },
+ "ed25519": {
+ publicKey: publicKey,
+ expectedKeyType: Ed25519PrivateKey,
+ },
+ "bad key type": {
+ publicKey: []byte{},
+ expectedKeyType: UnknownPrivateKey,
+ },
+ }
+
+ for name, tt := range testCases {
+ t.Run(name, func(t *testing.T) {
+ keyType := GetPrivateKeyTypeFromPublicKey(tt.publicKey)
+
+ if keyType != tt.expectedKeyType {
+ t.Fatalf("key type mismatch: expected %s, got %s", tt.expectedKeyType, keyType)
+ }
+ })
+ }
+}
diff --git a/sdk/helper/clientcountutil/generation/generate_data.pb.go b/sdk/helper/clientcountutil/generation/generate_data.pb.go
index dfe5eba189..29267282e9 100644
--- a/sdk/helper/clientcountutil/generation/generate_data.pb.go
+++ b/sdk/helper/clientcountutil/generation/generate_data.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/helper/clientcountutil/generation/generate_data.proto
@@ -621,7 +621,7 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_rawDescGZIP(
var file_sdk_helper_clientcountutil_generation_generate_data_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
-var file_sdk_helper_clientcountutil_generation_generate_data_proto_goTypes = []interface{}{
+var file_sdk_helper_clientcountutil_generation_generate_data_proto_goTypes = []any{
(WriteOptions)(0), // 0: generation.WriteOptions
(*ActivityLogMockInput)(nil), // 1: generation.ActivityLogMockInput
(*Data)(nil), // 2: generation.Data
@@ -651,7 +651,7 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*ActivityLogMockInput); i {
case 0:
return &v.state
@@ -663,7 +663,7 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_init() {
return nil
}
}
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*Data); i {
case 0:
return &v.state
@@ -675,7 +675,7 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_init() {
return nil
}
}
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*Segments); i {
case 0:
return &v.state
@@ -687,7 +687,7 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_init() {
return nil
}
}
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*Segment); i {
case 0:
return &v.state
@@ -699,7 +699,7 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_init() {
return nil
}
}
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*Clients); i {
case 0:
return &v.state
@@ -711,7 +711,7 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_init() {
return nil
}
}
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*Client); i {
case 0:
return &v.state
@@ -724,13 +724,13 @@ func file_sdk_helper_clientcountutil_generation_generate_data_proto_init() {
}
}
}
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[1].OneofWrappers = []interface{}{
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[1].OneofWrappers = []any{
(*Data_CurrentMonth)(nil),
(*Data_MonthsAgo)(nil),
(*Data_All)(nil),
(*Data_Segments)(nil),
}
- file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[3].OneofWrappers = []interface{}{}
+ file_sdk_helper_clientcountutil_generation_generate_data_proto_msgTypes[3].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
diff --git a/sdk/helper/docker/testhelpers.go b/sdk/helper/docker/testhelpers.go
index f1fefd65cd..af1f3f72a6 100644
--- a/sdk/helper/docker/testhelpers.go
+++ b/sdk/helper/docker/testhelpers.go
@@ -12,7 +12,6 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"net/url"
"os"
"strconv"
@@ -415,7 +414,7 @@ func (d *Runner) Start(ctx context.Context, addSuffix, forceLocalAddr bool) (*St
}
resp, _ := d.DockerAPI.ImageCreate(ctx, cfg.Image, opts)
if resp != nil {
- _, _ = ioutil.ReadAll(resp)
+ _, _ = io.ReadAll(resp)
}
for vol, mtpt := range d.RunOptions.VolumeNameToMountPoint {
diff --git a/sdk/helper/keysutil/policy.go b/sdk/helper/keysutil/policy.go
index 2708cc7cdb..08d1ebcf09 100644
--- a/sdk/helper/keysutil/policy.go
+++ b/sdk/helper/keysutil/policy.go
@@ -70,6 +70,7 @@ const (
KeyType_HMAC
KeyType_AES128_CMAC
KeyType_AES256_CMAC
+ // If adding to this list please update allTestKeyTypes in policy_test.go
)
const (
@@ -179,6 +180,17 @@ func (kt KeyType) CMACSupported() bool {
}
}
+func (kt KeyType) HMACSupported() bool {
+ switch {
+ case kt.CMACSupported():
+ return false
+ case kt == KeyType_MANAGED_KEY:
+ return false
+ default:
+ return true
+ }
+}
+
func (kt KeyType) ImportPublicKeySupported() bool {
switch kt {
case KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096, KeyType_ECDSA_P256, KeyType_ECDSA_P384, KeyType_ECDSA_P521, KeyType_ED25519:
@@ -713,8 +725,10 @@ func (p *Policy) NeedsUpgrade() bool {
return true
}
- if p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey == nil || len(p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey) == 0 {
- return true
+ if p.Type.HMACSupported() {
+ if p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey == nil || len(p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey) == 0 {
+ return true
+ }
}
return false
@@ -775,18 +789,20 @@ func (p *Policy) Upgrade(ctx context.Context, storage logical.Storage, randReade
persistNeeded = true
}
- if p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey == nil || len(p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey) == 0 {
- entry := p.Keys[strconv.Itoa(p.LatestVersion)]
- hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
- if err != nil {
- return err
- }
- entry.HMACKey = hmacKey
- p.Keys[strconv.Itoa(p.LatestVersion)] = entry
- persistNeeded = true
+ if p.Type.HMACSupported() {
+ if p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey == nil || len(p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey) == 0 {
+ entry := p.Keys[strconv.Itoa(p.LatestVersion)]
+ hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
+ if err != nil {
+ return err
+ }
+ entry.HMACKey = hmacKey
+ p.Keys[strconv.Itoa(p.LatestVersion)] = entry
+ persistNeeded = true
- if p.Type == KeyType_HMAC {
- entry.HMACKey = entry.Key
+ if p.Type == KeyType_HMAC {
+ entry.HMACKey = entry.Key
+ }
}
}
diff --git a/sdk/helper/keysutil/policy_test.go b/sdk/helper/keysutil/policy_test.go
index 487804b719..fd753f22ba 100644
--- a/sdk/helper/keysutil/policy_test.go
+++ b/sdk/helper/keysutil/policy_test.go
@@ -28,6 +28,120 @@ import (
"golang.org/x/crypto/ed25519"
)
+// Ordering of these items needs to match the iota order defined in policy.go. Ordering changes
+// should never occur, as it would lead to a key type change within existing stored policies.
+var allTestKeyTypes = []KeyType{
+ KeyType_AES256_GCM96, KeyType_ECDSA_P256, KeyType_ED25519, KeyType_RSA2048,
+ KeyType_RSA4096, KeyType_ChaCha20_Poly1305, KeyType_ECDSA_P384, KeyType_ECDSA_P521, KeyType_AES128_GCM96,
+ KeyType_RSA3072, KeyType_MANAGED_KEY, KeyType_HMAC, KeyType_AES128_CMAC, KeyType_AES256_CMAC,
+}
+
+func TestPolicy_KeyTypes(t *testing.T) {
+ // Make sure the iota value never change for key types, as existing storage would be affected
+ for i, keyType := range allTestKeyTypes {
+ if int(keyType) != i {
+ t.Fatalf("iota of keytype %s changed, expected %d got %d", keyType.String(), i, keyType)
+ }
+ }
+
+ // Make sure we have a string presentation for all types
+ for _, keyType := range allTestKeyTypes {
+ if strings.Contains(keyType.String(), "unknown") {
+ t.Fatalf("keytype with iota of %d should not contain 'unknown', missing in String() switch statement", keyType)
+ }
+ }
+}
+
+func TestPolicy_HmacCmacSuported(t *testing.T) {
+ // Test HMAC supported feature
+ for _, keyType := range allTestKeyTypes {
+ switch keyType {
+ case KeyType_MANAGED_KEY:
+ if keyType.HMACSupported() {
+ t.Fatalf("hmac should not have been not be supported for keytype %s", keyType.String())
+ }
+ if keyType.CMACSupported() {
+ t.Fatalf("cmac should not have been be supported for keytype %s", keyType.String())
+ }
+ case KeyType_AES128_CMAC, KeyType_AES256_CMAC:
+ if keyType.HMACSupported() {
+ t.Fatalf("hmac should have been not be supported for keytype %s", keyType.String())
+ }
+ if !keyType.CMACSupported() {
+ t.Fatalf("cmac should have been be supported for keytype %s", keyType.String())
+ }
+ default:
+ if !keyType.HMACSupported() {
+ t.Fatalf("hmac should have been supported for keytype %s", keyType.String())
+ }
+ if keyType.CMACSupported() {
+ t.Fatalf("cmac should not have been supported for keytype %s", keyType.String())
+ }
+ }
+ }
+}
+
+func TestPolicy_CMACKeyUpgrade(t *testing.T) {
+ ctx := context.Background()
+ lm, _ := NewLockManager(false, 0)
+ storage := &logical.InmemStorage{}
+ p, upserted, err := lm.GetPolicy(ctx, PolicyRequest{
+ Upsert: true,
+ Storage: storage,
+ KeyType: KeyType_AES256_CMAC,
+ Name: "test",
+ }, rand.Reader)
+ if err != nil {
+ t.Fatalf("failed loading policy: %v", err)
+ }
+ if p == nil {
+ t.Fatal("nil policy")
+ }
+ if !upserted {
+ t.Fatal("expected an upsert")
+ }
+
+ // This verifies we don't have a hmac key
+ _, err = p.HMACKey(1)
+ if err == nil {
+ t.Fatal("cmac key should not return an hmac key but did on initial creation")
+ }
+
+ if p.NeedsUpgrade() {
+ t.Fatal("cmac key should not require an upgrade after initial key creation")
+ }
+
+ err = p.Upgrade(ctx, storage, rand.Reader)
+ if err != nil {
+ t.Fatalf("an error was returned from upgrade method: %v", err)
+ }
+ p.Unlock()
+
+ // Now reload our policy from disk and make sure we still don't have a hmac key
+ p, upserted, err = lm.GetPolicy(ctx, PolicyRequest{
+ Upsert: true,
+ Storage: storage,
+ KeyType: KeyType_AES256_CMAC,
+ Name: "test",
+ }, rand.Reader)
+ if err != nil {
+ t.Fatalf("failed loading policy: %v", err)
+ }
+ if p == nil {
+ t.Fatal("nil policy")
+ }
+ if upserted {
+ t.Fatal("expected the key to exist but upserted was true")
+ }
+
+ p.Unlock()
+
+ _, err = p.HMACKey(1)
+ if err == nil {
+ t.Fatal("cmac key should not return an hmac key post upgrade")
+ }
+}
+
func TestPolicy_KeyEntryMapUpgrade(t *testing.T) {
now := time.Now()
old := map[int]KeyEntry{
diff --git a/sdk/helper/ocsp/client.go b/sdk/helper/ocsp/client.go
index 8fba050cb2..cef1f6896b 100644
--- a/sdk/helper/ocsp/client.go
+++ b/sdk/helper/ocsp/client.go
@@ -702,12 +702,12 @@ func (c *Client) VerifyLeafCertificate(ctx context.Context, subject, issuer *x50
if results.code == ocspStatusGood {
return nil
} else {
- serial := issuer.SerialNumber
+ serial := subject.SerialNumber
serialHex := strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":"))
if results.code == ocspStatusRevoked {
return fmt.Errorf("certificate with serial number %s has been revoked", serialHex)
} else if conf.OcspFailureMode == FailOpenFalse {
- return fmt.Errorf("unknown OCSP status for cert with serial number %s", strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":")))
+ return fmt.Errorf("unknown OCSP status for cert with serial number %s", serialHex)
} else {
c.Logger().Warn("could not validate OCSP status for cert, but continuing in fail open mode", "serial", serialHex)
}
diff --git a/sdk/helper/ocsp/ocsp_test.go b/sdk/helper/ocsp/ocsp_test.go
index 326a5b2336..1115766534 100644
--- a/sdk/helper/ocsp/ocsp_test.go
+++ b/sdk/helper/ocsp/ocsp_test.go
@@ -15,7 +15,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"math/big"
"net"
"net/http"
@@ -64,7 +63,7 @@ func TestOCSP(t *testing.T) {
t.Fatalf("failed to GET contents. err: %v", err)
}
defer res.Body.Close()
- _, err = ioutil.ReadAll(res.Body)
+ _, err = io.ReadAll(res.Body)
if err != nil {
t.Fatalf("failed to read content body for %v", tgt)
}
@@ -113,7 +112,7 @@ func TestMultiOCSP(t *testing.T) {
t.Fatalf("failed to GET contents. err: %v", err)
}
defer res.Body.Close()
- _, err = ioutil.ReadAll(res.Body)
+ _, err = io.ReadAll(res.Body)
if err != nil {
t.Fatalf("failed to read content body for %v", tgt)
}
diff --git a/sdk/helper/pluginutil/env.go b/sdk/helper/pluginutil/env.go
index 515baa1f76..ea05e8462c 100644
--- a/sdk/helper/pluginutil/env.go
+++ b/sdk/helper/pluginutil/env.go
@@ -44,6 +44,11 @@ const (
// colliding plugin-specific environment variables. Otherwise, plugin-specific
// environment variables take precedence over Vault process environment variables.
PluginUseLegacyEnvLayering = "VAULT_PLUGIN_USE_LEGACY_ENV_LAYERING"
+
+ // PluginUsePostgresSSLInline enables the usage of a custom sslinline
+ // configuration as a shim to the pgx posgtres library.
+ // Deprecated: VAULT_PLUGIN_USE_POSTGRES_SSLINLINE will be removed in a future version of the Vault SDK.
+ PluginUsePostgresSSLInline = "VAULT_PLUGIN_USE_POSTGRES_SSLINLINE"
)
// OptionallyEnableMlock determines if mlock should be called, and if so enables
diff --git a/sdk/helper/pluginutil/multiplexing.pb.go b/sdk/helper/pluginutil/multiplexing.pb.go
index 1faed8698f..4e6c9f46a2 100644
--- a/sdk/helper/pluginutil/multiplexing.pb.go
+++ b/sdk/helper/pluginutil/multiplexing.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/helper/pluginutil/multiplexing.proto
@@ -150,7 +150,7 @@ func file_sdk_helper_pluginutil_multiplexing_proto_rawDescGZIP() []byte {
}
var file_sdk_helper_pluginutil_multiplexing_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
-var file_sdk_helper_pluginutil_multiplexing_proto_goTypes = []interface{}{
+var file_sdk_helper_pluginutil_multiplexing_proto_goTypes = []any{
(*MultiplexingSupportRequest)(nil), // 0: pluginutil.multiplexing.MultiplexingSupportRequest
(*MultiplexingSupportResponse)(nil), // 1: pluginutil.multiplexing.MultiplexingSupportResponse
}
@@ -170,7 +170,7 @@ func file_sdk_helper_pluginutil_multiplexing_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_helper_pluginutil_multiplexing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_pluginutil_multiplexing_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*MultiplexingSupportRequest); i {
case 0:
return &v.state
@@ -182,7 +182,7 @@ func file_sdk_helper_pluginutil_multiplexing_proto_init() {
return nil
}
}
- file_sdk_helper_pluginutil_multiplexing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_helper_pluginutil_multiplexing_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*MultiplexingSupportResponse); i {
case 0:
return &v.state
diff --git a/sdk/helper/pluginutil/multiplexing_grpc.pb.go b/sdk/helper/pluginutil/multiplexing_grpc.pb.go
index 1fc6cba7c6..0f0df2128b 100644
--- a/sdk/helper/pluginutil/multiplexing_grpc.pb.go
+++ b/sdk/helper/pluginutil/multiplexing_grpc.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
-// - protoc-gen-go-grpc v1.3.0
+// - protoc-gen-go-grpc v1.4.0
// - protoc (unknown)
// source: sdk/helper/pluginutil/multiplexing.proto
@@ -18,8 +18,8 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
-// Requires gRPC-Go v1.32.0 or later.
-const _ = grpc.SupportPackageIsVersion7
+// Requires gRPC-Go v1.62.0 or later.
+const _ = grpc.SupportPackageIsVersion8
const (
PluginMultiplexing_MultiplexingSupport_FullMethodName = "/pluginutil.multiplexing.PluginMultiplexing/MultiplexingSupport"
@@ -41,8 +41,9 @@ func NewPluginMultiplexingClient(cc grpc.ClientConnInterface) PluginMultiplexing
}
func (c *pluginMultiplexingClient) MultiplexingSupport(ctx context.Context, in *MultiplexingSupportRequest, opts ...grpc.CallOption) (*MultiplexingSupportResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MultiplexingSupportResponse)
- err := c.cc.Invoke(ctx, PluginMultiplexing_MultiplexingSupport_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, PluginMultiplexing_MultiplexingSupport_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
diff --git a/sdk/helper/policyutil/policyutil.go b/sdk/helper/policyutil/policyutil.go
index a5a8082e13..a8e6214ab0 100644
--- a/sdk/helper/policyutil/policyutil.go
+++ b/sdk/helper/policyutil/policyutil.go
@@ -79,33 +79,25 @@ func SanitizePolicies(policies []string, addDefault bool) []string {
// EquivalentPolicies checks whether the given policy sets are equivalent, as in,
// they contain the same values. The benefit of this method is that it leaves
// the "default" policy out of its comparisons as it may be added later by core
-// after a set of policies has been saved by a backend.
+// after a set of policies has been saved by a backend and performs policy name
+// normalization.
func EquivalentPolicies(a, b []string) bool {
- switch {
- case a == nil && b == nil:
- return true
- case a == nil && len(b) == 1 && b[0] == "default":
- return true
- case b == nil && len(a) == 1 && a[0] == "default":
- return true
- case a == nil || b == nil:
- return false
- }
-
// First we'll build maps to ensure unique values and filter default
- mapA := map[string]bool{}
- mapB := map[string]bool{}
+ mapA := map[string]struct{}{}
+ mapB := map[string]struct{}{}
for _, keyA := range a {
+ keyA := strings.ToLower(keyA)
if keyA == "default" {
continue
}
- mapA[keyA] = true
+ mapA[keyA] = struct{}{}
}
for _, keyB := range b {
+ keyB := strings.ToLower(keyB)
if keyB == "default" {
continue
}
- mapB[keyB] = true
+ mapB[keyB] = struct{}{}
}
// Now we'll build our checking slices
diff --git a/sdk/helper/policyutil/policyutil_test.go b/sdk/helper/policyutil/policyutil_test.go
index 2280ba93ee..04aedfae72 100644
--- a/sdk/helper/policyutil/policyutil_test.go
+++ b/sdk/helper/policyutil/policyutil_test.go
@@ -56,24 +56,48 @@ func TestParsePolicies(t *testing.T) {
}
func TestEquivalentPolicies(t *testing.T) {
- a := []string{"foo", "bar"}
- var b []string
- if EquivalentPolicies(a, b) {
- t.Fatal("bad")
+ testCases := map[string]struct {
+ A []string
+ B []string
+ Expected bool
+ }{
+ "nil": {
+ A: nil,
+ B: nil,
+ Expected: true,
+ },
+ "empty": {
+ A: []string{"foo", "bar"},
+ B: []string{},
+ Expected: false,
+ },
+ "missing": {
+ A: []string{"foo", "bar"},
+ B: []string{"foo"},
+ Expected: false,
+ },
+ "equal": {
+ A: []string{"bar", "foo"},
+ B: []string{"bar", "foo"},
+ Expected: true,
+ },
+ "default": {
+ A: []string{"bar", "foo"},
+ B: []string{"foo", "default", "bar"},
+ Expected: true,
+ },
+ "case-insensitive": {
+ A: []string{"test"},
+ B: []string{"Test"},
+ Expected: true,
+ },
}
- b = []string{"foo"}
- if EquivalentPolicies(a, b) {
- t.Fatal("bad")
- }
-
- b = []string{"bar", "foo"}
- if !EquivalentPolicies(a, b) {
- t.Fatal("bad")
- }
-
- b = []string{"foo", "default", "bar"}
- if !EquivalentPolicies(a, b) {
- t.Fatal("bad")
+ for name, tc := range testCases {
+ t.Run(name, func(t *testing.T) {
+ if EquivalentPolicies(tc.A, tc.B) != tc.Expected {
+ t.Fatal("bad")
+ }
+ })
}
}
diff --git a/sdk/helper/testcluster/docker/environment.go b/sdk/helper/testcluster/docker/environment.go
index 8ed253d47b..fd1c11ffee 100644
--- a/sdk/helper/testcluster/docker/environment.go
+++ b/sdk/helper/testcluster/docker/environment.go
@@ -1008,6 +1008,7 @@ func (n *DockerClusterNode) PartitionFromCluster(ctx context.Context) error {
"-xec", strings.Join([]string{
fmt.Sprintf("echo partitioning container from network"),
"apk add iproute2",
+ "apk add iptables",
// Get the gateway address for the bridge so we can allow host to
// container traffic still.
"GW=$(ip r | grep default | grep eth0 | cut -f 3 -d' ')",
diff --git a/sdk/helper/testcluster/exec.go b/sdk/helper/testcluster/exec.go
index d91a3de034..f871e0dabb 100644
--- a/sdk/helper/testcluster/exec.go
+++ b/sdk/helper/testcluster/exec.go
@@ -53,7 +53,7 @@ type ExecDevClusterOptions struct {
BaseListenAddress string
}
-func NewTestExecDevCluster(t *testing.T, opts *ExecDevClusterOptions) *ExecDevCluster {
+func NewTestExecDevServer(t *testing.T, opts *ExecDevClusterOptions) *ExecDevCluster {
if opts == nil {
opts = &ExecDevClusterOptions{}
}
@@ -141,12 +141,10 @@ func (dc *ExecDevCluster) setupExecDevCluster(ctx context.Context, opts *ExecDev
clusterJsonPath := filepath.Join(dc.tmpDir, "cluster.json")
args := []string{"server", "-dev", "-dev-cluster-json", clusterJsonPath}
switch {
- case opts.NumCores == 3:
- args = append(args, "-dev-three-node")
case opts.NumCores == 1:
args = append(args, "-dev-tls")
default:
- return fmt.Errorf("NumCores=1 and NumCores=3 are the only supported options right now")
+ return fmt.Errorf("NumCores=1 is the only supported option right now")
}
if opts.BaseListenAddress != "" {
args = append(args, "-dev-listen-address", opts.BaseListenAddress)
@@ -223,6 +221,7 @@ func (dc *ExecDevCluster) setupExecDevCluster(ctx context.Context, opts *ExecDev
}
time.Sleep(500 * time.Millisecond)
}
+
return ctx.Err()
}
diff --git a/sdk/helper/testhelpers/output.go b/sdk/helper/testhelpers/output.go
index c18b1bb6de..9fde77f0d6 100644
--- a/sdk/helper/testhelpers/output.go
+++ b/sdk/helper/testhelpers/output.go
@@ -7,8 +7,8 @@ import (
"crypto/sha256"
"fmt"
"reflect"
+ "testing"
- "github.com/mitchellh/go-testing-interface"
"github.com/mitchellh/mapstructure"
)
@@ -74,7 +74,7 @@ func ToString(in any) string {
// StringOrDie renders its input using ToMap, and returns a string containing the
// result. If rendering yields an error, calls t.Fatal.
-func StringOrDie(t testing.T, in any) string {
+func StringOrDie(t testing.TB, in any) string {
t.Helper()
m, err := ToMap(in)
if err != nil {
diff --git a/sdk/logical/event.pb.go b/sdk/logical/event.pb.go
index 96633525cf..1db6d46dc9 100644
--- a/sdk/logical/event.pb.go
+++ b/sdk/logical/event.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/logical/event.proto
@@ -332,7 +332,7 @@ func file_sdk_logical_event_proto_rawDescGZIP() []byte {
}
var file_sdk_logical_event_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
-var file_sdk_logical_event_proto_goTypes = []interface{}{
+var file_sdk_logical_event_proto_goTypes = []any{
(*EventPluginInfo)(nil), // 0: logical.EventPluginInfo
(*EventData)(nil), // 1: logical.EventData
(*EventReceived)(nil), // 2: logical.EventReceived
@@ -355,7 +355,7 @@ func file_sdk_logical_event_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_logical_event_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_event_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*EventPluginInfo); i {
case 0:
return &v.state
@@ -367,7 +367,7 @@ func file_sdk_logical_event_proto_init() {
return nil
}
}
- file_sdk_logical_event_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_event_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*EventData); i {
case 0:
return &v.state
@@ -379,7 +379,7 @@ func file_sdk_logical_event_proto_init() {
return nil
}
}
- file_sdk_logical_event_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_event_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*EventReceived); i {
case 0:
return &v.state
diff --git a/sdk/logical/identity.pb.go b/sdk/logical/identity.pb.go
index 5a4a90c87d..5f08ce1689 100644
--- a/sdk/logical/identity.pb.go
+++ b/sdk/logical/identity.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/logical/identity.proto
@@ -592,7 +592,7 @@ func file_sdk_logical_identity_proto_rawDescGZIP() []byte {
}
var file_sdk_logical_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
-var file_sdk_logical_identity_proto_goTypes = []interface{}{
+var file_sdk_logical_identity_proto_goTypes = []any{
(*Entity)(nil), // 0: logical.Entity
(*Alias)(nil), // 1: logical.Alias
(*Group)(nil), // 2: logical.Group
@@ -627,7 +627,7 @@ func file_sdk_logical_identity_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_logical_identity_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_identity_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Entity); i {
case 0:
return &v.state
@@ -639,7 +639,7 @@ func file_sdk_logical_identity_proto_init() {
return nil
}
}
- file_sdk_logical_identity_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_identity_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*Alias); i {
case 0:
return &v.state
@@ -651,7 +651,7 @@ func file_sdk_logical_identity_proto_init() {
return nil
}
}
- file_sdk_logical_identity_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_identity_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*Group); i {
case 0:
return &v.state
@@ -663,7 +663,7 @@ func file_sdk_logical_identity_proto_init() {
return nil
}
}
- file_sdk_logical_identity_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_identity_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*MFAMethodID); i {
case 0:
return &v.state
@@ -675,7 +675,7 @@ func file_sdk_logical_identity_proto_init() {
return nil
}
}
- file_sdk_logical_identity_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_identity_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*MFAConstraintAny); i {
case 0:
return &v.state
@@ -687,7 +687,7 @@ func file_sdk_logical_identity_proto_init() {
return nil
}
}
- file_sdk_logical_identity_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_identity_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*MFARequirement); i {
case 0:
return &v.state
diff --git a/sdk/logical/plugin.pb.go b/sdk/logical/plugin.pb.go
index 3c9fc96e67..7b8fe8ce72 100644
--- a/sdk/logical/plugin.pb.go
+++ b/sdk/logical/plugin.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/logical/plugin.proto
@@ -123,7 +123,7 @@ func file_sdk_logical_plugin_proto_rawDescGZIP() []byte {
}
var file_sdk_logical_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_sdk_logical_plugin_proto_goTypes = []interface{}{
+var file_sdk_logical_plugin_proto_goTypes = []any{
(*PluginEnvironment)(nil), // 0: logical.PluginEnvironment
}
var file_sdk_logical_plugin_proto_depIdxs = []int32{
@@ -140,7 +140,7 @@ func file_sdk_logical_plugin_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_logical_plugin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_plugin_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*PluginEnvironment); i {
case 0:
return &v.state
diff --git a/sdk/logical/testing.go b/sdk/logical/testing.go
index d379561930..c507b1c3e3 100644
--- a/sdk/logical/testing.go
+++ b/sdk/logical/testing.go
@@ -6,15 +6,15 @@ package logical
import (
"context"
"reflect"
+ "testing"
"time"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/helper/logging"
- testing "github.com/mitchellh/go-testing-interface"
)
// TestRequest is a helper to create a purely in-memory Request struct.
-func TestRequest(t testing.T, op Operation, path string) *Request {
+func TestRequest(t testing.TB, op Operation, path string) *Request {
return &Request{
Operation: op,
Path: path,
@@ -26,7 +26,7 @@ func TestRequest(t testing.T, op Operation, path string) *Request {
// TestStorage is a helper that can be used from unit tests to verify
// the behavior of a Storage impl.
-func TestStorage(t testing.T, s Storage) {
+func TestStorage(t testing.TB, s Storage) {
keys, err := s.List(context.Background(), "")
if err != nil {
t.Fatalf("list error: %s", err)
diff --git a/sdk/logical/version.pb.go b/sdk/logical/version.pb.go
index c21789b7aa..abb579096b 100644
--- a/sdk/logical/version.pb.go
+++ b/sdk/logical/version.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/logical/version.proto
@@ -141,7 +141,7 @@ func file_sdk_logical_version_proto_rawDescGZIP() []byte {
}
var file_sdk_logical_version_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
-var file_sdk_logical_version_proto_goTypes = []interface{}{
+var file_sdk_logical_version_proto_goTypes = []any{
(*Empty)(nil), // 0: logical.Empty
(*VersionReply)(nil), // 1: logical.VersionReply
}
@@ -161,7 +161,7 @@ func file_sdk_logical_version_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_logical_version_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_version_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Empty); i {
case 0:
return &v.state
@@ -173,7 +173,7 @@ func file_sdk_logical_version_proto_init() {
return nil
}
}
- file_sdk_logical_version_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_logical_version_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*VersionReply); i {
case 0:
return &v.state
diff --git a/sdk/logical/version_grpc.pb.go b/sdk/logical/version_grpc.pb.go
index bdb3561449..9aa110fce9 100644
--- a/sdk/logical/version_grpc.pb.go
+++ b/sdk/logical/version_grpc.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
-// - protoc-gen-go-grpc v1.3.0
+// - protoc-gen-go-grpc v1.4.0
// - protoc (unknown)
// source: sdk/logical/version.proto
@@ -18,8 +18,8 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
-// Requires gRPC-Go v1.32.0 or later.
-const _ = grpc.SupportPackageIsVersion7
+// Requires gRPC-Go v1.62.0 or later.
+const _ = grpc.SupportPackageIsVersion8
const (
PluginVersion_Version_FullMethodName = "/logical.PluginVersion/Version"
@@ -28,6 +28,8 @@ const (
// PluginVersionClient is the client API for PluginVersion service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+//
+// PluginVersion is an optional RPC service implemented by plugins.
type PluginVersionClient interface {
// Version returns version information for the plugin.
Version(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*VersionReply, error)
@@ -42,8 +44,9 @@ func NewPluginVersionClient(cc grpc.ClientConnInterface) PluginVersionClient {
}
func (c *pluginVersionClient) Version(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*VersionReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(VersionReply)
- err := c.cc.Invoke(ctx, PluginVersion_Version_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, PluginVersion_Version_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -53,6 +56,8 @@ func (c *pluginVersionClient) Version(ctx context.Context, in *Empty, opts ...gr
// PluginVersionServer is the server API for PluginVersion service.
// All implementations must embed UnimplementedPluginVersionServer
// for forward compatibility
+//
+// PluginVersion is an optional RPC service implemented by plugins.
type PluginVersionServer interface {
// Version returns version information for the plugin.
Version(context.Context, *Empty) (*VersionReply, error)
diff --git a/sdk/plugin/pb/backend.pb.go b/sdk/plugin/pb/backend.pb.go
index 1a171af39c..4c28e80b13 100644
--- a/sdk/plugin/pb/backend.pb.go
+++ b/sdk/plugin/pb/backend.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.34.1
+// protoc-gen-go v1.34.2
// protoc (unknown)
// source: sdk/plugin/pb/backend.proto
@@ -4288,7 +4288,7 @@ func file_sdk_plugin_pb_backend_proto_rawDescGZIP() []byte {
}
var file_sdk_plugin_pb_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 60)
-var file_sdk_plugin_pb_backend_proto_goTypes = []interface{}{
+var file_sdk_plugin_pb_backend_proto_goTypes = []any{
(*Empty)(nil), // 0: pb.Empty
(*Header)(nil), // 1: pb.Header
(*ProtoError)(nil), // 2: pb.ProtoError
@@ -4463,7 +4463,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_sdk_plugin_pb_backend_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Empty); i {
case 0:
return &v.state
@@ -4475,7 +4475,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*Header); i {
case 0:
return &v.state
@@ -4487,7 +4487,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*ProtoError); i {
case 0:
return &v.state
@@ -4499,7 +4499,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*Paths); i {
case 0:
return &v.state
@@ -4511,7 +4511,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*Request); i {
case 0:
return &v.state
@@ -4523,7 +4523,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*Auth); i {
case 0:
return &v.state
@@ -4535,7 +4535,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*TokenEntry); i {
case 0:
return &v.state
@@ -4547,7 +4547,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*LeaseOptions); i {
case 0:
return &v.state
@@ -4559,7 +4559,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[8].Exporter = func(v any, i int) any {
switch v := v.(*Secret); i {
case 0:
return &v.state
@@ -4571,7 +4571,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[9].Exporter = func(v any, i int) any {
switch v := v.(*Response); i {
case 0:
return &v.state
@@ -4583,7 +4583,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[10].Exporter = func(v any, i int) any {
switch v := v.(*ResponseWrapInfo); i {
case 0:
return &v.state
@@ -4595,7 +4595,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[11].Exporter = func(v any, i int) any {
switch v := v.(*RequestWrapInfo); i {
case 0:
return &v.state
@@ -4607,7 +4607,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[12].Exporter = func(v any, i int) any {
switch v := v.(*HandleRequestArgs); i {
case 0:
return &v.state
@@ -4619,7 +4619,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[13].Exporter = func(v any, i int) any {
switch v := v.(*HandleRequestReply); i {
case 0:
return &v.state
@@ -4631,7 +4631,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[14].Exporter = func(v any, i int) any {
switch v := v.(*InitializeArgs); i {
case 0:
return &v.state
@@ -4643,7 +4643,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[15].Exporter = func(v any, i int) any {
switch v := v.(*InitializeReply); i {
case 0:
return &v.state
@@ -4655,7 +4655,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[16].Exporter = func(v any, i int) any {
switch v := v.(*SpecialPathsReply); i {
case 0:
return &v.state
@@ -4667,7 +4667,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[17].Exporter = func(v any, i int) any {
switch v := v.(*HandleExistenceCheckArgs); i {
case 0:
return &v.state
@@ -4679,7 +4679,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[18].Exporter = func(v any, i int) any {
switch v := v.(*HandleExistenceCheckReply); i {
case 0:
return &v.state
@@ -4691,7 +4691,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[19].Exporter = func(v any, i int) any {
switch v := v.(*SetupArgs); i {
case 0:
return &v.state
@@ -4703,7 +4703,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[20].Exporter = func(v any, i int) any {
switch v := v.(*SetupReply); i {
case 0:
return &v.state
@@ -4715,7 +4715,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[21].Exporter = func(v any, i int) any {
switch v := v.(*TypeReply); i {
case 0:
return &v.state
@@ -4727,7 +4727,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[22].Exporter = func(v any, i int) any {
switch v := v.(*InvalidateKeyArgs); i {
case 0:
return &v.state
@@ -4739,7 +4739,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[23].Exporter = func(v any, i int) any {
switch v := v.(*StorageEntry); i {
case 0:
return &v.state
@@ -4751,7 +4751,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[24].Exporter = func(v any, i int) any {
switch v := v.(*StorageListArgs); i {
case 0:
return &v.state
@@ -4763,7 +4763,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[25].Exporter = func(v any, i int) any {
switch v := v.(*StorageListReply); i {
case 0:
return &v.state
@@ -4775,7 +4775,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[26].Exporter = func(v any, i int) any {
switch v := v.(*StorageGetArgs); i {
case 0:
return &v.state
@@ -4787,7 +4787,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[27].Exporter = func(v any, i int) any {
switch v := v.(*StorageGetReply); i {
case 0:
return &v.state
@@ -4799,7 +4799,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[28].Exporter = func(v any, i int) any {
switch v := v.(*StoragePutArgs); i {
case 0:
return &v.state
@@ -4811,7 +4811,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[29].Exporter = func(v any, i int) any {
switch v := v.(*StoragePutReply); i {
case 0:
return &v.state
@@ -4823,7 +4823,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[30].Exporter = func(v any, i int) any {
switch v := v.(*StorageDeleteArgs); i {
case 0:
return &v.state
@@ -4835,7 +4835,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[31].Exporter = func(v any, i int) any {
switch v := v.(*StorageDeleteReply); i {
case 0:
return &v.state
@@ -4847,7 +4847,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[32].Exporter = func(v any, i int) any {
switch v := v.(*TTLReply); i {
case 0:
return &v.state
@@ -4859,7 +4859,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[33].Exporter = func(v any, i int) any {
switch v := v.(*TaintedReply); i {
case 0:
return &v.state
@@ -4871,7 +4871,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[34].Exporter = func(v any, i int) any {
switch v := v.(*CachingDisabledReply); i {
case 0:
return &v.state
@@ -4883,7 +4883,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[35].Exporter = func(v any, i int) any {
switch v := v.(*ReplicationStateReply); i {
case 0:
return &v.state
@@ -4895,7 +4895,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[36].Exporter = func(v any, i int) any {
switch v := v.(*ResponseWrapDataArgs); i {
case 0:
return &v.state
@@ -4907,7 +4907,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[37].Exporter = func(v any, i int) any {
switch v := v.(*ResponseWrapDataReply); i {
case 0:
return &v.state
@@ -4919,7 +4919,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[38].Exporter = func(v any, i int) any {
switch v := v.(*MlockEnabledReply); i {
case 0:
return &v.state
@@ -4931,7 +4931,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[39].Exporter = func(v any, i int) any {
switch v := v.(*LocalMountReply); i {
case 0:
return &v.state
@@ -4943,7 +4943,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[40].Exporter = func(v any, i int) any {
switch v := v.(*EntityInfoArgs); i {
case 0:
return &v.state
@@ -4955,7 +4955,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[41].Exporter = func(v any, i int) any {
switch v := v.(*EntityInfoReply); i {
case 0:
return &v.state
@@ -4967,7 +4967,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[42].Exporter = func(v any, i int) any {
switch v := v.(*GroupsForEntityReply); i {
case 0:
return &v.state
@@ -4979,7 +4979,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[43].Exporter = func(v any, i int) any {
switch v := v.(*PluginEnvReply); i {
case 0:
return &v.state
@@ -4991,7 +4991,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[44].Exporter = func(v any, i int) any {
switch v := v.(*GeneratePasswordFromPolicyRequest); i {
case 0:
return &v.state
@@ -5003,7 +5003,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[45].Exporter = func(v any, i int) any {
switch v := v.(*GeneratePasswordFromPolicyReply); i {
case 0:
return &v.state
@@ -5015,7 +5015,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[46].Exporter = func(v any, i int) any {
switch v := v.(*ClusterInfoReply); i {
case 0:
return &v.state
@@ -5027,7 +5027,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[47].Exporter = func(v any, i int) any {
switch v := v.(*GenerateIdentityTokenRequest); i {
case 0:
return &v.state
@@ -5039,7 +5039,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[48].Exporter = func(v any, i int) any {
switch v := v.(*GenerateIdentityTokenResponse); i {
case 0:
return &v.state
@@ -5051,7 +5051,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[49].Exporter = func(v any, i int) any {
switch v := v.(*Connection); i {
case 0:
return &v.state
@@ -5063,7 +5063,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[50].Exporter = func(v any, i int) any {
switch v := v.(*ConnectionState); i {
case 0:
return &v.state
@@ -5075,7 +5075,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[51].Exporter = func(v any, i int) any {
switch v := v.(*Certificate); i {
case 0:
return &v.state
@@ -5087,7 +5087,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[52].Exporter = func(v any, i int) any {
switch v := v.(*CertificateChain); i {
case 0:
return &v.state
@@ -5099,7 +5099,7 @@ func file_sdk_plugin_pb_backend_proto_init() {
return nil
}
}
- file_sdk_plugin_pb_backend_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} {
+ file_sdk_plugin_pb_backend_proto_msgTypes[53].Exporter = func(v any, i int) any {
switch v := v.(*SendEventRequest); i {
case 0:
return &v.state
diff --git a/sdk/plugin/pb/backend_grpc.pb.go b/sdk/plugin/pb/backend_grpc.pb.go
index b0e96cd4a7..322e723f15 100644
--- a/sdk/plugin/pb/backend_grpc.pb.go
+++ b/sdk/plugin/pb/backend_grpc.pb.go
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
-// - protoc-gen-go-grpc v1.3.0
+// - protoc-gen-go-grpc v1.4.0
// - protoc (unknown)
// source: sdk/plugin/pb/backend.proto
@@ -18,8 +18,8 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
-// Requires gRPC-Go v1.32.0 or later.
-const _ = grpc.SupportPackageIsVersion7
+// Requires gRPC-Go v1.62.0 or later.
+const _ = grpc.SupportPackageIsVersion8
const (
Backend_HandleRequest_FullMethodName = "/pb.Backend/HandleRequest"
@@ -35,6 +35,10 @@ const (
// BackendClient is the client API for Backend service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+//
+// Backend is the interface that plugins must satisfy. The plugin should
+// implement the server for this service. Requests will first run the
+// HandleExistenceCheck rpc then run the HandleRequests rpc.
type BackendClient interface {
// HandleRequest is used to handle a request and generate a response.
// The plugins must check the operation type and handle appropriately.
@@ -82,8 +86,9 @@ func NewBackendClient(cc grpc.ClientConnInterface) BackendClient {
}
func (c *backendClient) HandleRequest(ctx context.Context, in *HandleRequestArgs, opts ...grpc.CallOption) (*HandleRequestReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(HandleRequestReply)
- err := c.cc.Invoke(ctx, Backend_HandleRequest_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_HandleRequest_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -91,8 +96,9 @@ func (c *backendClient) HandleRequest(ctx context.Context, in *HandleRequestArgs
}
func (c *backendClient) SpecialPaths(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*SpecialPathsReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SpecialPathsReply)
- err := c.cc.Invoke(ctx, Backend_SpecialPaths_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_SpecialPaths_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -100,8 +106,9 @@ func (c *backendClient) SpecialPaths(ctx context.Context, in *Empty, opts ...grp
}
func (c *backendClient) HandleExistenceCheck(ctx context.Context, in *HandleExistenceCheckArgs, opts ...grpc.CallOption) (*HandleExistenceCheckReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(HandleExistenceCheckReply)
- err := c.cc.Invoke(ctx, Backend_HandleExistenceCheck_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_HandleExistenceCheck_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -109,8 +116,9 @@ func (c *backendClient) HandleExistenceCheck(ctx context.Context, in *HandleExis
}
func (c *backendClient) Cleanup(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Backend_Cleanup_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_Cleanup_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -118,8 +126,9 @@ func (c *backendClient) Cleanup(ctx context.Context, in *Empty, opts ...grpc.Cal
}
func (c *backendClient) InvalidateKey(ctx context.Context, in *InvalidateKeyArgs, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Backend_InvalidateKey_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_InvalidateKey_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -127,8 +136,9 @@ func (c *backendClient) InvalidateKey(ctx context.Context, in *InvalidateKeyArgs
}
func (c *backendClient) Setup(ctx context.Context, in *SetupArgs, opts ...grpc.CallOption) (*SetupReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SetupReply)
- err := c.cc.Invoke(ctx, Backend_Setup_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_Setup_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -136,8 +146,9 @@ func (c *backendClient) Setup(ctx context.Context, in *SetupArgs, opts ...grpc.C
}
func (c *backendClient) Initialize(ctx context.Context, in *InitializeArgs, opts ...grpc.CallOption) (*InitializeReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(InitializeReply)
- err := c.cc.Invoke(ctx, Backend_Initialize_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_Initialize_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -145,8 +156,9 @@ func (c *backendClient) Initialize(ctx context.Context, in *InitializeArgs, opts
}
func (c *backendClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TypeReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TypeReply)
- err := c.cc.Invoke(ctx, Backend_Type_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Backend_Type_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -156,6 +168,10 @@ func (c *backendClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallOp
// BackendServer is the server API for Backend service.
// All implementations must embed UnimplementedBackendServer
// for forward compatibility
+//
+// Backend is the interface that plugins must satisfy. The plugin should
+// implement the server for this service. Requests will first run the
+// HandleExistenceCheck rpc then run the HandleRequests rpc.
type BackendServer interface {
// HandleRequest is used to handle a request and generate a response.
// The plugins must check the operation type and handle appropriately.
@@ -434,6 +450,9 @@ const (
// StorageClient is the client API for Storage service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+//
+// Storage is the way that plugins are able read/write data. Plugins should
+// implement the client for this service.
type StorageClient interface {
List(ctx context.Context, in *StorageListArgs, opts ...grpc.CallOption) (*StorageListReply, error)
Get(ctx context.Context, in *StorageGetArgs, opts ...grpc.CallOption) (*StorageGetReply, error)
@@ -450,8 +469,9 @@ func NewStorageClient(cc grpc.ClientConnInterface) StorageClient {
}
func (c *storageClient) List(ctx context.Context, in *StorageListArgs, opts ...grpc.CallOption) (*StorageListReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(StorageListReply)
- err := c.cc.Invoke(ctx, Storage_List_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Storage_List_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -459,8 +479,9 @@ func (c *storageClient) List(ctx context.Context, in *StorageListArgs, opts ...g
}
func (c *storageClient) Get(ctx context.Context, in *StorageGetArgs, opts ...grpc.CallOption) (*StorageGetReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(StorageGetReply)
- err := c.cc.Invoke(ctx, Storage_Get_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Storage_Get_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -468,8 +489,9 @@ func (c *storageClient) Get(ctx context.Context, in *StorageGetArgs, opts ...grp
}
func (c *storageClient) Put(ctx context.Context, in *StoragePutArgs, opts ...grpc.CallOption) (*StoragePutReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(StoragePutReply)
- err := c.cc.Invoke(ctx, Storage_Put_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Storage_Put_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -477,8 +499,9 @@ func (c *storageClient) Put(ctx context.Context, in *StoragePutArgs, opts ...grp
}
func (c *storageClient) Delete(ctx context.Context, in *StorageDeleteArgs, opts ...grpc.CallOption) (*StorageDeleteReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(StorageDeleteReply)
- err := c.cc.Invoke(ctx, Storage_Delete_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Storage_Delete_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -488,6 +511,9 @@ func (c *storageClient) Delete(ctx context.Context, in *StorageDeleteArgs, opts
// StorageServer is the server API for Storage service.
// All implementations must embed UnimplementedStorageServer
// for forward compatibility
+//
+// Storage is the way that plugins are able read/write data. Plugins should
+// implement the client for this service.
type StorageServer interface {
List(context.Context, *StorageListArgs) (*StorageListReply, error)
Get(context.Context, *StorageGetArgs) (*StorageGetReply, error)
@@ -645,6 +671,9 @@ const (
// SystemViewClient is the client API for SystemView service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+//
+// SystemView exposes system configuration information in a safe way for plugins
+// to consume. Plugins should implement the client for this service.
type SystemViewClient interface {
// DefaultLeaseTTL returns the default lease TTL set in Vault configuration
DefaultLeaseTTL(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TTLReply, error)
@@ -699,8 +728,9 @@ func NewSystemViewClient(cc grpc.ClientConnInterface) SystemViewClient {
}
func (c *systemViewClient) DefaultLeaseTTL(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TTLReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TTLReply)
- err := c.cc.Invoke(ctx, SystemView_DefaultLeaseTTL_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_DefaultLeaseTTL_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -708,8 +738,9 @@ func (c *systemViewClient) DefaultLeaseTTL(ctx context.Context, in *Empty, opts
}
func (c *systemViewClient) MaxLeaseTTL(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TTLReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TTLReply)
- err := c.cc.Invoke(ctx, SystemView_MaxLeaseTTL_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_MaxLeaseTTL_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -717,8 +748,9 @@ func (c *systemViewClient) MaxLeaseTTL(ctx context.Context, in *Empty, opts ...g
}
func (c *systemViewClient) Tainted(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TaintedReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TaintedReply)
- err := c.cc.Invoke(ctx, SystemView_Tainted_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_Tainted_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -726,8 +758,9 @@ func (c *systemViewClient) Tainted(ctx context.Context, in *Empty, opts ...grpc.
}
func (c *systemViewClient) CachingDisabled(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CachingDisabledReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CachingDisabledReply)
- err := c.cc.Invoke(ctx, SystemView_CachingDisabled_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_CachingDisabled_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -735,8 +768,9 @@ func (c *systemViewClient) CachingDisabled(ctx context.Context, in *Empty, opts
}
func (c *systemViewClient) ReplicationState(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ReplicationStateReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ReplicationStateReply)
- err := c.cc.Invoke(ctx, SystemView_ReplicationState_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_ReplicationState_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -744,8 +778,9 @@ func (c *systemViewClient) ReplicationState(ctx context.Context, in *Empty, opts
}
func (c *systemViewClient) ResponseWrapData(ctx context.Context, in *ResponseWrapDataArgs, opts ...grpc.CallOption) (*ResponseWrapDataReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ResponseWrapDataReply)
- err := c.cc.Invoke(ctx, SystemView_ResponseWrapData_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_ResponseWrapData_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -753,8 +788,9 @@ func (c *systemViewClient) ResponseWrapData(ctx context.Context, in *ResponseWra
}
func (c *systemViewClient) MlockEnabled(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*MlockEnabledReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MlockEnabledReply)
- err := c.cc.Invoke(ctx, SystemView_MlockEnabled_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_MlockEnabled_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -762,8 +798,9 @@ func (c *systemViewClient) MlockEnabled(ctx context.Context, in *Empty, opts ...
}
func (c *systemViewClient) LocalMount(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*LocalMountReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LocalMountReply)
- err := c.cc.Invoke(ctx, SystemView_LocalMount_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_LocalMount_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -771,8 +808,9 @@ func (c *systemViewClient) LocalMount(ctx context.Context, in *Empty, opts ...gr
}
func (c *systemViewClient) EntityInfo(ctx context.Context, in *EntityInfoArgs, opts ...grpc.CallOption) (*EntityInfoReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(EntityInfoReply)
- err := c.cc.Invoke(ctx, SystemView_EntityInfo_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_EntityInfo_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -780,8 +818,9 @@ func (c *systemViewClient) EntityInfo(ctx context.Context, in *EntityInfoArgs, o
}
func (c *systemViewClient) PluginEnv(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PluginEnvReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PluginEnvReply)
- err := c.cc.Invoke(ctx, SystemView_PluginEnv_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_PluginEnv_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -789,8 +828,9 @@ func (c *systemViewClient) PluginEnv(ctx context.Context, in *Empty, opts ...grp
}
func (c *systemViewClient) GroupsForEntity(ctx context.Context, in *EntityInfoArgs, opts ...grpc.CallOption) (*GroupsForEntityReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GroupsForEntityReply)
- err := c.cc.Invoke(ctx, SystemView_GroupsForEntity_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_GroupsForEntity_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -798,8 +838,9 @@ func (c *systemViewClient) GroupsForEntity(ctx context.Context, in *EntityInfoAr
}
func (c *systemViewClient) GeneratePasswordFromPolicy(ctx context.Context, in *GeneratePasswordFromPolicyRequest, opts ...grpc.CallOption) (*GeneratePasswordFromPolicyReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GeneratePasswordFromPolicyReply)
- err := c.cc.Invoke(ctx, SystemView_GeneratePasswordFromPolicy_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_GeneratePasswordFromPolicy_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -807,8 +848,9 @@ func (c *systemViewClient) GeneratePasswordFromPolicy(ctx context.Context, in *G
}
func (c *systemViewClient) ClusterInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ClusterInfoReply, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ClusterInfoReply)
- err := c.cc.Invoke(ctx, SystemView_ClusterInfo_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_ClusterInfo_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -816,8 +858,9 @@ func (c *systemViewClient) ClusterInfo(ctx context.Context, in *Empty, opts ...g
}
func (c *systemViewClient) GenerateIdentityToken(ctx context.Context, in *GenerateIdentityTokenRequest, opts ...grpc.CallOption) (*GenerateIdentityTokenResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GenerateIdentityTokenResponse)
- err := c.cc.Invoke(ctx, SystemView_GenerateIdentityToken_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, SystemView_GenerateIdentityToken_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -827,6 +870,9 @@ func (c *systemViewClient) GenerateIdentityToken(ctx context.Context, in *Genera
// SystemViewServer is the server API for SystemView service.
// All implementations must embed UnimplementedSystemViewServer
// for forward compatibility
+//
+// SystemView exposes system configuration information in a safe way for plugins
+// to consume. Plugins should implement the client for this service.
type SystemViewServer interface {
// DefaultLeaseTTL returns the default lease TTL set in Vault configuration
DefaultLeaseTTL(context.Context, *Empty) (*TTLReply, error)
@@ -1272,8 +1318,9 @@ func NewEventsClient(cc grpc.ClientConnInterface) EventsClient {
}
func (c *eventsClient) SendEvent(ctx context.Context, in *SendEventRequest, opts ...grpc.CallOption) (*Empty, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Empty)
- err := c.cc.Invoke(ctx, Events_SendEvent_FullMethodName, in, out, opts...)
+ err := c.cc.Invoke(ctx, Events_SendEvent_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
diff --git a/serviceregistration/consul/consul_service_registration.go b/serviceregistration/consul/consul_service_registration.go
index c59ed775cc..f3830121ae 100644
--- a/serviceregistration/consul/consul_service_registration.go
+++ b/serviceregistration/consul/consul_service_registration.go
@@ -5,6 +5,7 @@ package consul
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"math/rand"
@@ -73,6 +74,7 @@ type serviceRegistration struct {
redirectPort int64
serviceName string
serviceTags []string
+ serviceMeta map[string]string
serviceAddress *string
disableRegistration bool
checkTimeout time.Duration
@@ -229,6 +231,18 @@ func (c *serviceRegistration) merge(conf map[string]string) error {
c.logger.Debug("config service_tags set", "service_tags", tags)
}
+ // Get user-defined meta tags to attach to the registered service name
+ metaTags := map[string]string{}
+ if metaTagsJSON, ok := conf["service_meta"]; ok {
+ if err := json.Unmarshal([]byte(metaTagsJSON), &metaTags); err != nil {
+ return errors.New("service tags must be a dictionary of string keys and values")
+ }
+ }
+ metaTags["external-source"] = metaExternalSource
+ if c.logger.IsDebug() {
+ c.logger.Debug("config service_meta set", "service_meta", metaTags)
+ }
+
// Get the service-specific address to override the use of the HA redirect address
var serviceAddr *string
serviceAddrStr, ok := conf["service_address"]
@@ -294,6 +308,7 @@ func (c *serviceRegistration) merge(conf map[string]string) error {
c.config = consulConf
c.serviceName = service
c.serviceTags = strutil.ParseDedupAndSortStrings(tags, ",")
+ c.serviceMeta = metaTags
c.serviceAddress = serviceAddr
c.checkTimeout = checkTimeout
c.disableRegistration = disableRegistration
@@ -586,12 +601,10 @@ func (c *serviceRegistration) reconcileConsul() (serviceID string, err error) {
ID: serviceID,
Name: c.serviceName,
Tags: tags,
+ Meta: c.serviceMeta,
Port: int(c.redirectPort),
Address: serviceAddress,
EnableTagOverride: false,
- Meta: map[string]string{
- "external-source": metaExternalSource,
- },
}
checkStatus := api.HealthCritical
diff --git a/serviceregistration/consul/consul_service_registration_test.go b/serviceregistration/consul/consul_service_registration_test.go
index 8dcc3d6695..c728e721c1 100644
--- a/serviceregistration/consul/consul_service_registration_test.go
+++ b/serviceregistration/consul/consul_service_registration_test.go
@@ -492,6 +492,66 @@ func TestConsul_serviceTags(t *testing.T) {
}
}
+// TestConsul_ServiceMeta tests whether consul service meta registration works
+func TestConsul_ServiceMeta(t *testing.T) {
+ tests := []struct {
+ conf map[string]string
+ pass bool
+ expect map[string]string
+ }{
+ {
+ conf: map[string]string{},
+ pass: true,
+ expect: map[string]string{"external-source": "vault"},
+ },
+ {
+ conf: map[string]string{"service_meta": "true"},
+ pass: false,
+ expect: map[string]string{"external-source": "vault"},
+ },
+ {
+ conf: map[string]string{"service_meta": "{\"key\":\"value\"}"},
+ pass: true,
+ expect: map[string]string{"key": "value", "external-source": "vault"},
+ },
+ {
+ conf: map[string]string{"service_meta": "{\"external-source\":\"something-else\"}"},
+ pass: true,
+ expect: map[string]string{"external-source": "vault"},
+ },
+ }
+
+ for _, test := range tests {
+ logger := logging.NewVaultLogger(log.Debug)
+
+ shutdownCh := make(chan struct{})
+ defer func() {
+ close(shutdownCh)
+ }()
+ sr, err := NewServiceRegistration(test.conf, logger, sr.State{})
+ if !test.pass {
+ if err == nil {
+ t.Fatal("Expected Consul to fail with error")
+ }
+ continue
+ }
+
+ if err != nil && test.pass {
+ t.Fatalf("Expected Consul to initialize: %v", err)
+ }
+
+ c, ok := sr.(*serviceRegistration)
+ if !ok {
+ t.Fatalf("Expected serviceRegistration")
+ }
+
+ if !reflect.DeepEqual(c.serviceMeta, test.expect) {
+ t.Fatalf("Did not produce expected meta: wanted: %v, got %v", test.expect, c.serviceMeta)
+ }
+
+ }
+}
+
func TestConsul_setRedirectAddr(t *testing.T) {
tests := []struct {
addr string
diff --git a/tools/semgrep/ci/no-nil-check.yml b/tools/semgrep/ci/no-nil-check.yml
index 00c64c3641..a470f35c87 100644
--- a/tools/semgrep/ci/no-nil-check.yml
+++ b/tools/semgrep/ci/no-nil-check.yml
@@ -99,6 +99,13 @@ rules:
...
}
...
+ - pattern-not: |
+ $VAR, $ERR = NamespaceByID(...)
+ ...
+ if !a.includeInResponse(..., $VAR) {
+ ...
+ }
+ ...
message: missed nil check
languages:
- go
diff --git a/tools/stubmaker/main.go b/tools/stubmaker/main.go
index 187ca219e2..e298442053 100644
--- a/tools/stubmaker/main.go
+++ b/tools/stubmaker/main.go
@@ -50,15 +50,21 @@ func main() {
DetectDotGit: true,
})
if err != nil {
- fatal(err)
+ if err.Error() != "repository does not exist" {
+ fatal(err)
+ }
+ repo = nil
}
- wt, err := repo.Worktree()
- if err != nil {
- fatal(err)
- }
- if !isEnterprise(wt) {
- return
+ var wt *git.Worktree
+ if repo != nil {
+ wt, err = repo.Worktree()
+ if err != nil {
+ fatal(err)
+ }
+ if !isEnterprise(wt) {
+ return
+ }
}
// Read the file and figure out if we need to do anything.
@@ -88,26 +94,28 @@ func main() {
// We'd like to write the file, but first make sure that we're not going
// to blow away anyone's work or overwrite a file already in git.
- head, err := repo.Head()
- if err != nil {
- fatal(err)
- }
- obj, err := repo.Object(plumbing.AnyObject, head.Hash())
- if err != nil {
- fatal(err)
- }
+ if repo != nil {
+ head, err := repo.Head()
+ if err != nil {
+ fatal(err)
+ }
+ obj, err := repo.Object(plumbing.AnyObject, head.Hash())
+ if err != nil {
+ fatal(err)
+ }
- st, err := wt.Status()
- if err != nil {
- fatal(err)
- }
+ st, err := wt.Status()
+ if err != nil {
+ fatal(err)
+ }
- tracked, err := inGit(wt, st, obj, outputFile)
- if err != nil {
- fatal(err)
- }
- if tracked {
- fatal(fmt.Errorf("output file %s exists in git, not overwriting", outputFile))
+ tracked, err := inGit(wt, st, obj, outputFile)
+ if err != nil {
+ fatal(err)
+ }
+ if tracked {
+ fatal(fmt.Errorf("output file %s exists in git, not overwriting", outputFile))
+ }
}
// Now we can finally write the file
diff --git a/tools/tools.sh b/tools/tools.sh
index cdfa6be73b..d42f8db4ee 100755
--- a/tools/tools.sh
+++ b/tools/tools.sh
@@ -34,7 +34,8 @@ check_tool() {
install_external() {
local tools
# If you update this please update check_external below as well as our external tools
- # install action ./github/actions/install-external-tools.yml
+ # install action .github/actions/install-external-tools/action.yml
+ #
tools=(
github.com/bufbuild/buf/cmd/buf@v1.25.0
github.com/favadi/protoc-go-inject-tag@latest
@@ -43,7 +44,7 @@ install_external() {
github.com/rinchsan/gosimports/cmd/gosimports@latest
golang.org/x/tools/cmd/goimports@latest
google.golang.org/protobuf/cmd/protoc-gen-go@latest
- google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
+ google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.4.0
gotest.tools/gotestsum@latest
honnef.co/go/tools/cmd/staticcheck@latest
mvdan.cc/gofumpt@latest
diff --git a/ui/.gitignore b/ui/.gitignore
index 99318284a7..639f011c1d 100644
--- a/ui/.gitignore
+++ b/ui/.gitignore
@@ -15,6 +15,7 @@
/testem.log
/yarn-error.log
package-lock.json
+/docs/components/*
# ember-try
/.node_modules.ember-try/
diff --git a/ui/.yarnrc b/ui/.yarnrc
deleted file mode 100644
index 65dab0366d..0000000000
--- a/ui/.yarnrc
+++ /dev/null
@@ -1,6 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-lastUpdateCheck 1664829239911
-yarn-path ".yarn/releases/yarn-1.22.19.js"
diff --git a/ui/app/adapters/aws-credential.js b/ui/app/adapters/aws-credential.js
index 948b91a6cb..4cba977295 100644
--- a/ui/app/adapters/aws-credential.js
+++ b/ui/app/adapters/aws-credential.js
@@ -16,7 +16,7 @@ export default ApplicationAdapter.extend({
if (roleType === 'iam_user') {
method = 'GET';
} else {
- if (ttl !== undefined) {
+ if (ttl) {
data.ttl = ttl;
}
if (roleType === 'assumed_role' && roleArn) {
diff --git a/ui/app/adapters/aws/lease-config.js b/ui/app/adapters/aws/lease-config.js
new file mode 100644
index 0000000000..b7dac0df84
--- /dev/null
+++ b/ui/app/adapters/aws/lease-config.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import ApplicationAdapter from '../application';
+import { encodePath } from 'vault/utils/path-encoding-helpers';
+
+export default class AwsRootConfig extends ApplicationAdapter {
+ namespace = 'v1';
+ // For now this is only being used on the vault.cluster.secrets.backend.configuration route. This is a read-only route.
+ // Eventually, this will be used to create the lease config for the AWS secret backend, replacing the requests located on the secret-engine adapter.
+ queryRecord(store, type, query) {
+ const { backend } = query;
+ return this.ajax(`${this.buildURL()}/${encodePath(backend)}/config/lease`, 'GET').then((resp) => {
+ resp.id = backend;
+ return resp;
+ });
+ }
+}
diff --git a/ui/app/adapters/aws/root-config.js b/ui/app/adapters/aws/root-config.js
new file mode 100644
index 0000000000..ae141a47c9
--- /dev/null
+++ b/ui/app/adapters/aws/root-config.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import ApplicationAdapter from '../application';
+import { encodePath } from 'vault/utils/path-encoding-helpers';
+
+export default class AwsRootConfig extends ApplicationAdapter {
+ namespace = 'v1';
+ // For now this is only being used on the vault.cluster.secrets.backend.configuration route. This is a read-only route.
+ // Eventually, this will be used to create the root config for the AWS secret backend, replacing the requests located on the secret-engine adapter.
+ queryRecord(store, type, query) {
+ const { backend } = query;
+ return this.ajax(`${this.buildURL()}/${encodePath(backend)}/config/root`, 'GET').then((resp) => {
+ resp.id = backend;
+ return resp;
+ });
+ }
+}
diff --git a/ui/app/adapters/clients/activity.js b/ui/app/adapters/clients/activity.js
index 67c4a74786..7a85c9505d 100644
--- a/ui/app/adapters/clients/activity.js
+++ b/ui/app/adapters/clients/activity.js
@@ -3,34 +3,79 @@
* SPDX-License-Identifier: BUSL-1.1
*/
+import queryParamString from 'vault/utils/query-param-string';
import ApplicationAdapter from '../application';
import { formatDateObject } from 'core/utils/client-count-utils';
+import { debug } from '@ember/debug';
export default class ActivityAdapter extends ApplicationAdapter {
+ formatTimeParam(dateObj, isEnd = false) {
+ let formatted;
+ if (dateObj) {
+ try {
+ const iso = dateObj.timestamp || formatDateObject(dateObj, isEnd);
+ formatted = iso;
+ } catch (e) {
+ // carry on
+ }
+ }
+ return formatted;
+ }
// javascript localizes new Date() objects but all activity log data is stored in UTC
// create date object from user's input using Date.UTC() then send to backend as unix
// time params from the backend are formatted as a zulu timestamp
formatQueryParams(queryParams) {
- if (queryParams?.current_billing_period) {
- // { current_billing_period: true } automatically queries the activity log
- // from the builtin license start timestamp to the current month
- return queryParams;
+ const query = {};
+ const start = this.formatTimeParam(queryParams?.start_time);
+ const end = this.formatTimeParam(queryParams?.end_time, true);
+ if (start) {
+ query.start_time = start;
}
- let { start_time, end_time } = queryParams;
- start_time = start_time.timestamp || formatDateObject(start_time);
- end_time = end_time.timestamp || formatDateObject(end_time, true);
- return { start_time, end_time };
+ if (end) {
+ query.end_time = end;
+ }
+ return query;
}
queryRecord(store, type, query) {
const url = `${this.buildURL()}/internal/counters/activity`;
const queryParams = this.formatQueryParams(query);
- if (queryParams) {
- return this.ajax(url, 'GET', { data: queryParams }).then((resp) => {
- const response = resp || {};
- response.id = response.request_id || 'no-data';
- return response;
- });
+ return this.ajax(url, 'GET', { data: queryParams }).then((resp) => {
+ const response = resp || {};
+ response.id = response.request_id || 'no-data';
+ return response;
+ });
+ }
+
+ async exportData(query) {
+ const url = `${this.buildURL()}/internal/counters/activity/export${queryParamString({
+ format: query?.format || 'csv',
+ start_time: query?.start_time ?? undefined,
+ end_time: query?.end_time ?? undefined,
+ })}`;
+ let errorMsg;
+ try {
+ const options = query?.namespace ? { namespace: query.namespace } : {};
+ const resp = await this.rawRequest(url, 'GET', options);
+ if (resp.status === 200) {
+ return resp.blob();
+ }
+ // If it's an empty response (eg 204), there's no data so return an error
+ errorMsg = 'no data to export in provided time range.';
+ } catch (e) {
+ const { errors } = await e.json();
+ errorMsg = errors?.join('. ');
+ }
+ if (errorMsg) {
+ throw new Error(errorMsg);
}
}
+
+ urlForFindRecord(id) {
+ // debug reminder so model is stored in Ember data with the same id for consistency
+ if (id !== 'clients/activity') {
+ debug(`findRecord('clients/activity') should pass 'clients/activity' as the id, you passed: '${id}'`);
+ }
+ return `${this.buildURL()}/internal/counters/activity`;
+ }
}
diff --git a/ui/app/adapters/kv/data.js b/ui/app/adapters/kv/data.js
index 2b68acd5a7..b43beefd41 100644
--- a/ui/app/adapters/kv/data.js
+++ b/ui/app/adapters/kv/data.js
@@ -4,7 +4,14 @@
*/
import ApplicationAdapter from '../application';
-import { kvDataPath, kvDeletePath, kvDestroyPath, kvMetadataPath, kvUndeletePath } from 'vault/utils/kv-path';
+import {
+ kvDataPath,
+ kvDeletePath,
+ kvDestroyPath,
+ kvMetadataPath,
+ kvSubkeysPath,
+ kvUndeletePath,
+} from 'vault/utils/kv-path';
import { assert } from '@ember/debug';
import ControlGroupError from 'vault/lib/control-group-error';
@@ -31,12 +38,30 @@ export default class KvDataAdapter extends ApplicationAdapter {
});
}
+ fetchSubkeys(backend, path, query) {
+ const url = this._url(kvSubkeysPath(backend, path, query));
+ // TODO subkeys response handles deleted records the same as queryRecord and returns a 404
+ // extrapolate error handling logic from queryRecord and share between these two methods
+ return this.ajax(url, 'GET').then((resp) => resp.data);
+ }
+
fetchWrapInfo(query) {
const { backend, path, version, wrapTTL } = query;
const id = kvDataPath(backend, path, version);
return this.ajax(this._url(id), 'GET', { wrapTTL }).then((resp) => resp.wrap_info);
}
+ // patching a secret happens without retrieving the ember data model
+ // so we use a custom method instead of updateRecord
+ patchSecret(backend, path, patchData, version) {
+ const url = this._url(kvDataPath(backend, path));
+ const data = {
+ options: { cas: version },
+ data: patchData,
+ };
+ return this.ajax(url, 'PATCH', { data });
+ }
+
queryRecord(store, type, query) {
const { backend, path, version } = query;
// ID is the full path for the data (including version)
diff --git a/ui/app/adapters/ssh/ca-config.js b/ui/app/adapters/ssh/ca-config.js
new file mode 100644
index 0000000000..1f89badf51
--- /dev/null
+++ b/ui/app/adapters/ssh/ca-config.js
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import ApplicationAdapter from '../application';
+import { encodePath } from 'vault/utils/path-encoding-helpers';
+
+export default class SshCaConfig extends ApplicationAdapter {
+ namespace = 'v1';
+ // For now this is only being used on the vault.cluster.secrets.backend.configuration route. This is a read-only route.
+ // Eventually, this will be used to create the ca config for the SSH secret backend, replacing the requests located on the secret-engine adapter.
+ queryRecord(store, type, query) {
+ const { backend } = query;
+ return this.ajax(`${this.buildURL()}/${encodePath(backend)}/config/ca`, 'GET').then((resp) => {
+ resp.id = backend;
+ return resp;
+ });
+ }
+}
diff --git a/ui/app/components/app-footer.hbs b/ui/app/components/app-footer.hbs
index 477807626a..00bbee1848 100644
--- a/ui/app/components/app-footer.hbs
+++ b/ui/app/components/app-footer.hbs
@@ -28,4 +28,16 @@
Documentation
+
+ {{#if this.isDevelopment}}
+
+ {{/if}}
+
\ No newline at end of file
diff --git a/ui/app/components/auth-form.js b/ui/app/components/auth-form.js
index cf7e93102c..d87161b290 100644
--- a/ui/app/components/auth-form.js
+++ b/ui/app/components/auth-form.js
@@ -3,7 +3,6 @@
* SPDX-License-Identifier: BUSL-1.1
*/
-import Ember from 'ember';
import { next } from '@ember/runloop';
import { service } from '@ember/service';
import { match, or } from '@ember/object/computed';
@@ -11,27 +10,25 @@ import { dasherize } from '@ember/string';
import Component from '@ember/component';
import { computed } from '@ember/object';
import { allSupportedAuthBackends, supportedAuthBackends } from 'vault/helpers/supported-auth-backends';
-import { task, timeout } from 'ember-concurrency';
+import { task } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
import { v4 as uuidv4 } from 'uuid';
/**
* @module AuthForm
- * The `AuthForm` is used to sign users into Vault.
+ * The AuthForm displays the form used to sign users into Vault and passes input data to the Auth::Page component which handles authentication
*
- * @example ```js
- * // All properties are passed in via query params.
- * ```
+ * @example
+ *
*
- * @param {string} wrappedToken - The auth method that is currently selected in the dropdown.
- * @param {object} cluster - The auth method that is currently selected in the dropdown. This corresponds to an Ember Model.
+ * @param {string} wrappedToken - Token that can be used to login if added directly to the URL via the "wrapped_token" query param
+ * @param {object} cluster - The cluster model which contains information such as cluster id, name and boolean for if the cluster is in standby
* @param {string} namespace- The currently active namespace.
* @param {string} selectedAuth - The auth method that is currently selected in the dropdown.
- * @param {function} onSuccess - Fired on auth success.
- * @param {function} [setOktaNumberChallenge] - Sets whether we are waiting for okta number challenge to be used to sign in.
- * @param {boolean} [waitingForOktaNumberChallenge=false] - Determines if we are waiting for the Okta Number Challenge to sign in.
- * @param {function} [setCancellingAuth] - Sets whether we are cancelling or not the login authentication for Okta Number Challenge.
- * @param {boolean} [cancelAuthForOktaNumberChallenge=false] - Determines if we are cancelling the login authentication for the Okta Number Challenge.
+ * @param {function} performAuth - Callback that triggers authenticate task in the parent, backend type (i.e. 'okta') and relevant auth data are passed as args
+ * @param {string} error - Error returned by the parent authenticate task, message is generated by the auth service handleError method
+ * @param {boolean} authIsRunning - Boolean that relays whether or not the authenticate task is running
+ * @param {boolean} delayIsIdle - Boolean that relays whether or not the delayAuthMessageReminder parent task is idle
*/
const DEFAULTS = {
@@ -49,7 +46,7 @@ export default Component.extend(DEFAULTS, {
csp: service('csp-event'),
version: service(),
- // passed in via a query param
+ // set by query params, passed from parent Auth::Page component
selectedAuth: null,
methods: null,
cluster: null,
@@ -58,9 +55,6 @@ export default Component.extend(DEFAULTS, {
// internal
oldNamespace: null,
- // number answer for okta number challenge if applicable
- oktaNumberChallengeAnswer: null,
-
authMethods: computed('version.isEnterprise', function () {
return this.version.isEnterprise ? allSupportedAuthBackends() : supportedAuthBackends();
}),
@@ -74,18 +68,13 @@ export default Component.extend(DEFAULTS, {
namespace: ns,
selectedAuth: newMethod,
oldSelectedAuth: oldMethod,
- cancelAuthForOktaNumberChallenge: cancelAuth,
} = this;
- // if we are cancelling the login then we reset the number challenge answer and cancel the current authenticate and polling tasks
- if (cancelAuth) {
- this.set('oktaNumberChallengeAnswer', null);
- this.authenticate.cancelAll();
- this.pollForOktaNumberChallenge.cancelAll();
- }
next(() => {
if (!token && (oldNS === null || oldNS !== ns)) {
this.fetchMethods.perform();
}
+ // don't set any variables if the component is being torn down
+ if (this.isDestroyed || this.isDestroying) return;
this.set('oldNamespace', ns);
// we only want to trigger this once
if (token && !oldToken) {
@@ -235,65 +224,7 @@ export default Component.extend(DEFAULTS, {
})
),
- showLoading: or('isLoading', 'authenticate.isRunning', 'fetchMethods.isRunning', 'unwrapToken.isRunning'),
-
- authenticate: task(
- waitFor(function* (backendType, data) {
- const {
- selectedAuth,
- cluster: { id: clusterId },
- } = this;
- try {
- if (backendType === 'okta') {
- this.pollForOktaNumberChallenge.perform(data.nonce, data.path);
- } else {
- this.delayAuthMessageReminder.perform();
- }
- const authResponse = yield this.auth.authenticate({
- clusterId,
- backend: backendType,
- data,
- selectedAuth,
- });
- this.onSuccess(authResponse, backendType, data);
- } catch (e) {
- this.set('isLoading', false);
- if (!this.auth.mfaError) {
- this.set('error', `Authentication failed: ${this.auth.handleError(e)}`);
- }
- }
- })
- ),
-
- pollForOktaNumberChallenge: task(function* (nonce, mount) {
- // yield for 1s to wait to see if there is a login error before polling
- yield timeout(1000);
- if (this.error) {
- return;
- }
- let response = null;
- this.setOktaNumberChallenge(true);
- this.setCancellingAuth(false);
- // keep polling /auth/okta/verify/:nonce API every 1s until a response is given with the correct number for the Okta Number Challenge
- while (response === null) {
- // when testing, the polling loop causes promises to be rejected making acceptance tests fail
- // so disable the poll in tests
- if (Ember.testing) {
- return;
- }
- yield timeout(1000);
- response = yield this.auth.getOktaNumberChallengeAnswer(nonce, mount);
- }
- this.set('oktaNumberChallengeAnswer', response);
- }),
-
- delayAuthMessageReminder: task(function* () {
- if (Ember.testing) {
- yield timeout(0);
- } else {
- yield timeout(5000);
- }
- }),
+ showLoading: or('isLoading', 'authIsRunning', 'fetchMethods.isRunning', 'unwrapToken.isRunning'),
actions: {
doSubmit(passedData, event, token) {
@@ -326,7 +257,7 @@ export default Component.extend(DEFAULTS, {
data.path = 'okta';
}
}
- return this.authenticate.unlinked().perform(backend.type, data);
+ return this.performAuth(backend.type, data);
},
handleError(e) {
this.setProperties({
@@ -334,9 +265,5 @@ export default Component.extend(DEFAULTS, {
error: e ? this.auth.handleError(e) : null,
});
},
- returnToLoginFromOktaNumberChallenge() {
- this.setOktaNumberChallenge(false);
- this.set('oktaNumberChallengeAnswer', null);
- },
},
});
diff --git a/ui/app/components/auth-jwt.js b/ui/app/components/auth-jwt.js
index a373ee86cf..610b6d0993 100644
--- a/ui/app/components/auth-jwt.js
+++ b/ui/app/components/auth-jwt.js
@@ -2,14 +2,13 @@
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
-
+import Ember from 'ember';
import { service } from '@ember/service';
// ARG NOTE: Once you remove outer-html after glimmerizing you can remove the outer-html component
import Component from './outer-html';
import { task, timeout, waitForEvent } from 'ember-concurrency';
import { debounce } from '@ember/runloop';
-const WAIT_TIME = 500;
const ERROR_WINDOW_CLOSED =
'The provider window was closed before authentication was complete. Your web browser may have blocked or closed a pop-up window. Please check your settings and click Sign In to try again.';
const ERROR_MISSING_PARAMS =
@@ -109,6 +108,8 @@ export default Component.extend({
watchPopup: task(function* (oidcWindow) {
while (true) {
+ const WAIT_TIME = Ember.testing ? 50 : 500;
+
yield timeout(WAIT_TIME);
if (!oidcWindow || oidcWindow.closed) {
return this.handleOIDCError(ERROR_WINDOW_CLOSED);
diff --git a/ui/app/components/auth/login-form.hbs b/ui/app/components/auth/login-form.hbs
new file mode 100644
index 0000000000..e8b4d0c2e2
--- /dev/null
+++ b/ui/app/components/auth/login-form.hbs
@@ -0,0 +1,23 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+~}}
+
+{{#if this.waitingForOktaNumberChallenge}}
+
+{{else}}
+
+{{/if}}
\ No newline at end of file
diff --git a/ui/app/components/auth/login-form.js b/ui/app/components/auth/login-form.js
new file mode 100644
index 0000000000..e3551ce68d
--- /dev/null
+++ b/ui/app/components/auth/login-form.js
@@ -0,0 +1,108 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Component from '@glimmer/component';
+import Ember from 'ember';
+import { service } from '@ember/service';
+import { task, timeout } from 'ember-concurrency';
+import { waitFor } from '@ember/test-waiters';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
+
+/**
+ * @module AuthLoginForm
+ * The Auth::LoginForm wraps OktaNumberChallenge and AuthForm to manage the login flow and is responsible for calling the authenticate method
+ *
+ * @example
+ *
+ *
+ * @param {string} wrappedToken - Query param value of a wrapped token that can be used to login when added directly to the URL via the "wrapped_token" query param
+ * @param {object} cluster - The route model which is the ember data cluster model. contains information such as cluster id, name and boolean for if the cluster is in standby
+ * @param {string} namespace- Namespace query param, passed to AuthForm and set by typing in namespace input or URL
+ * @param {string} selectedAuth - The auth method selected in the dropdown, passed to auth service's authenticate method
+ * @param {function} onSuccess - Callback that fires the "onAuthResponse" action in the auth controller and handles transitioning after success
+ */
+
+export default class AuthLoginFormComponent extends Component {
+ @service auth;
+
+ @tracked authError = null;
+ @tracked oktaNumberChallengeAnswer = '';
+ @tracked waitingForOktaNumberChallenge = false;
+
+ @action
+ performAuth(backendType, data) {
+ this.authenticate.unlinked().perform(backendType, data);
+ }
+
+ @task
+ @waitFor
+ *delayAuthMessageReminder() {
+ if (Ember.testing) {
+ yield timeout(0);
+ } else {
+ yield timeout(5000);
+ }
+ }
+
+ @task
+ @waitFor
+ *authenticate(backendType, data) {
+ const {
+ selectedAuth,
+ cluster: { id: clusterId },
+ } = this.args;
+ try {
+ if (backendType === 'okta') {
+ this.pollForOktaNumberChallenge.perform(data.nonce, data.path);
+ } else {
+ this.delayAuthMessageReminder.perform();
+ }
+ const authResponse = yield this.auth.authenticate({
+ clusterId,
+ backend: backendType,
+ data,
+ selectedAuth,
+ });
+
+ this.args.onSuccess(authResponse, backendType, data);
+ } catch (e) {
+ if (!this.auth.mfaError) {
+ this.authError = `Authentication failed: ${this.auth.handleError(e)}`;
+ }
+ }
+ }
+
+ @task
+ @waitFor
+ *pollForOktaNumberChallenge(nonce, mount) {
+ // yield for 1s to wait to see if there is a login error before polling
+ yield timeout(1000);
+ if (this.authError) return;
+
+ this.waitingForOktaNumberChallenge = true;
+ // keep polling /auth/okta/verify/:nonce API every 1s until response returns with correct_number
+ let response = null;
+ while (response === null) {
+ // disable polling for tests otherwise promises reject and acceptance tests fail
+ if (Ember.testing) return;
+
+ yield timeout(1000);
+ response = yield this.auth.getOktaNumberChallengeAnswer(nonce, mount);
+ }
+ // display correct number so user can select on personal MFA device
+ this.oktaNumberChallengeAnswer = response;
+ }
+
+ @action
+ onCancel() {
+ // reset variables and stop polling tasks if canceling login
+ this.authError = null;
+ this.oktaNumberChallengeAnswer = null;
+ this.waitingForOktaNumberChallenge = false;
+ this.authenticate.cancelAll();
+ this.pollForOktaNumberChallenge.cancelAll();
+ }
+}
diff --git a/ui/app/components/auth/page.hbs b/ui/app/components/auth/page.hbs
new file mode 100644
index 0000000000..046a9655d9
--- /dev/null
+++ b/ui/app/components/auth/page.hbs
@@ -0,0 +1,119 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+~}}
+
+{{#if this.mfaErrors}}
+
+
+
+
+
+{{else}}
+
+ <:header>
+ {{#if @oidcProviderQueryParam}}
+
+
+
+ {{else}}
+
+
+ {{#if this.mfaAuthData}}
+
+ {{/if}}
+
+ {{if this.mfaAuthData "Authenticate" "Sign in to Vault"}}
+
+
+ {{/if}}
+
+
+ <:subHeader>
+ {{#if (has-feature "Namespaces")}}
+ {{#unless this.mfaAuthData}}
+
+
+
+ Namespace
+
+ {{#if this.flags.hvdManagedNamespaceRoot}}
+
+ /{{this.flags.hvdManagedNamespaceRoot}}
+
+ {{/if}}
+
+
+
+ {{/unless}}
+ {{/if}}
+
+
+ <:content>
+ {{#if this.mfaAuthData}}
+
+ {{else}}
+
+ {{/if}}
+
+
+ <:footer>
+
+
+ {{#if @oidcProviderQueryParam}}
+ Once you log in, you will be redirected back to your application. If you require login credentials, contact your
+ administrator.
+ {{else}}
+ Contact your administrator for login credentials.
+ {{/if}}
+
+
+
+
+{{/if}}
\ No newline at end of file
diff --git a/ui/app/components/auth/page.js b/ui/app/components/auth/page.js
new file mode 100644
index 0000000000..85dc29c207
--- /dev/null
+++ b/ui/app/components/auth/page.js
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Component from '@glimmer/component';
+import { service } from '@ember/service';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
+
+/**
+ * @module AuthPage
+ * The Auth::Page wraps OktaNumberChallenge and AuthForm to manage the login flow and is responsible for calling the authenticate method
+ *
+ * @example
+ *
+ *
+ * @param {string} authMethodQueryParam - auth method type to login with, updated by selecting an auth method from the dropdown
+ * @param {string} namespaceQueryParam - namespace to login with, updated by typing in to the namespace input
+ * @param {string} oidcProviderQueryParam - oidc provider query param, set in url as "?o=someprovider"
+ * @param {function} onAuthSuccess - callback task in controller that receives the auth response (after MFA, if enabled) when login is successful
+ * @param {function} onNamespaceUpdate - callback task that passes user input to the controller to update the login namespace in the url query params
+ * @param {string} wrappedToken - passed down to the AuthForm component and can be used to login if added directly to the URL via the "wrapped_token" query param
+ * */
+
+export default class AuthPage extends Component {
+ @service flags;
+
+ @tracked mfaErrors;
+ @tracked mfaAuthData;
+
+ get namespaceInput() {
+ const namespaceQP = this.args.namespaceQueryParam;
+ if (this.flags.hvdManagedNamespaceRoot) {
+ // When managed, the user isn't allowed to edit the prefix `admin/` for their nested namespace
+ const split = namespaceQP.split('/');
+ if (split.length > 1) {
+ split.shift();
+ return `/${split.join('/')}`;
+ }
+ return '';
+ }
+ return namespaceQP;
+ }
+
+ @action
+ handleNamespaceUpdate(event) {
+ this.args.onNamespaceUpdate(event.target.value);
+ }
+
+ @action
+ onAuthResponse(authResponse, backend, data) {
+ const { mfa_requirement } = authResponse;
+ // if an mfa requirement exists further action is required
+ if (mfa_requirement) {
+ this.mfaAuthData = { mfa_requirement, backend, data };
+ } else {
+ this.args.onAuthSuccess(authResponse);
+ }
+ }
+
+ @action
+ onMfaSuccess(authResponse) {
+ this.args.onAuthSuccess(authResponse);
+ }
+
+ @action
+ onMfaErrorDismiss() {
+ this.mfaAuthData = null;
+ this.mfaErrors = null;
+ }
+}
diff --git a/ui/app/components/calendar-widget.js b/ui/app/components/calendar-widget.js
deleted file mode 100644
index 804c9af196..0000000000
--- a/ui/app/components/calendar-widget.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: BUSL-1.1
- */
-
-import Component from '@glimmer/component';
-import { action } from '@ember/object';
-import { tracked } from '@glimmer/tracking';
-import { ARRAY_OF_MONTHS, parseAPITimestamp } from 'core/utils/date-formatters';
-import { addYears, isSameYear, subYears } from 'date-fns';
-import timestamp from 'core/utils/timestamp';
-/**
- * @module CalendarWidget
- * CalendarWidget component is used in the client counts dashboard to select a month/year to query the /activity endpoint.
- * The component returns an object with selected date info, example: { dateType: 'endDate', monthIdx: 0, monthName: 'January', year: 2022 }
- *
- * @example
- * ```js
- *
- *
- * @param {string} startTimestamp - ISO timestamp string of the calendar widget's start time, displays in dropdown trigger
- * @param {string} endTimestamp - ISO timestamp string for the calendar widget's end time, displays in dropdown trigger
- * @param {function} selectMonth - callback function from parent - fires when selecting a month or clicking "Current billing period"
- * />
- * ```
- */
-export default class CalendarWidget extends Component {
- currentDate = timestamp.now();
- @tracked calendarDisplayDate = this.currentDate; // init to current date, updates when user clicks on calendar chevrons
- @tracked showCalendar = false;
-
- // both date getters return a date object
- get startDate() {
- return parseAPITimestamp(this.args.startTimestamp);
- }
- get endDate() {
- return parseAPITimestamp(this.args.endTimestamp);
- }
- get displayYear() {
- return this.calendarDisplayDate.getFullYear();
- }
- get disableFutureYear() {
- return isSameYear(this.calendarDisplayDate, this.currentDate);
- }
- get disablePastYear() {
- // calendar widget should only go as far back as the passed in start time
- return isSameYear(this.calendarDisplayDate, this.startDate);
- }
- get widgetMonths() {
- const startYear = this.startDate.getFullYear();
- const startMonthIdx = this.startDate.getMonth();
- return ARRAY_OF_MONTHS.map((month, index) => {
- let readonly = false;
-
- // if widget is showing same year as @startTimestamp year, disable if month is before start month
- if (startYear === this.displayYear && index < startMonthIdx) {
- readonly = true;
- }
-
- // if widget showing current year, disable if month is later than current month
- if (this.displayYear === this.currentDate.getFullYear() && index > this.currentDate.getMonth()) {
- readonly = true;
- }
- return {
- index,
- year: this.displayYear,
- name: month,
- readonly,
- };
- });
- }
-
- @action
- addYear() {
- this.calendarDisplayDate = addYears(this.calendarDisplayDate, 1);
- }
-
- @action
- subYear() {
- this.calendarDisplayDate = subYears(this.calendarDisplayDate, 1);
- }
-
- @action
- toggleShowCalendar() {
- this.showCalendar = !this.showCalendar;
- this.calendarDisplayDate = this.endDate;
- }
-
- @action
- handleDateShortcut(dropdown, { target }) {
- this.args.selectMonth({ dateType: target.name }); // send clicked shortcut to parent callback
- this.showCalendar = false;
- dropdown.close();
- }
-
- @action
- selectMonth(month, dropdown) {
- const { index, year, name } = month;
- this.toggleShowCalendar();
- this.args.selectMonth({ monthIdx: index, monthName: name, year, dateType: 'endDate' });
- dropdown.close();
- }
-}
diff --git a/ui/app/components/clients/activity.ts b/ui/app/components/clients/activity.ts
index f22134b94a..10a419b2e9 100644
--- a/ui/app/components/clients/activity.ts
+++ b/ui/app/components/clients/activity.ts
@@ -7,7 +7,7 @@
// contains getters that filter and extract data from activity model for use in charts
import Component from '@glimmer/component';
-import { isSameMonth, fromUnixTime } from 'date-fns';
+import { isSameMonth } from 'date-fns';
import { parseAPITimestamp } from 'core/utils/date-formatters';
import { calculateAverage } from 'vault/utils/chart-helpers';
import { filterVersionHistory, hasMountsKey, hasNamespacesKey } from 'core/utils/client-count-utils';
@@ -24,8 +24,8 @@ import type {
interface Args {
activity: ClientsActivityModel;
versionHistory: ClientsVersionHistoryModel[];
- startTimestamp: number;
- endTimestamp: number;
+ startTimestamp: string;
+ endTimestamp: string;
namespace: string;
mountPath: string;
}
@@ -40,14 +40,6 @@ export default class ClientsActivityComponent extends Component {
return calculateAverage(data, key);
};
- get startTimeISO() {
- return fromUnixTime(this.args.startTimestamp).toISOString();
- }
-
- get endTimeISO() {
- return fromUnixTime(this.args.endTimestamp).toISOString();
- }
-
get byMonthActivityData() {
const { activity, namespace } = this.args;
return namespace ? this.filteredActivityByMonth : activity.byMonth;
diff --git a/ui/app/components/clients/attribution.hbs b/ui/app/components/clients/attribution.hbs
index b28def4803..311ba5dd9e 100644
--- a/ui/app/components/clients/attribution.hbs
+++ b/ui/app/components/clients/attribution.hbs
@@ -14,13 +14,44 @@
{{this.chartText.description}}
@@ -79,68 +110,4 @@
{{date-format @responseTimestamp "MMM d yyyy, h:mm:ss aaa" withTimeZone=true}}
{{/if}}
-
-
-{{! MODAL FOR CSV DOWNLOAD }}
-{{#if this.showCSVDownloadModal}}
-
-
- Export attribution data
-
-
-
- {{this.modalExportText}}
-
-
- The
- mount_path
- for entity/non-entity clients is the corresponding authentication method path
- {{if @isSecretsSyncActivated "and for secrets sync clients is the KV v2 engine path"}}.
-
- SELECTED DATE {{if this.formattedEndDate " RANGE"}}
-
- {{this.formattedStartDate}}
- {{if this.formattedEndDate "-"}}
- {{this.formattedEndDate}}
-
-
-
-
-
-
- {{#if @upgradesDuringActivity}}
-
-
- Data contains {{pluralize @upgradesDuringActivity.length "upgrade"}}:
-
-
-
- {{#each @upgradesDuringActivity as |upgrade|}}
-
- {{upgrade.version}}
- {{this.parseAPITimestamp upgrade.timestampInstalled "(MMM d, yyyy)"}}
-
- {{/each}}
-
-
-
- Visit our
-
- Client count FAQ
-
- for more information.
-
-
- {{/if}}
-
-
-{{/if}}
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ui/app/components/clients/attribution.js b/ui/app/components/clients/attribution.js
index ed8bde49f3..1f14f3b549 100644
--- a/ui/app/components/clients/attribution.js
+++ b/ui/app/components/clients/attribution.js
@@ -4,11 +4,12 @@
*/
import Component from '@glimmer/component';
-import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';
import { parseAPITimestamp } from 'core/utils/date-formatters';
-import { format, isSameMonth } from 'date-fns';
+import { isSameMonth } from 'date-fns';
+import { sanitizePath } from 'core/utils/sanitize-path';
+import { waitFor } from '@ember/test-waiters';
/**
* @module Attribution
@@ -17,7 +18,6 @@ import { format, isSameMonth } from 'date-fns';
*
* @example
*
*
- * @param {object} totalUsageCounts - object with total client counts for chart tooltip text
* @param {object} newUsageCounts - object with new client counts for chart tooltip text
* @param {array} totalClientAttribution - array of objects containing a label and breakdown of client counts for total clients
* @param {array} newClientAttribution - array of objects containing a label and breakdown of client counts for new clients
@@ -44,7 +43,33 @@ import { format, isSameMonth } from 'date-fns';
export default class Attribution extends Component {
@service download;
- @tracked showCSVDownloadModal = false;
+ @service store;
+ @service namespace;
+
+ @tracked canDownload = false;
+ @tracked showExportModal = false;
+ @tracked exportFormat = 'csv';
+ @tracked downloadError = '';
+
+ constructor() {
+ super(...arguments);
+ this.getExportCapabilities(this.args.selectedNamespace);
+ }
+
+ @waitFor
+ async getExportCapabilities(ns = '') {
+ try {
+ // selected namespace usually ends in /
+ const url = ns
+ ? `${sanitizePath(ns)}/sys/internal/counters/activity/export`
+ : 'sys/internal/counters/activity/export';
+ const cap = await this.store.findRecord('capabilities', url);
+ this.canDownload = cap.canSudo;
+ } catch (e) {
+ // if we can't read capabilities, default to show
+ this.canDownload = true;
+ }
+ }
get attributionLegend() {
const attributionLegend = [
@@ -59,21 +84,16 @@ export default class Attribution extends Component {
return attributionLegend;
}
- get formattedStartDate() {
- if (!this.args.startTimestamp) return null;
- return parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy');
- }
-
- get formattedEndDate() {
- if (!this.args.startTimestamp && !this.args.endTimestamp) return null;
- // displays on CSV export modal, no need to display duplicate months and years
+ get isSingleMonth() {
+ if (!this.args.startTimestamp && !this.args.endTimestamp) return false;
const startDateObject = parseAPITimestamp(this.args.startTimestamp);
const endDateObject = parseAPITimestamp(this.args.endTimestamp);
- return isSameMonth(startDateObject, endDateObject) ? null : format(endDateObject, 'MMMM yyyy');
+ return isSameMonth(startDateObject, endDateObject);
}
- get hasCsvData() {
- return this.args.totalClientAttribution ? this.args.totalClientAttribution.length > 0 : false;
+ get showExportButton() {
+ const hasData = this.args.totalClientAttribution ? this.args.totalClientAttribution.length > 0 : false;
+ return hasData && this.canDownload;
}
get isSingleNamespace() {
@@ -104,7 +124,7 @@ export default class Attribution extends Component {
if (!this.args.totalClientAttribution) {
return { description: 'There is a problem gathering data' };
}
- const dateText = this.formattedEndDate ? 'date range' : 'month';
+ const dateText = this.isSingleMonth ? 'month' : 'date range';
switch (this.isSingleNamespace) {
case true:
return {
@@ -129,121 +149,4 @@ export default class Attribution extends Component {
return '';
}
}
-
- destructureCountsToArray(object) {
- // destructure the namespace object {label: 'some-namespace', entity_clients: 171, non_entity_clients: 20, acme_clients: 6, secret_syncs: 10, clients: 207}
- // to get integers for CSV file
- const { clients, entity_clients, non_entity_clients, acme_clients, secret_syncs } = object;
- const { isSecretsSyncActivated } = this.args;
-
- return [
- clients,
- entity_clients,
- non_entity_clients,
- acme_clients,
- ...(isSecretsSyncActivated ? [secret_syncs] : []),
- ];
- }
-
- constructCsvRow(namespaceColumn, mountColumn = null, totalColumns, newColumns = null) {
- // if namespaceColumn is a string, then we're at mount level attribution, otherwise it is an object
- // if constructing a namespace row, mountColumn=null so the column is blank, otherwise it is an object
- const otherColumns = newColumns ? [...totalColumns, ...newColumns] : [...totalColumns];
- return [
- `${typeof namespaceColumn === 'string' ? namespaceColumn : namespaceColumn.label}`,
- `${mountColumn ? mountColumn.label : '*'}`,
- ...otherColumns,
- ];
- }
-
- generateCsvData() {
- const totalAttribution = this.args.totalClientAttribution;
- const newAttribution = this.barChartNewClients ? this.args.newClientAttribution : null;
- const { isSecretsSyncActivated } = this.args;
- const csvData = [];
- // added to clarify that the row of namespace totals without an auth method (blank) are not additional clients
- // but indicate the total clients for that ns, including its auth methods
- const upgrade = this.args.upgradesDuringActivity?.length
- ? `\n **data contains an upgrade (mount summation may not equal namespace totals)`
- : '';
- const descriptionOfBlanks = this.isSingleNamespace
- ? ''
- : `\n *namespace totals, inclusive of mount clients${upgrade}`;
- // client type order here should match array order returned by destructureCountsToArray
- let csvHeader = [
- 'Namespace path',
- `"Mount path${descriptionOfBlanks}"`, // double quotes necessary so description stays inside this cell
- 'Total clients',
- 'Entity clients',
- 'Non-entity clients',
- 'ACME clients',
- ...(isSecretsSyncActivated ? ['Secrets sync clients'] : []),
- ];
-
- if (newAttribution) {
- csvHeader = [
- ...csvHeader,
- 'Total new clients',
- 'New entity clients',
- 'New non-entity clients',
- 'New ACME clients',
- ...(isSecretsSyncActivated ? 'New secrets sync clients' : []),
- ];
- }
-
- totalAttribution.forEach((totalClientsObject) => {
- const namespace = this.isSingleNamespace ? this.args.selectedNamespace : totalClientsObject;
- const mount = this.isSingleNamespace ? totalClientsObject : null;
-
- // find new client data for namespace/mount object we're iterating over
- const newClientsObject = newAttribution
- ? newAttribution.find((d) => d.label === totalClientsObject.label)
- : null;
-
- const totalClients = this.destructureCountsToArray(totalClientsObject);
- const newClients = newClientsObject ? this.destructureCountsToArray(newClientsObject) : null;
-
- csvData.push(this.constructCsvRow(namespace, mount, totalClients, newClients));
- // constructCsvRow returns an array that corresponds to a row in the csv file:
- // ['ns label', 'mount label', total client #, entity #, non-entity #, acme #, secrets sync #, ...new client #'s]
-
- // only iterate through mounts if NOT viewing a single namespace
- if (!this.isSingleNamespace && namespace.mounts) {
- namespace.mounts.forEach((mount) => {
- const newMountData = newAttribution
- ? newClientsObject?.mounts.find((m) => m.label === mount.label)
- : null;
- const mountTotalClients = this.destructureCountsToArray(mount);
- const mountNewClients = newMountData ? this.destructureCountsToArray(newMountData) : null;
- csvData.push(this.constructCsvRow(namespace, mount, mountTotalClients, mountNewClients));
- });
- }
- });
-
- csvData.unshift(csvHeader);
- // make each nested array a comma separated string, join each array "row" in csvData with line break (\n)
- return csvData.map((d) => d.join()).join('\n');
- }
-
- get formattedCsvFileName() {
- const endRange = this.formattedEndDate ? `-${this.formattedEndDate}` : '';
- const csvDateRange = this.formattedStartDate ? `_${this.formattedStartDate + endRange}` : '';
- return this.isSingleNamespace
- ? `clients_by_mount_path${csvDateRange}`
- : `clients_by_namespace${csvDateRange}`;
- }
-
- get modalExportText() {
- const { isSecretsSyncActivated } = this.args;
- return `This export will include the namespace path, mount path and associated total entity, non-entity${
- isSecretsSyncActivated ? ', ACME and secrets sync clients' : ' and ACME clients'
- } for the ${this.formattedEndDate ? 'date range' : 'month'} below.`;
- }
-
- @action
- exportChartData(filename) {
- const contents = this.generateCsvData();
- this.download.csv(filename, contents);
- this.showCSVDownloadModal = false;
- }
}
diff --git a/ui/app/components/clients/counts/nav-bar.hbs b/ui/app/components/clients/counts/nav-bar.hbs
index 04c6e028c2..3c4b75c3ce 100644
--- a/ui/app/components/clients/counts/nav-bar.hbs
+++ b/ui/app/components/clients/counts/nav-bar.hbs
@@ -15,7 +15,7 @@
Entity/Non-entity clients
- {{#if @showSecretsSync}}
+ {{#if @showSecretsSyncClientCounts}}
Secrets sync clients
diff --git a/ui/app/components/clients/date-range.hbs b/ui/app/components/clients/date-range.hbs
new file mode 100644
index 0000000000..c652c9f912
--- /dev/null
+++ b/ui/app/components/clients/date-range.hbs
@@ -0,0 +1,102 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+~}}
+
+
+
+ Date range
+
+
+
+ {{#if (and @startTime @endTime)}}
+
{{this.formattedDate @startTime}}
+
—
+
{{this.formattedDate @endTime}}
+
+ {{else}}
+
+ {{/if}}
+
+
+ {{#if this.showEditModal}}
+
+
+ Edit date range
+
+
+
+ The start date will be used as the client counting start time and all clients in that month will be considered new.
+ {{#if this.version.isEnterprise}}
+ We recommend setting this date as your license or billing start date to get the most accurate new and total
+ client count estimations. These dates are only for querying data in storage. Editing the date range does not
+ change any license or billing configurations.
+ {{/if}}
+
+
+
+ Start
+
+
+
+ End
+
+
+
+
+ {{#if this.validationError}}
+ {{this.validationError}}
+ {{/if}}
+ {{#if (and this.version.isEnterprise this.useDefaultDates)}}
+
+ Dashboard will use the default date range from the API.
+
+ {{/if}}
+
+
+
+
+
+
+ {{/if}}
+
\ No newline at end of file
diff --git a/ui/app/components/clients/date-range.ts b/ui/app/components/clients/date-range.ts
new file mode 100644
index 0000000000..9e87e413cf
--- /dev/null
+++ b/ui/app/components/clients/date-range.ts
@@ -0,0 +1,125 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { action } from '@ember/object';
+import { service } from '@ember/service';
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { formatDateObject } from 'core/utils/client-count-utils';
+import { parseAPITimestamp } from 'core/utils/date-formatters';
+import timestamp from 'core/utils/timestamp';
+import { format } from 'date-fns';
+import type VersionService from 'vault/services/version';
+import type { HTMLElementEvent } from 'forms';
+
+interface OnChangeParams {
+ start_time: number | undefined;
+ end_time: number | undefined;
+}
+interface Args {
+ onChange: (callback: OnChangeParams) => void;
+ startTime: string;
+ endTime: string;
+}
+/**
+ * @module ClientsDateRange
+ * ClientsDateRange components are used to display the current date range and provide a modal interface for editing the date range.
+ *
+ * @example
+ *
+ *
+ *
+ * @param {function} onChange - callback when a new range is saved.
+ * @param {string} [startTime] - ISO string timestamp of the current start date
+ * @param {string} [endTime] - ISO string timestamp of the current end date
+ */
+
+export default class ClientsDateRangeComponent extends Component {
+ @service declare readonly version: VersionService;
+
+ @tracked showEditModal = false;
+ @tracked startDate = ''; // format yyyy-MM
+ @tracked endDate = ''; // format yyyy-MM
+ currentMonth = format(timestamp.now(), 'yyyy-MM');
+
+ constructor(owner: unknown, args: Args) {
+ super(owner, args);
+ this.setTrackedFromArgs();
+ }
+
+ setTrackedFromArgs() {
+ if (this.args.startTime) {
+ this.startDate = parseAPITimestamp(this.args.startTime, 'yyyy-MM') as string;
+ }
+ if (this.args.endTime) {
+ this.endDate = parseAPITimestamp(this.args.endTime, 'yyyy-MM') as string;
+ }
+ }
+
+ formattedDate = (isoTimestamp: string) => {
+ return parseAPITimestamp(isoTimestamp, 'MMMM yyyy');
+ };
+
+ get useDefaultDates() {
+ return !this.startDate && !this.endDate;
+ }
+
+ get validationError() {
+ if (this.useDefaultDates && this.version.isEnterprise) {
+ // this means we want to reset, which is fine for ent only
+ return null;
+ }
+ if (!this.startDate || !this.endDate) {
+ return 'You must supply both start and end dates.';
+ }
+ if (this.startDate > this.endDate) {
+ return 'Start date must be before end date.';
+ }
+ return null;
+ }
+
+ @action onClose() {
+ // since the component never gets torn down, we have to manually re-set this on close
+ this.setTrackedFromArgs();
+ this.showEditModal = false;
+ }
+
+ @action resetDates() {
+ this.startDate = '';
+ this.endDate = '';
+ }
+
+ @action updateDate(evt: HTMLElementEvent) {
+ const { name, value } = evt.target;
+ if (name === 'end') {
+ this.endDate = value;
+ } else {
+ this.startDate = value;
+ }
+ }
+
+ @action handleSave() {
+ if (this.validationError) return;
+ const params: OnChangeParams = {
+ start_time: undefined,
+ end_time: undefined,
+ };
+ if (this.startDate) {
+ const [year, month] = this.startDate.split('-');
+ if (year && month) {
+ params.start_time = formatDateObject({ monthIdx: parseInt(month) - 1, year: parseInt(year) }, false);
+ }
+ }
+ if (this.endDate) {
+ const [year, month] = this.endDate.split('-');
+ if (year && month) {
+ params.end_time = formatDateObject({ monthIdx: parseInt(month) - 1, year: parseInt(year) }, true);
+ }
+ }
+
+ this.args.onChange(params);
+ this.onClose();
+ }
+}
diff --git a/ui/app/components/clients/export-button.hbs b/ui/app/components/clients/export-button.hbs
new file mode 100644
index 0000000000..b947a29654
--- /dev/null
+++ b/ui/app/components/clients/export-button.hbs
@@ -0,0 +1,72 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+~}}
+
+
+
+{{! MODAL FOR CSV DOWNLOAD }}
+{{#if this.showExportModal}}
+
+
+ Export activity data
+
+
+ {{#if this.exportChartData.isRunning}}
+
+ Your export request is being processed. This may take some time; please do not navigate away from this page.
+
+
+
+
+ {{else}}
+
+ This file will include an export of the clients that had activity within the date range below. See the
+ activity export documentation
+ for more details.
+
+ SELECTED DATE {{if this.formattedEndDate " RANGE"}}
+
+ {{this.formattedStartDate}}
+ {{if this.formattedEndDate "-"}}
+ {{this.formattedEndDate}}
+
+
+ Export format
+
+ CSV
+ JSON Lines
+
+
+ {{/if}}
+
+ {{#if this.downloadError}}
+
+ CSV export failed
+ {{this.downloadError}}
+
+ {{/if}}
+
+
+
+
+
+
+ {{yield to="alert"}}
+
+
+{{/if}}
\ No newline at end of file
diff --git a/ui/app/components/clients/export-button.js b/ui/app/components/clients/export-button.js
new file mode 100644
index 0000000000..43a3be252f
--- /dev/null
+++ b/ui/app/components/clients/export-button.js
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { action } from '@ember/object';
+import { service } from '@ember/service';
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { parseAPITimestamp } from 'core/utils/date-formatters';
+import { sanitizePath } from 'core/utils/sanitize-path';
+import { format, isSameMonth } from 'date-fns';
+import { task } from 'ember-concurrency';
+
+/**
+ * @module ClientsExportButtonComponent
+ * ClientsExportButton components are used to display the export button, manage the modal, and download the file from the clients export API
+ *
+ * @example
+ * ```js
+ *
+ * ```
+ * @param {string} [startTimestamp] - ISO timestamp of start time, to be passed to export request
+ * @param {string} [endTimestamp] - ISO timestamp of end time, to be passed to export request
+ * @param {string} [namespace] - namespace filter. Will be appended to the current namespace in the export request.
+ */
+export default class ClientsExportButtonComponent extends Component {
+ @service download;
+ @service namespace;
+ @service store;
+
+ @tracked showExportModal = false;
+ @tracked exportFormat = 'csv';
+ @tracked downloadError = '';
+
+ get formattedStartDate() {
+ if (!this.args.startTimestamp) return null;
+ return parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy');
+ }
+
+ get formattedEndDate() {
+ if (!this.args.startTimestamp && !this.args.endTimestamp) return null;
+ // displays on CSV export modal, no need to display duplicate months and years
+ const startDateObject = parseAPITimestamp(this.args.startTimestamp);
+ const endDateObject = parseAPITimestamp(this.args.endTimestamp);
+ return isSameMonth(startDateObject, endDateObject) ? null : format(endDateObject, 'MMMM yyyy');
+ }
+
+ get formattedCsvFileName() {
+ const endRange = this.formattedEndDate ? `-${this.formattedEndDate}` : '';
+ const csvDateRange = this.formattedStartDate ? `_${this.formattedStartDate + endRange}` : '';
+ const ns = this.namespaceFilter ? `_${this.namespaceFilter}` : '';
+ return `clients_export${ns}${csvDateRange}`;
+ }
+
+ get namespaceFilter() {
+ const currentNs = this.namespace.path;
+ const { selectedNamespace } = this.args;
+ return selectedNamespace ? sanitizePath(`${currentNs}/${selectedNamespace}`) : sanitizePath(currentNs);
+ }
+
+ async getExportData() {
+ const adapter = this.store.adapterFor('clients/activity');
+ const { startTimestamp, endTimestamp } = this.args;
+ return adapter.exportData({
+ // the API only accepts json or csv
+ format: this.exportFormat === 'jsonl' ? 'json' : 'csv',
+ start_time: startTimestamp,
+ end_time: endTimestamp,
+ namespace: this.namespaceFilter,
+ });
+ }
+
+ exportChartData = task({ drop: true }, async (filename) => {
+ try {
+ const contents = await this.getExportData();
+ this.download.download(filename, contents, this.exportFormat);
+ this.showExportModal = false;
+ } catch (e) {
+ this.downloadError = e.message;
+ }
+ });
+
+ @action setExportFormat(evt) {
+ const { value } = evt.target;
+ this.exportFormat = value;
+ }
+
+ @action resetModal() {
+ this.showExportModal = false;
+ this.downloadError = '';
+ }
+}
diff --git a/ui/app/components/clients/no-data.hbs b/ui/app/components/clients/no-data.hbs
index b6fa080dcd..113c1e33c7 100644
--- a/ui/app/components/clients/no-data.hbs
+++ b/ui/app/components/clients/no-data.hbs
@@ -3,13 +3,13 @@
SPDX-License-Identifier: BUSL-1.1
~}}
-{{#if (eq @config.enabled "On")}}
+{{#if (or @config.reportingEnabled (eq @config.enabled "On"))}}
-{{else}}
+{{else if @config}}
{{/if}}
+{{else}}
+
{{/if}}
\ No newline at end of file
diff --git a/ui/app/components/clients/page/counts.hbs b/ui/app/components/clients/page/counts.hbs
index 512d729b91..38b8fd840c 100644
--- a/ui/app/components/clients/page/counts.hbs
+++ b/ui/app/components/clients/page/counts.hbs
@@ -18,35 +18,12 @@
Date queries are sent in UTC.
-
- {{this.versionText.label}}
-
-
-
- {{#if this.formattedStartDate}}
-
{{this.formattedStartDate}}
-
- {{else}}
-
- {{/if}}
-
-
-
- {{this.versionText.description}}
-
+
{{#if (eq @activity.id "no-data")}}
@@ -76,11 +53,6 @@
-
{{#if (or @namespace this.namespaces)}}
{{/if}}
-
+
{{! CLIENT COUNT PAGE COMPONENTS RENDER HERE }}
{{yield}}
@@ -172,22 +144,4 @@
{{/if}}
{{/if}}
-
-
-{{#if this.showBillingStartModal}}
-
-
- Edit start month
-
-
-
- {{this.versionText.description}}
-
- {{this.versionText.label}}
-
-
-
-
-
-
-{{/if}}
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ui/app/components/clients/page/counts.ts b/ui/app/components/clients/page/counts.ts
index 28fb5ae7b0..bd53145a54 100644
--- a/ui/app/components/clients/page/counts.ts
+++ b/ui/app/components/clients/page/counts.ts
@@ -6,10 +6,9 @@
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { action } from '@ember/object';
-import { fromUnixTime, getUnixTime, isSameMonth, isAfter } from 'date-fns';
+import { isSameMonth, isAfter } from 'date-fns';
import { parseAPITimestamp } from 'core/utils/date-formatters';
-import { filterVersionHistory, formatDateObject } from 'core/utils/client-count-utils';
-import timestamp from 'core/utils/timestamp';
+import { filterVersionHistory } from 'core/utils/client-count-utils';
import type AdapterError from '@ember-data/adapter';
import type FlagsService from 'vault/services/flags';
@@ -22,11 +21,11 @@ interface Args {
activity: ClientsActivityModel;
activityError?: AdapterError;
config: ClientsConfigModel;
- endTimestamp: number;
+ endTimestamp: string; // ISO format
mountPath: string;
namespace: string;
onFilterChange: CallableFunction;
- startTimestamp: number;
+ startTimestamp: string; // ISO format
versionHistory: ClientsVersionHistoryModel[];
}
@@ -35,29 +34,21 @@ export default class ClientsCountsPageComponent extends Component {
@service declare readonly version: VersionService;
@service declare readonly store: StoreService;
- get startTimestampISO() {
- return this.args.startTimestamp ? fromUnixTime(this.args.startTimestamp).toISOString() : null;
- }
-
- get endTimestampISO() {
- return this.args.endTimestamp ? fromUnixTime(this.args.endTimestamp).toISOString() : null;
- }
-
get formattedStartDate() {
- return this.startTimestampISO ? parseAPITimestamp(this.startTimestampISO, 'MMMM yyyy') : null;
+ return this.args.startTimestamp ? parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy') : null;
}
// returns text for empty state message if noActivityData
get dateRangeMessage() {
- if (this.startTimestampISO && this.endTimestampISO) {
+ if (this.args.startTimestamp && this.args.endTimestamp) {
const endMonth = isSameMonth(
- parseAPITimestamp(this.startTimestampISO) as Date,
- parseAPITimestamp(this.endTimestampISO) as Date
+ parseAPITimestamp(this.args.startTimestamp) as Date,
+ parseAPITimestamp(this.args.endTimestamp) as Date
)
? ''
- : `to ${parseAPITimestamp(this.endTimestampISO, 'MMMM yyyy')}`;
+ : `to ${parseAPITimestamp(this.args.endTimestamp, 'MMMM yyyy')}`;
// completes the message 'No data received from { dateRangeMessage }'
- return `from ${parseAPITimestamp(this.startTimestampISO, 'MMMM yyyy')} ${endMonth}`;
+ return `from ${parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy')} ${endMonth}`;
}
return null;
}
@@ -94,17 +85,11 @@ export default class ClientsCountsPageComponent extends Component {
get versionText() {
return this.version.isEnterprise
? {
- label: 'Billing start month',
- description:
- 'This date comes from your license, and defines when client counting starts. Without this starting point, the data shown is not reliable.',
title: 'No billing start date found',
message:
'In order to get the most from this data, please enter your billing period start month. This will ensure that the resulting data is accurate.',
}
: {
- label: 'Client counting start date',
- description:
- 'This date is when client counting starts. Without this starting point, the data shown is not reliable.',
title: 'No start date found',
message:
'In order to get the most from this data, please enter a start month above. Vault will calculate new clients starting from that month.',
@@ -134,9 +119,9 @@ export default class ClientsCountsPageComponent extends Component {
// show banner if startTime returned from activity log (response) is after the queried startTime
const { activity, config } = this.args;
const activityStartDateObject = parseAPITimestamp(activity.startTime) as Date;
- const queryStartDateObject = parseAPITimestamp(this.startTimestampISO) as Date;
+ const queryStartDateObject = parseAPITimestamp(this.args.startTimestamp) as Date;
const isEnterprise =
- this.startTimestampISO === config.billingStartTimestamp?.toISOString() && this.version.isEnterprise;
+ this.args.startTimestamp === config.billingStartTimestamp?.toISOString() && this.version.isEnterprise;
const message = isEnterprise ? 'Your license start date is' : 'You requested data from';
if (
@@ -167,42 +152,15 @@ export default class ClientsCountsPageComponent extends Component {
return activity?.total;
}
- get showSecretsSync(): boolean {
+ get hasSecretsSyncClients(): boolean {
const { activity } = this.args;
// if there is any sync client data, show it
- if (activity && activity?.total?.secret_syncs > 0) return true;
-
- // otherwise, show the tab based on the cluster type and license
- if (this.version.isCommunity) return false;
-
- const isHvd = this.flags.isHvdManaged;
- const onLicense = this.version.hasSecretsSync;
-
- // we can't tell if HVD clusters have the feature or not, so we show it by default
- // if the cluster is not HVD, show the tab if the feature is on the license
- return isHvd || onLicense;
+ return activity && activity?.total?.secret_syncs > 0;
}
@action
- onDateChange(dateObject: { dateType: string; monthIdx: number; year: number }) {
- const { dateType, monthIdx, year } = dateObject;
- const { config } = this.args;
- const currentTimestamp = getUnixTime(timestamp.now());
-
- // converts the selectedDate to unix timestamp for activity query
- const selectedDate = formatDateObject({ monthIdx, year }, dateType === 'endDate');
-
- if (dateType !== 'cancel') {
- const start_time = {
- reset: getUnixTime(config?.billingStartTimestamp) || null, // clicked 'Current billing period' in calendar widget -> resets to billing start date
- currentMonth: currentTimestamp, // clicked 'Current month' from calendar widget -> defaults to currentTimestamp
- startDate: selectedDate, // from "Edit billing start" modal
- }[dateType];
- // endDate type is selection from calendar widget
- const end_time = dateType === 'endDate' ? selectedDate : currentTimestamp; // defaults to currentTimestamp
- const params = start_time !== undefined ? { start_time, end_time } : { end_time };
- this.args.onFilterChange(params);
- }
+ onDateChange(params: { start_time: number | undefined; end_time: number | undefined }) {
+ this.args.onFilterChange(params);
}
@action
diff --git a/ui/app/components/clients/page/overview.hbs b/ui/app/components/clients/page/overview.hbs
index f069423df2..c4635c97d3 100644
--- a/ui/app/components/clients/page/overview.hbs
+++ b/ui/app/components/clients/page/overview.hbs
@@ -16,13 +16,12 @@
{{#if this.hasAttributionData}}
-
diff --git a/ui/app/components/console/ui-panel.js b/ui/app/components/console/ui-panel.js
index a001b051f5..525dfb2270 100644
--- a/ui/app/components/console/ui-panel.js
+++ b/ui/app/components/console/ui-panel.js
@@ -6,7 +6,7 @@
import { service } from '@ember/service';
import { alias, or } from '@ember/object/computed';
import Component from '@ember/component';
-import { getOwner } from '@ember/application';
+import { getOwner } from '@ember/owner';
import { schedule } from '@ember/runloop';
import { camelize } from '@ember/string';
import { task } from 'ember-concurrency';
diff --git a/ui/app/components/dashboard/client-count-card.hbs b/ui/app/components/dashboard/client-count-card.hbs
index 2b9b4fa320..b904566483 100644
--- a/ui/app/components/dashboard/client-count-card.hbs
+++ b/ui/app/components/dashboard/client-count-card.hbs
@@ -14,10 +14,10 @@
- {{#if this.hasActivity}}
- {{#if this.fetchClientActivity.isRunning}}
-
- {{else}}
+ {{#if this.fetchClientActivity.isRunning}}
+
+ {{else}}
+ {{#if this.activityData}}
@@ -34,15 +34,13 @@
{{on "click" (perform this.fetchClientActivity)}}
data-test-refresh
/>
-
+
Updated
{{date-format this.updatedAt "MMM d yyyy, h:mm:ss aaa" withTimeZone=true}}
+ {{else}}
+
{{/if}}
- {{else}}
- {{! This will likely never show since the clients activity api has changed to always return data. In the past it
- would return no activity data. Adding this empty state here to match the current client count behavior }}
-
{{/if}}
\ No newline at end of file
diff --git a/ui/app/components/dashboard/client-count-card.js b/ui/app/components/dashboard/client-count-card.js
index 51c2d174dd..6b613bfe53 100644
--- a/ui/app/components/dashboard/client-count-card.js
+++ b/ui/app/components/dashboard/client-count-card.js
@@ -23,7 +23,7 @@ export default class DashboardClientCountCard extends Component {
@service store;
@tracked activityData = null;
- @tracked hasActivity = false;
+ @tracked activityConfig = null;
@tracked updatedAt = null;
constructor() {
@@ -53,11 +53,10 @@ export default class DashboardClientCountCard extends Component {
this.updatedAt = timestamp.now().toISOString();
try {
- this.activityData = yield this.store.queryRecord('clients/activity', {
- current_billing_period: true,
- });
- this.hasActivity = this.activityData.id === 'no-data' ? false : true;
+ this.activityData = yield this.store.findRecord('clients/activity', 'clients/activity');
} catch (error) {
+ // used for rendering the "No data" empty state, swallow any errors requesting config data
+ this.activityConfig = yield this.store.queryRecord('clients/config', {}).catch(() => null);
this.error = error;
}
}
diff --git a/ui/app/components/date-dropdown.js b/ui/app/components/date-dropdown.js
deleted file mode 100644
index 7fee2b4551..0000000000
--- a/ui/app/components/date-dropdown.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: BUSL-1.1
- */
-
-import Component from '@glimmer/component';
-import { action } from '@ember/object';
-import { tracked } from '@glimmer/tracking';
-import { ARRAY_OF_MONTHS } from 'core/utils/date-formatters';
-import timestamp from 'core/utils/timestamp';
-/**
- * @module DateDropdown
- * DateDropdown components are used to display a dropdown of months and years to handle date selection. Future dates are disabled (current month and year are selectable).
- * The component returns an object with selected date info, example: { dateType: 'start', monthIdx: 0, monthName: 'January', year: 2022 }
- *
- * @example
- * ```js
- *
- * ```
- * @param {function} handleSubmit - callback function from parent that the date picker triggers on submit
- * @param {string} [dateType] - optional argument to give the selected month/year a type
- * @param {string} [submitText] - optional argument to change submit button text
- * @param {function} [validateDate] - parent function to validate date selection, receives date object and returns an error message that's passed to the inline alert
- */
-export default class DateDropdown extends Component {
- currentDate = timestamp.now();
- currentYear = this.currentDate.getFullYear(); // integer of year
- currentMonthIdx = this.currentDate.getMonth(); // integer of month, 0 indexed
- dropdownMonths = ARRAY_OF_MONTHS.map((m, i) => ({ name: m, index: i }));
- dropdownYears = Array.from({ length: 5 }, (item, i) => this.currentYear - i);
-
- @tracked maxMonthIdx = 11; // disables months with index greater than this number, initially all months are selectable
- @tracked disabledYear = null; // year as integer if current year should be disabled
- @tracked selectedMonth = null;
- @tracked selectedYear = null;
- @tracked invalidDate = null;
-
- @action
- selectMonth(month, dropdown) {
- this.selectedMonth = month;
- // disable current year if selected month is later than current month
- this.disabledYear = month.index > this.currentMonthIdx ? this.currentYear : null;
- dropdown.close();
- }
-
- @action
- selectYear(year, dropdown) {
- this.selectedYear = year;
- // disable months after current month if selected year is current year
- this.maxMonthIdx = year === this.currentYear ? this.currentMonthIdx : 11;
- dropdown.close();
- }
-
- @action
- handleSubmit() {
- if (this.args.validateDate) {
- this.invalidDate = null;
- this.invalidDate = this.args.validateDate(new Date(this.selectedYear, this.selectedMonth.index));
- if (this.invalidDate) return;
- }
- const { index, name } = this.selectedMonth;
- this.args.handleSubmit({
- monthIdx: index,
- monthName: name,
- year: this.selectedYear,
- dateType: this.args.dateType,
- });
- this.resetDropdown();
- }
-
- resetDropdown() {
- this.maxMonthIdx = 11;
- this.disabledYear = null;
- this.selectedMonth = null;
- this.selectedYear = null;
- this.invalidDate = null;
- }
-}
diff --git a/ui/app/templates/components/generate-credentials.hbs b/ui/app/components/generate-credentials.hbs
similarity index 57%
rename from ui/app/templates/components/generate-credentials.hbs
rename to ui/app/components/generate-credentials.hbs
index 8ab1ca3f28..8481a662c9 100644
--- a/ui/app/templates/components/generate-credentials.hbs
+++ b/ui/app/components/generate-credentials.hbs
@@ -7,13 +7,13 @@
-
-
+
+
@@ -24,7 +24,7 @@
-{{#if this.model.hasGenerated}}
+{{#if this.hasGenerated}}
{{#unless this.model.isError}}
@@ -35,48 +35,42 @@
{{/unless}}
- {{#each this.model.attrs as |attr|}}
- {{#if (eq attr.type "object")}}
-
- {{else}}
- {{#if
- (or
- (eq attr.name "key")
- (eq attr.name "secretKey")
- (eq attr.name "securityToken")
- (eq attr.name "privateKey")
- attr.options.masked
- )
- }}
- {{#if (get this.model attr.name)}}
+ {{#each this.displayFields as |key|}}
+ {{#let (get this.model.allByKey key) as |attr|}}
+ {{#if (eq attr.type "object")}}
+
+ {{else}}
+ {{#if attr.options.masked}}
+ {{#if (get this.model attr.name)}}
+
+
+
+ {{/if}}
+ {{else if (and (get this.model attr.name) (or (eq attr.name "issueDate") (eq attr.name "expiryDate")))}}
+
+ {{else}}
-
-
+ />
{{/if}}
- {{else if (and (get this.model attr.name) (or (eq attr.name "issueDate") (eq attr.name "expiryDate")))}}
-
- {{else}}
-
{{/if}}
- {{/if}}
+ {{/let}}
{{/each}}
@@ -106,34 +100,25 @@
@text="Back"
@color="secondary"
@route="vault.cluster.secrets.backend.list-root"
- @model={{this.backendPath}}
- data-test-secret-generate-back={{true}}
+ @model={{@backendPath}}
+ data-test-back-button
/>
{{else}}
-
+
{{/if}}
{{else}}
-