├── .dockerignore ├── .editorconfig ├── .envrc ├── .github ├── .editorconfig ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ ├── config.yml │ └── feature_request.yaml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yaml ├── renovate.json └── workflows │ ├── analysis-scorecard.yaml │ ├── artifacts.yaml │ ├── ci.yaml │ ├── pr.yml │ ├── project.yml │ └── release.yaml ├── .gitignore ├── .golangci.yaml ├── .goreleaser.yaml ├── .hadolint.yaml ├── .licensei.toml ├── .yamlignore ├── .yamllint.yaml ├── Dockerfile ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── client_logger.go ├── docker-compose.yaml ├── flake.lock ├── flake.nix ├── go.mod ├── go.sum └── main.go /.dockerignore: -------------------------------------------------------------------------------- 1 | /.devenv/ 2 | /.direnv/ 3 | /.github/ 4 | /bin/ 5 | /build/ 6 | /Dockerfile 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.go] 12 | indent_style = tab 13 | 14 | [{*.yaml,*.yml}] 15 | indent_size = 2 16 | 17 | [{Makefile,*.mk}] 18 | indent_style = tab 19 | 20 | [*.nix] 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" 3 | fi 4 | use flake . --impure 5 | 6 | # Vault 7 | export VAULT_ADDR=http://127.0.0.1:8200 8 | export VAULT_TOKEN=227e1cce-6bf7-30bb-2d2a-acc854318caf 9 | -------------------------------------------------------------------------------- /.github/.editorconfig: -------------------------------------------------------------------------------- 1 | [{*.yml,*.yaml}] 2 | indent_size = 2 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This file provides an overview of code owners in this repository. 2 | 3 | # Each line is a file pattern followed by one or more owners. 4 | # The last matching pattern has the most precedence. 5 | # For more details read the following article on GitHub: https://help.github.com/articles/about-codeowners/. 6 | 7 | # These are the default owners for the whole content of repository. 8 | # The default owners are automatically added as reviewers when you open a pull request unless different owners are specified in the file. 9 | * @bank-vaults/maintainers 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug report 2 | description: Report a bug to help us improve Vault Env 3 | labels: [kind/bug] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for submitting a bug report! 9 | 10 | Please fill out the template below to make it easier to debug your problem. 11 | 12 | If you are not sure if it is a bug or not, you can contact us via the available [support channels](https://bank-vaults.dev/docs/support). 13 | - type: checkboxes 14 | attributes: 15 | label: Preflight Checklist 16 | description: Please ensure you've completed all of the following. 17 | options: 18 | - label: I have searched the [issue tracker](https://www.github.com/bank-vaults/vault-env/issues) for an issue that matches the one I want to file, without success. 19 | required: true 20 | - label: I am not looking for support or already pursued the available [support channels](https://bank-vaults.dev/docs/support) without success. 21 | required: true 22 | - label: I agree to follow the [Code of Conduct](https://bank-vaults.dev/docs/code-of-conduct). 23 | required: true 24 | - type: input 25 | attributes: 26 | label: Vault Env Version 27 | description: What version of Vault Env are you using? 28 | placeholder: 1.20.0 29 | validations: 30 | required: true 31 | - type: dropdown 32 | attributes: 33 | label: Installation Type 34 | description: How did you install the Operator? 35 | options: 36 | - Official Helm chart 37 | - Custom Helm chart 38 | - Vault Secrets Webhook 39 | - Other (specify below) 40 | - type: input 41 | attributes: 42 | label: Kubernetes Version 43 | description: What version of Kubernetes are you using? 44 | placeholder: 1.27.0 45 | validations: 46 | required: true 47 | - type: input 48 | attributes: 49 | label: Kubernetes Distribution/Provisioner 50 | description: Which Kubernetes distribution/privisioner are you using? 51 | placeholder: e.g. GKE, EKS, AKS, etc 52 | validations: 53 | required: true 54 | - type: textarea 55 | attributes: 56 | label: Expected Behavior 57 | description: A clear and concise description of what you expected to happen. 58 | validations: 59 | required: true 60 | - type: textarea 61 | attributes: 62 | label: Actual Behavior 63 | description: A clear description of what actually happens. 64 | validations: 65 | required: true 66 | - type: textarea 67 | attributes: 68 | label: Steps To Reproduce 69 | description: Steps to reproduce the behavior if it is not self-explanatory. 70 | placeholder: | 71 | 1. In this environment... 72 | 2. With this config... 73 | 3. Run '...' 74 | 4. See error... 75 | - type: textarea 76 | attributes: 77 | label: Logs 78 | description: Operator or application logs (if relevant). 79 | render: shell 80 | - type: textarea 81 | attributes: 82 | label: Additional Information 83 | description: Links? References? Anything that will give us more context about the issue that you are encountering! 84 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: 📖 Documentation enhancement 4 | url: https://github.com/bank-vaults/bank-vaults.dev/issues 5 | about: Suggest an improvement to the documentation 6 | 7 | - name: 📚 Documentation 8 | url: https://bank-vaults.dev/docs 9 | about: Check the documentation for help 10 | 11 | - name: 💬 Slack channel 12 | url: https://cloud-native.slack.com/archives/C078PHYK38W/ 13 | about: Please ask and answer questions here 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yaml: -------------------------------------------------------------------------------- 1 | name: 🎉 Feature request 2 | description: Suggest an idea for the Vault Env 3 | labels: [kind/enhancement] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for submitting a feature request! 9 | 10 | Please describe what you would like to change/add and why in detail by filling out the template below. 11 | 12 | If you are not sure if your request fits into Vault Env, you can contact us via the available [support channels](https://bank-vaults.dev/docs/support). 13 | - type: checkboxes 14 | attributes: 15 | label: Preflight Checklist 16 | description: Please ensure you've completed all of the following. 17 | options: 18 | - label: I have searched the [issue tracker](https://www.github.com/bank-vaults/vault-env/issues) for an issue that matches the one I want to file, without success. 19 | required: true 20 | - label: I agree to follow the [Code of Conduct](https://bank-vaults.dev/docs/code-of-conduct). 21 | required: true 22 | - type: textarea 23 | attributes: 24 | label: Problem Description 25 | description: A clear and concise description of the problem you are seeking to solve with this feature request. 26 | validations: 27 | required: true 28 | - type: textarea 29 | attributes: 30 | label: Proposed Solution 31 | description: A clear and concise description of what would you like to happen. 32 | validations: 33 | required: true 34 | - type: textarea 35 | attributes: 36 | label: Alternatives Considered 37 | description: A clear and concise description of any alternative solutions or features you've considered. 38 | - type: textarea 39 | attributes: 40 | label: Additional Information 41 | description: Add any other relevant context here. 42 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ## Overview 10 | 11 | 16 | 17 | Fixes #(issue) 18 | 19 | ## Notes for reviewer 20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "gomod" 5 | directory: "/" 6 | labels: 7 | - "area/dependencies" 8 | schedule: 9 | interval: "weekly" 10 | day: "sunday" 11 | time: "16:00" 12 | open-pull-requests-limit: 10 13 | 14 | - package-ecosystem: "docker" 15 | directory: "/" 16 | labels: 17 | - "area/dependencies" 18 | schedule: 19 | interval: "weekly" 20 | day: "sunday" 21 | time: "16:00" 22 | open-pull-requests-limit: 10 23 | 24 | - package-ecosystem: "github-actions" 25 | directory: "/" 26 | labels: 27 | - "area/dependencies" 28 | schedule: 29 | interval: "weekly" 30 | day: "sunday" 31 | time: "16:00" 32 | open-pull-requests-limit: 10 33 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "schedule:earlyMondays", 5 | ":disableDependencyDashboard" 6 | ], 7 | "enabledManagers": [ 8 | "nix" 9 | ], 10 | "nix": { 11 | "enabled": true 12 | }, 13 | "lockFileMaintenance": { 14 | "enabled": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/analysis-scorecard.yaml: -------------------------------------------------------------------------------- 1 | name: OpenSSF Scorecard 2 | 3 | on: 4 | branch_protection_rule: 5 | push: 6 | branches: [main] 7 | schedule: 8 | - cron: '30 0 * * 5' 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | analyze: 15 | name: Analyze 16 | runs-on: ubuntu-latest 17 | 18 | permissions: 19 | actions: read 20 | contents: read 21 | id-token: write 22 | security-events: write 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | with: 28 | persist-credentials: false 29 | 30 | - name: Run analysis 31 | uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 32 | with: 33 | results_file: results.sarif 34 | results_format: sarif 35 | publish_results: true 36 | 37 | - name: Upload results as artifact 38 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 39 | with: 40 | name: OpenSSF Scorecard results 41 | path: results.sarif 42 | retention-days: 5 43 | 44 | - name: Upload results to GitHub Security tab 45 | uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v2.3.4 46 | with: 47 | sarif_file: results.sarif 48 | -------------------------------------------------------------------------------- /.github/workflows/artifacts.yaml: -------------------------------------------------------------------------------- 1 | name: Artifacts 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | publish: 7 | description: Publish artifacts to the artifact store 8 | default: false 9 | required: false 10 | type: boolean 11 | release: 12 | description: Whether this is a release build 13 | default: false 14 | required: false 15 | type: boolean 16 | outputs: 17 | container-image-name: 18 | description: Container image name 19 | value: ${{ jobs.container-image.outputs.name }} 20 | container-image-digest: 21 | description: Container image digest 22 | value: ${{ jobs.container-image.outputs.digest }} 23 | container-image-tag: 24 | description: Container image tag 25 | value: ${{ jobs.container-image.outputs.tag }} 26 | container-image-ref: 27 | description: Container image ref 28 | value: ${{ jobs.container-image.outputs.ref }} 29 | 30 | permissions: 31 | contents: read 32 | 33 | jobs: 34 | container-image: 35 | name: Container image 36 | runs-on: ubuntu-latest 37 | 38 | permissions: 39 | contents: read 40 | packages: write 41 | id-token: write 42 | security-events: write 43 | 44 | outputs: 45 | name: ${{ steps.image-name.outputs.value }} 46 | digest: ${{ steps.build.outputs.digest }} 47 | tag: ${{ steps.meta.outputs.version }} 48 | ref: ${{ steps.image-ref.outputs.value }} 49 | 50 | steps: 51 | - name: Checkout repository 52 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 53 | 54 | - name: Set up QEMU 55 | uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 56 | 57 | - name: Set up Docker Buildx 58 | uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 59 | 60 | - name: Set up Cosign 61 | uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2 62 | 63 | - name: Set image name 64 | id: image-name 65 | run: echo "value=ghcr.io/${{ github.repository }}" >> "$GITHUB_OUTPUT" 66 | 67 | - name: Gather build metadata 68 | id: meta 69 | uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 70 | with: 71 | images: ${{ steps.image-name.outputs.value }} 72 | flavor: | 73 | latest = false 74 | tags: | 75 | type=ref,event=branch 76 | type=ref,event=pr,prefix=pr- 77 | type=semver,pattern={{raw}} 78 | type=raw,value=latest,enable={{is_default_branch}} 79 | 80 | # Multiple exporters are not supported yet 81 | # See https://github.com/moby/buildkit/pull/2760 82 | - name: Determine build output 83 | uses: haya14busa/action-cond@94f77f7a80cd666cb3155084e428254fea4281fd # v1.2.1 84 | id: build-output 85 | with: 86 | cond: ${{ inputs.publish }} 87 | if_true: type=image,push=true 88 | if_false: type=oci,dest=image.tar 89 | 90 | - name: Login to GitHub Container Registry 91 | uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 92 | with: 93 | registry: ghcr.io 94 | username: ${{ github.actor }} 95 | password: ${{ github.token }} 96 | if: inputs.publish 97 | 98 | - name: Build and push image 99 | id: build 100 | uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0 101 | with: 102 | context: . 103 | platforms: linux/amd64,linux/arm64,linux/arm/v7 104 | tags: ${{ steps.meta.outputs.tags }} 105 | labels: ${{ steps.meta.outputs.labels }} 106 | cache-from: type=gha 107 | cache-to: type=gha,mode=max 108 | outputs: ${{ steps.build-output.outputs.value }} 109 | # push: ${{ inputs.publish }} 110 | 111 | - name: Sign image with GitHub OIDC Token 112 | if: ${{ inputs.publish && github.repository_owner == 'bank-vaults' }} # Check if the workflow is called by the same GitHub organization 113 | env: 114 | DIGEST: ${{ steps.build.outputs.digest }} 115 | TAGS: ${{ steps.meta.outputs.tags }} 116 | run: | 117 | images="" 118 | for tag in ${TAGS[@]}; do 119 | images+="${tag}@${DIGEST} " 120 | done 121 | 122 | cosign sign --yes --rekor-url "https://rekor.sigstore.dev/" ${images} 123 | 124 | - name: Verify signed image with cosign 125 | if: ${{ inputs.publish && github.repository_owner == 'bank-vaults' }} # Check if the workflow is called by the same GitHub organization 126 | env: 127 | DIGEST: ${{ steps.build.outputs.digest }} 128 | TAGS: ${{ steps.meta.outputs.tags }} 129 | run: | 130 | for tag in ${TAGS[@]}; do 131 | cosign verify "${tag}@${DIGEST}" \ 132 | --rekor-url "https://rekor.sigstore.dev/" \ 133 | --certificate-identity "https://github.com/${{ github.repository }}/.github/workflows/artifacts.yaml@${{ github.ref }}" \ 134 | --certificate-oidc-issuer "https://token.actions.githubusercontent.com" | jq 135 | done 136 | 137 | - name: Set image ref 138 | id: image-ref 139 | run: echo "value=${{ steps.image-name.outputs.value }}@${{ steps.build.outputs.digest }}" >> "$GITHUB_OUTPUT" 140 | 141 | - name: Fetch image 142 | run: skopeo --insecure-policy copy docker://${{ steps.image-name.outputs.value }}:${{ steps.meta.outputs.version }} oci-archive:image.tar 143 | if: inputs.publish 144 | 145 | - name: Upload image as artifact 146 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 147 | with: 148 | name: "[${{ github.job }}] OCI tarball" 149 | path: image.tar 150 | 151 | - name: Extract OCI tarball 152 | run: | 153 | mkdir -p image 154 | tar -xf image.tar -C image 155 | 156 | # See https://github.com/anchore/syft/issues/1545 157 | - name: Extract image from multi-arch image 158 | run: skopeo --override-os linux --override-arch amd64 --insecure-policy copy --additional-tag ${{ steps.image-name.outputs.value }}:${{ steps.meta.outputs.version }} oci:image docker-archive:docker.tar 159 | 160 | - name: Upload image as artifact 161 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 162 | with: 163 | name: "[${{ github.job }}] Docker tarball" 164 | path: docker.tar 165 | 166 | - name: Run Trivy vulnerability scanner 167 | uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0 168 | with: 169 | input: image 170 | format: sarif 171 | output: trivy-results.sarif 172 | 173 | - name: Upload Trivy scan results as artifact 174 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 175 | with: 176 | name: "[${{ github.job }}] Trivy scan results" 177 | path: trivy-results.sarif 178 | retention-days: 5 179 | 180 | - name: Upload Trivy scan results to GitHub Security tab 181 | uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 182 | with: 183 | sarif_file: trivy-results.sarif 184 | 185 | binary: 186 | name: Binary 187 | runs-on: ubuntu-latest 188 | 189 | permissions: 190 | contents: write 191 | 192 | steps: 193 | - name: Increase tmpfs size 194 | run: | 195 | echo "=== Original tmpfs size ===" 196 | df -h /run/user/1001 197 | sudo mount -o remount,size=8G /run/user/1001 198 | echo "=== New tmpfs size ===" 199 | df -h /run/user/1001 200 | 201 | - name: Checkout repository 202 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 203 | 204 | - name: Set up Nix 205 | uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 206 | with: 207 | extra_nix_config: | 208 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 209 | 210 | - name: Prepare Nix shell 211 | run: nix develop --impure .#ci 212 | 213 | - name: Determine build command 214 | uses: haya14busa/action-cond@94f77f7a80cd666cb3155084e428254fea4281fd # v1.2.1 215 | id: build-command 216 | with: 217 | cond: ${{ inputs.release }} 218 | if_true: goreleaser release 219 | if_false: goreleaser release --skip=publish --snapshot 220 | 221 | - name: Build 222 | run: nix develop --impure .#ci -c ${{ steps.build-command.outputs.value }} 223 | env: 224 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 225 | 226 | - name: Upload artifacts 227 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 228 | with: 229 | name: "${{ github.job }}" 230 | path: | 231 | build/dist/*.tar.gz 232 | build/dist/checksums.txt 233 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | permissions: 9 | contents: read 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github. run_id }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | build: 17 | name: Build 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 23 | 24 | - name: Set up Nix 25 | uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 26 | with: 27 | extra_nix_config: | 28 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 29 | 30 | - name: Set up magic Nix cache 31 | uses: DeterminateSystems/magic-nix-cache-action@6221693898146dc97e38ad0e013488a16477a4c4 # v9 32 | 33 | - name: Set up Go cache 34 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 35 | with: 36 | path: | 37 | ~/.cache/go-build 38 | ~/go/pkg/mod 39 | key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 40 | restore-keys: | 41 | ${{ github.job }}-${{ runner.os }}-go- 42 | 43 | - name: Prepare Nix shell 44 | run: nix develop --impure .#ci 45 | 46 | - name: Build 47 | run: nix develop --impure .#ci -c make build 48 | 49 | test: 50 | name: Test 51 | runs-on: ubuntu-latest 52 | 53 | steps: 54 | - name: Checkout repository 55 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 56 | 57 | - name: Set up Nix 58 | uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 59 | with: 60 | extra_nix_config: | 61 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 62 | 63 | - name: Set up magic Nix cache 64 | uses: DeterminateSystems/magic-nix-cache-action@6221693898146dc97e38ad0e013488a16477a4c4 # v9 65 | 66 | - name: Set up Go cache 67 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 68 | with: 69 | path: | 70 | ~/.cache/go-build 71 | ~/go/pkg/mod 72 | key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 73 | restore-keys: | 74 | ${{ github.job }}-${{ runner.os }}-go- 75 | 76 | - name: Prepare Nix shell 77 | run: nix develop --impure .#ci 78 | 79 | - name: Test 80 | run: nix develop --impure .#ci -c make test 81 | 82 | lint: 83 | name: Lint 84 | runs-on: ubuntu-latest 85 | 86 | steps: 87 | - name: Checkout repository 88 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 89 | 90 | - name: Set up Nix 91 | uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 92 | with: 93 | extra_nix_config: | 94 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 95 | 96 | - name: Set up magic Nix cache 97 | uses: DeterminateSystems/magic-nix-cache-action@6221693898146dc97e38ad0e013488a16477a4c4 # v9 98 | 99 | - name: Set up Go cache 100 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 101 | with: 102 | path: | 103 | ~/.cache/go-build 104 | ~/go/pkg/mod 105 | key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 106 | restore-keys: | 107 | ${{ github.job }}-${{ runner.os }}-go- 108 | 109 | - name: Prepare Nix shell 110 | run: nix develop --impure .#ci 111 | 112 | - name: Lint 113 | run: nix develop --impure .#ci -c make lint -j 114 | 115 | license-check: 116 | name: License check 117 | runs-on: ubuntu-latest 118 | 119 | steps: 120 | - name: Checkout repository 121 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 122 | 123 | - name: Set up Nix 124 | uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 125 | with: 126 | extra_nix_config: | 127 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 128 | 129 | - name: Set up magic Nix cache 130 | uses: DeterminateSystems/magic-nix-cache-action@6221693898146dc97e38ad0e013488a16477a4c4 # v9 131 | 132 | - name: Set up Go cache 133 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 134 | with: 135 | path: | 136 | ~/.cache/go-build 137 | ~/go/pkg/mod 138 | key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 139 | restore-keys: | 140 | ${{ github.job }}-${{ runner.os }}-go- 141 | 142 | - name: Cache license information 143 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 144 | with: 145 | path: .licensei.cache 146 | key: licensei-v1-${{ github.ref_name }}-${{ hashFiles('go.sum') }} 147 | restore-keys: | 148 | licensei-v1-${{ github.ref_name }} 149 | licensei-v1-main 150 | licensei-v1 151 | 152 | - name: Prepare Nix shell 153 | run: nix develop --impure .#ci 154 | 155 | - name: Populate license cache 156 | run: nix develop --impure .#ci -c licensei cache 157 | env: 158 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 159 | 160 | - name: Check licenses 161 | run: nix develop --impure .#ci -c make license-check 162 | env: 163 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 164 | 165 | dev: 166 | name: Developer environment 167 | runs-on: ubuntu-latest 168 | 169 | steps: 170 | - name: Checkout repository 171 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 172 | 173 | - name: Set up Nix 174 | uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 175 | with: 176 | extra_nix_config: | 177 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 178 | 179 | - name: Set up magic Nix cache 180 | uses: DeterminateSystems/magic-nix-cache-action@6221693898146dc97e38ad0e013488a16477a4c4 # v9 181 | 182 | - name: Check 183 | run: nix flake check --impure 184 | 185 | - name: Dev shell 186 | run: nix develop --impure 187 | 188 | artifacts: 189 | name: Artifacts 190 | uses: ./.github/workflows/artifacts.yaml 191 | with: 192 | publish: ${{ github.event_name == 'push' }} 193 | permissions: 194 | contents: write 195 | packages: write 196 | id-token: write 197 | security-events: write 198 | 199 | dependency-review: 200 | name: Dependency review 201 | runs-on: ubuntu-latest 202 | if: github.event_name == 'pull_request' 203 | 204 | steps: 205 | - name: Checkout repository 206 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 207 | 208 | - name: Dependency Review 209 | uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 210 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: PR 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - reopened 9 | - synchronize 10 | 11 | jobs: 12 | common: 13 | uses: bank-vaults/.github/.github/workflows/_pr-common.yml@main 14 | permissions: 15 | pull-requests: write 16 | issues: write 17 | -------------------------------------------------------------------------------- /.github/workflows/project.yml: -------------------------------------------------------------------------------- 1 | name: Project 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * 0" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | common: 10 | uses: bank-vaults/.github/.github/workflows/_project-common.yml@main 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v[0-9]+.[0-9]+.[0-9]+" 7 | - "v[0-9]+.[0-9]+.[0-9]+-dev.[0-9]+" 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | artifacts: 14 | name: Artifacts 15 | uses: ./.github/workflows/artifacts.yaml 16 | with: 17 | publish: true 18 | release: true 19 | permissions: 20 | contents: write 21 | packages: write 22 | id-token: write 23 | security-events: write 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.devenv/ 2 | /.direnv/ 3 | /.pre-commit-config.yaml 4 | /bin/ 5 | /build/ 6 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | run: 3 | timeout: 10m 4 | 5 | formatters: 6 | settings: 7 | gci: 8 | sections: 9 | - standard 10 | - default 11 | - prefix(github.com/bank-vaults/vault-env) 12 | goimports: 13 | local-prefixes: 14 | - github.com/bank-vaults/vault-env 15 | gofmt: 16 | simplify: true 17 | gofumpt: 18 | extra-rules: false 19 | 20 | linters: 21 | settings: 22 | misspell: 23 | locale: US 24 | nolintlint: 25 | allow-unused: false # report any unused nolint directives 26 | require-specific: false # don't require nolint directives to be specific about which linter is being skipped 27 | revive: 28 | confidence: 0.1 29 | enable: 30 | - bodyclose 31 | - errcheck 32 | - ineffassign 33 | - misspell 34 | - nolintlint 35 | - revive 36 | - unconvert 37 | - unparam 38 | - unused 39 | - whitespace 40 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | project_name: vault-env 4 | 5 | dist: build/dist 6 | 7 | before: 8 | hooks: 9 | - go mod tidy 10 | builds: 11 | - env: 12 | - CGO_ENABLED=0 13 | ldflags: "-s -w -X main.Version={{ .Version }}" 14 | main: . 15 | goos: 16 | - linux 17 | - darwin 18 | goarch: 19 | - amd64 20 | - arm64 21 | 22 | archives: 23 | - format: tar.gz 24 | # this name template makes the OS and Arch compatible with the results of uname. 25 | name_template: >- 26 | {{ .ProjectName }}_ 27 | {{- title .Os }}_ 28 | {{- if eq .Arch "amd64" }}x86_64 29 | {{- else if eq .Arch "386" }}i386 30 | {{- else }}{{ .Arch }}{{ end }} 31 | {{- if .Arm }}v{{ .Arm }}{{ end }} 32 | 33 | checksum: 34 | name_template: "checksums.txt" 35 | 36 | changelog: 37 | disable: true 38 | -------------------------------------------------------------------------------- /.hadolint.yaml: -------------------------------------------------------------------------------- 1 | ignored: 2 | - DL3018 3 | - DL3059 4 | -------------------------------------------------------------------------------- /.licensei.toml: -------------------------------------------------------------------------------- 1 | approved = [ 2 | "mit", 3 | "apache-2.0", 4 | "bsd-3-clause", 5 | "bsd-2-clause", 6 | "mpl-2.0", 7 | "isc" 8 | ] 9 | 10 | ignored = [ 11 | "github.com/aliyun/aliyun-oss-go-sdk", # Apache License 2.0. 12 | "github.com/ghodss/yaml", # MIT 13 | "sigs.k8s.io/yaml", # Forked from above 14 | "github.com/gogo/protobuf", # 3-Clause BSD 15 | "logur.dev/adapter/logrus", # MIT 16 | "logur.dev/logur", # MIT 17 | "emperror.dev/errors", # MIT 18 | "github.com/hashicorp/vault/api", # Mozilla Public License 2.0 19 | "github.com/hashicorp/vault/api/auth/aws", # Mozilla Public License 2.0 20 | "github.com/hashicorp/vault/api/auth/azure", # Mozilla Public License 2.0 21 | "github.com/hashicorp/vault/api/auth/gcp", # Mozilla Public License 2.0 22 | "github.com/hashicorp/vault/api/auth/kubernetes", # Mozilla Public License 2.0 23 | 24 | # Unsupported VCS 25 | "gopkg.in/fsnotify.v1", 26 | "gopkg.in/square/go-jose.v2", # Apache 2.0 27 | "google.golang.org/grpc", 28 | "google.golang.org/genproto", 29 | "google.golang.org/api", 30 | "google.golang.org/protobuf", 31 | "cloud.google.com/go", 32 | "cloud.google.com/go/storage", 33 | 34 | "gomodules.xyz/orderedmap", # MIT 35 | "github.com/form3tech-oss/jwt-go", # MIT 36 | "gomodules.xyz/jsonpatch/v2", # Apache 2.0 37 | "gomodules.xyz/jsonpatch/v3", # Apache 2.0 38 | ] 39 | 40 | [header] 41 | authors = ["Banzai Cloud", "Bank-Vaults Maintainers"] 42 | ignorePaths = [".direnv", ".devenv", "vendor"] 43 | ignoreFiles = ["zz_generated.*.go"] 44 | template = """// Copyright © :YEAR: :AUTHOR: 45 | // 46 | // Licensed under the Apache License, Version 2.0 (the "License"); 47 | // you may not use this file except in compliance with the License. 48 | // You may obtain a copy of the License at 49 | // 50 | // http://www.apache.org/licenses/LICENSE-2.0 51 | // 52 | // Unless required by applicable law or agreed to in writing, software 53 | // distributed under the License is distributed on an "AS IS" BASIS, 54 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 55 | // See the License for the specific language governing permissions and 56 | // limitations under the License.""" 57 | -------------------------------------------------------------------------------- /.yamlignore: -------------------------------------------------------------------------------- 1 | /.github/ 2 | -------------------------------------------------------------------------------- /.yamllint.yaml: -------------------------------------------------------------------------------- 1 | ignore-from-file: [.gitignore, .yamlignore] 2 | 3 | extends: default 4 | 5 | rules: 6 | line-length: disable 7 | document-start: disable 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.6.1@sha256:923441d7c25f1e2eb5789f82d987693c47b8ed987c4ab3b075d6ed2b5d6779a3 AS xx 2 | 3 | FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine3.20@sha256:9f98e9893fbc798c710f3432baa1e0ac6127799127c3101d2c263c3a954f0abe AS builder 4 | 5 | COPY --from=xx / / 6 | 7 | RUN apk add --update --no-cache ca-certificates make git curl clang lld 8 | 9 | ARG TARGETPLATFORM 10 | 11 | RUN xx-apk --update --no-cache add musl-dev gcc 12 | 13 | RUN xx-go --wrap 14 | 15 | WORKDIR /usr/local/src/vault-env 16 | 17 | ARG GOPROXY 18 | 19 | ENV CGO_ENABLED=0 20 | 21 | COPY go.* ./ 22 | RUN go mod download 23 | 24 | COPY . . 25 | 26 | RUN go build -ldflags "-s -w" -o /usr/local/bin/vault-env . 27 | RUN xx-verify /usr/local/bin/vault-env 28 | 29 | 30 | FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c 31 | 32 | RUN apk add --update --no-cache ca-certificates tzdata 33 | 34 | COPY --from=builder /usr/local/bin/vault-env /usr/local/bin/vault-env 35 | 36 | USER 65534 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html 2 | 3 | export PATH := $(abspath bin/):${PATH} 4 | 5 | ##@ General 6 | 7 | # Targets commented with ## will be visible in "make help" info. 8 | # Comments marked with ##@ will be used as categories for a group of targets. 9 | 10 | .PHONY: help 11 | default: help 12 | help: ## Display this help 13 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 14 | 15 | ##@ Development 16 | 17 | .PHONY: up 18 | up: ## Start development environment 19 | docker compose up -d 20 | 21 | .PHONY: down 22 | down: ## Destroy development environment 23 | docker compose down -v 24 | 25 | ##@ Build 26 | 27 | .PHONY: build 28 | build: ## Build binary 29 | @mkdir -p build 30 | go build -race -o build/vault-env . 31 | 32 | .PHONY: artifacts 33 | artifacts: container-image binary-snapshot 34 | artifacts: ## Build artifacts 35 | 36 | .PHONY: container-image 37 | container-image: ## Build container image 38 | docker build . 39 | 40 | .PHONY: binary-snapshot 41 | binary-snapshot: ## Build binary snapshot 42 | VERSION=v${GORELEASER_VERSION} ${GORELEASER_BIN} release --clean --skip=publish --snapshot 43 | 44 | ##@ Checks 45 | 46 | .PHONY: check 47 | check: test lint ## Run tests lint checks 48 | 49 | .PHONY: test 50 | test: ## Run tests 51 | go test -race -v ./... 52 | 53 | .PHONY: lint 54 | lint: lint-go lint-docker lint-yaml 55 | lint: ## Run linters 56 | 57 | .PHONY: lint-go 58 | lint-go: 59 | $(GOLANGCI_LINT_BIN) run 60 | 61 | .PHONY: lint-docker 62 | lint-docker: 63 | $(HADOLINT_BIN) Dockerfile 64 | 65 | .PHONY: lint-yaml 66 | lint-yaml: 67 | $(YAMLLINT_BIN) $(if ${CI},-f github,) --no-warnings . 68 | 69 | .PHONY: fmt 70 | fmt: ## Format code 71 | $(GOLANGCI_LINT_BIN) run --fix 72 | 73 | .PHONY: license-check 74 | license-check: ## Run license check 75 | $(LICENSEI_BIN) check 76 | $(LICENSEI_BIN) header 77 | 78 | ##@ Dependencies 79 | 80 | deps: bin/golangci-lint bin/cosign bin/licensei bin/goreleaser 81 | deps: ## Install dependencies 82 | 83 | # Dependency versions 84 | GOLANGCI_LINT_VERSION = 2.0.2 85 | LICENSEI_VERSION = 0.9.0 86 | COSIGN_VERSION = 2.4.1 87 | GORELEASER_VERSION = 2.4.8 88 | 89 | # Dependency binaries 90 | GOLANGCI_LINT_BIN := golangci-lint 91 | COSIGN_BIN := cosign 92 | LICENSEI_BIN := licensei 93 | GORELEASER_BIN := goreleaser 94 | 95 | # TODO: add support for hadolint and yamllint dependencies 96 | HADOLINT_BIN := hadolint 97 | YAMLLINT_BIN := yamllint 98 | 99 | # If we have "bin" dir, use those binaries instead 100 | ifneq ($(wildcard ./bin/.),) 101 | GOLANGCI_LINT_BIN := bin/$(GOLANGCI_LINT_BIN) 102 | COSIGN_BIN := bin/$(COSIGN_BIN) 103 | LICENSEI_BIN := bin/$(LICENSEI_BIN) 104 | GORELEASER_BIN := bin/$(GORELEASER_BIN) 105 | endif 106 | 107 | bin/golangci-lint: 108 | @mkdir -p bin 109 | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- v${GOLANGCI_LINT_VERSION} 110 | 111 | bin/licensei: 112 | @mkdir -p bin 113 | curl -sfL https://raw.githubusercontent.com/goph/licensei/master/install.sh | bash -s -- v${LICENSEI_VERSION} 114 | 115 | bin/cosign: 116 | @mkdir -p bin 117 | @OS=$$(uname -s); \ 118 | case $$OS in \ 119 | "Linux") \ 120 | curl -sSfL https://github.com/sigstore/cosign/releases/download/v${COSIGN_VERSION}/cosign-linux-amd64 -o bin/cosign; \ 121 | ;; \ 122 | "Darwin") \ 123 | curl -sSfL https://github.com/sigstore/cosign/releases/download/v${COSIGN_VERSION}/cosign-darwin-arm64 -o bin/cosign; \ 124 | ;; \ 125 | *) \ 126 | echo "Unsupported OS: $$OS"; \ 127 | exit 1; \ 128 | ;; \ 129 | esac 130 | @chmod +x bin/cosign 131 | 132 | 133 | bin/goreleaser: 134 | @mkdir -p bin 135 | curl -sfL https://goreleaser.com/static/run -o bin/goreleaser 136 | @chmod +x bin/goreleaser 137 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright © 2018 Banzai Cloud 2 | Copyright © 2021 Cisco Systems, Inc. and/or its affiliates 3 | Copyright © 2023 Bank-Vaults Maintainers 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `vault-env` 2 | 3 | [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bank-vaults/vault-env/ci.yaml?branch=main&style=flat-square)](https://github.com/bank-vaults/vault-env/actions/workflows/ci.yaml?query=workflow%3ACI) 4 | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/bank-vaults/vault-env/badge?style=flat-square)](https://api.securityscorecards.dev/projects/github.com/bank-vaults/vault-env) 5 | [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8062/badge)](https://www.bestpractices.dev/projects/8062) 6 | 7 | **Minimalistic init system for containers with [Hashicorp Vault](https://www.vaultproject.io/) secrets support .** 8 | 9 | ## Usage 10 | 11 | `vault-env` is designed for use with the [Kubernetes mutating webhook](https://bank-vaults.dev/docs/mutating-webhook/); however, it can also function as a standalone tool. 12 | 13 | ## Development 14 | 15 | **For an optimal developer experience, it is recommended to install [Nix](https://nixos.org/download.html) and [direnv](https://direnv.net/docs/installation.html).** 16 | 17 | _Alternatively, install [Go](https://go.dev/dl/) on your computer then run `make deps` to install the rest of the dependencies._ 18 | 19 | Make sure Docker is installed with Compose and Buildx. 20 | 21 | Run project dependencies: 22 | 23 | ```shell 24 | make up 25 | ``` 26 | 27 | Build a binary: 28 | 29 | ```shell 30 | make build 31 | ``` 32 | 33 | Run the test suite: 34 | 35 | ```shell 36 | make test 37 | ``` 38 | 39 | Run linters: 40 | 41 | ```shell 42 | make lint # pass -j option to run them in parallel 43 | ``` 44 | 45 | Some linter violations can automatically be fixed: 46 | 47 | ```shell 48 | make fmt 49 | ``` 50 | 51 | Build artifacts locally: 52 | 53 | ```shell 54 | make artifacts 55 | ``` 56 | 57 | Once you are done either stop or tear down dependencies: 58 | 59 | ```shell 60 | make down 61 | ``` 62 | 63 | ## License 64 | 65 | The project is licensed under the [Apache 2.0 License](LICENSE). 66 | -------------------------------------------------------------------------------- /client_logger.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2023 Bank-Vaults Maintainers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "log/slog" 19 | 20 | "github.com/bank-vaults/vault-sdk/vault" 21 | ) 22 | 23 | var _ vault.Logger = &clientLogger{} 24 | 25 | type clientLogger struct { 26 | logger *slog.Logger 27 | } 28 | 29 | func (l clientLogger) Trace(msg string, args ...map[string]interface{}) { 30 | l.Debug(msg, args...) 31 | } 32 | 33 | func (l clientLogger) Debug(msg string, args ...map[string]interface{}) { 34 | l.logger.Debug(msg, l.argsToAttrs(args...)...) 35 | } 36 | 37 | func (l clientLogger) Info(msg string, args ...map[string]interface{}) { 38 | l.logger.Info(msg, l.argsToAttrs(args...)...) 39 | } 40 | 41 | func (l clientLogger) Warn(msg string, args ...map[string]interface{}) { 42 | l.logger.Warn(msg, l.argsToAttrs(args...)...) 43 | } 44 | 45 | func (l clientLogger) Error(msg string, args ...map[string]interface{}) { 46 | l.logger.Error(msg, l.argsToAttrs(args...)...) 47 | } 48 | 49 | func (clientLogger) argsToAttrs(args ...map[string]interface{}) []any { 50 | var attrs []any 51 | 52 | for _, arg := range args { 53 | for key, value := range arg { 54 | attrs = append(attrs, slog.Any(key, value)) 55 | } 56 | } 57 | 58 | return attrs 59 | } 60 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | vault: 5 | image: hashicorp/vault:1.14.8 6 | ports: 7 | - 127.0.0.1:8200:8200 8 | environment: 9 | SKIP_SETCAP: true 10 | VAULT_DEV_ROOT_TOKEN_ID: 227e1cce-6bf7-30bb-2d2a-acc854318caf 11 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "cachix": { 4 | "inputs": { 5 | "devenv": [ 6 | "devenv" 7 | ], 8 | "flake-compat": [ 9 | "devenv" 10 | ], 11 | "git-hooks": [ 12 | "devenv" 13 | ], 14 | "nixpkgs": "nixpkgs" 15 | }, 16 | "locked": { 17 | "lastModified": 1744206633, 18 | "narHash": "sha256-pb5aYkE8FOoa4n123slgHiOf1UbNSnKe5pEZC+xXD5g=", 19 | "owner": "cachix", 20 | "repo": "cachix", 21 | "rev": "8a60090640b96f9df95d1ab99e5763a586be1404", 22 | "type": "github" 23 | }, 24 | "original": { 25 | "owner": "cachix", 26 | "ref": "latest", 27 | "repo": "cachix", 28 | "type": "github" 29 | } 30 | }, 31 | "devenv": { 32 | "inputs": { 33 | "cachix": "cachix", 34 | "flake-compat": "flake-compat", 35 | "git-hooks": "git-hooks", 36 | "nix": "nix", 37 | "nixpkgs": "nixpkgs_3" 38 | }, 39 | "locked": { 40 | "lastModified": 1747543288, 41 | "narHash": "sha256-W+E2xxaKSQtafQX7KqNwfFm10RrqnSLzKEoA2iZ+VbM=", 42 | "owner": "cachix", 43 | "repo": "devenv", 44 | "rev": "3a8a52386bde1cf14fc2f4c4df80f91417348480", 45 | "type": "github" 46 | }, 47 | "original": { 48 | "owner": "cachix", 49 | "repo": "devenv", 50 | "type": "github" 51 | } 52 | }, 53 | "flake-compat": { 54 | "flake": false, 55 | "locked": { 56 | "lastModified": 1733328505, 57 | "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", 58 | "owner": "edolstra", 59 | "repo": "flake-compat", 60 | "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", 61 | "type": "github" 62 | }, 63 | "original": { 64 | "owner": "edolstra", 65 | "repo": "flake-compat", 66 | "type": "github" 67 | } 68 | }, 69 | "flake-parts": { 70 | "inputs": { 71 | "nixpkgs-lib": [ 72 | "devenv", 73 | "nix", 74 | "nixpkgs" 75 | ] 76 | }, 77 | "locked": { 78 | "lastModified": 1712014858, 79 | "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", 80 | "owner": "hercules-ci", 81 | "repo": "flake-parts", 82 | "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", 83 | "type": "github" 84 | }, 85 | "original": { 86 | "owner": "hercules-ci", 87 | "repo": "flake-parts", 88 | "type": "github" 89 | } 90 | }, 91 | "flake-parts_2": { 92 | "inputs": { 93 | "nixpkgs-lib": "nixpkgs-lib" 94 | }, 95 | "locked": { 96 | "lastModified": 1743550720, 97 | "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", 98 | "owner": "hercules-ci", 99 | "repo": "flake-parts", 100 | "rev": "c621e8422220273271f52058f618c94e405bb0f5", 101 | "type": "github" 102 | }, 103 | "original": { 104 | "owner": "hercules-ci", 105 | "repo": "flake-parts", 106 | "type": "github" 107 | } 108 | }, 109 | "git-hooks": { 110 | "inputs": { 111 | "flake-compat": [ 112 | "devenv" 113 | ], 114 | "gitignore": "gitignore", 115 | "nixpkgs": [ 116 | "devenv", 117 | "nixpkgs" 118 | ] 119 | }, 120 | "locked": { 121 | "lastModified": 1746537231, 122 | "narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=", 123 | "owner": "cachix", 124 | "repo": "git-hooks.nix", 125 | "rev": "fa466640195d38ec97cf0493d6d6882bc4d14969", 126 | "type": "github" 127 | }, 128 | "original": { 129 | "owner": "cachix", 130 | "repo": "git-hooks.nix", 131 | "type": "github" 132 | } 133 | }, 134 | "gitignore": { 135 | "inputs": { 136 | "nixpkgs": [ 137 | "devenv", 138 | "git-hooks", 139 | "nixpkgs" 140 | ] 141 | }, 142 | "locked": { 143 | "lastModified": 1709087332, 144 | "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", 145 | "owner": "hercules-ci", 146 | "repo": "gitignore.nix", 147 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 148 | "type": "github" 149 | }, 150 | "original": { 151 | "owner": "hercules-ci", 152 | "repo": "gitignore.nix", 153 | "type": "github" 154 | } 155 | }, 156 | "libgit2": { 157 | "flake": false, 158 | "locked": { 159 | "lastModified": 1697646580, 160 | "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", 161 | "owner": "libgit2", 162 | "repo": "libgit2", 163 | "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", 164 | "type": "github" 165 | }, 166 | "original": { 167 | "owner": "libgit2", 168 | "repo": "libgit2", 169 | "type": "github" 170 | } 171 | }, 172 | "nix": { 173 | "inputs": { 174 | "flake-compat": [ 175 | "devenv" 176 | ], 177 | "flake-parts": "flake-parts", 178 | "libgit2": "libgit2", 179 | "nixpkgs": "nixpkgs_2", 180 | "nixpkgs-23-11": [ 181 | "devenv" 182 | ], 183 | "nixpkgs-regression": [ 184 | "devenv" 185 | ], 186 | "pre-commit-hooks": [ 187 | "devenv" 188 | ] 189 | }, 190 | "locked": { 191 | "lastModified": 1745930071, 192 | "narHash": "sha256-bYyjarS3qSNqxfgc89IoVz8cAFDkF9yPE63EJr+h50s=", 193 | "owner": "domenkozar", 194 | "repo": "nix", 195 | "rev": "b455edf3505f1bf0172b39a735caef94687d0d9c", 196 | "type": "github" 197 | }, 198 | "original": { 199 | "owner": "domenkozar", 200 | "ref": "devenv-2.24", 201 | "repo": "nix", 202 | "type": "github" 203 | } 204 | }, 205 | "nixpkgs": { 206 | "locked": { 207 | "lastModified": 1733212471, 208 | "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", 209 | "owner": "NixOS", 210 | "repo": "nixpkgs", 211 | "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", 212 | "type": "github" 213 | }, 214 | "original": { 215 | "owner": "NixOS", 216 | "ref": "nixos-unstable", 217 | "repo": "nixpkgs", 218 | "type": "github" 219 | } 220 | }, 221 | "nixpkgs-lib": { 222 | "locked": { 223 | "lastModified": 1743296961, 224 | "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", 225 | "owner": "nix-community", 226 | "repo": "nixpkgs.lib", 227 | "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", 228 | "type": "github" 229 | }, 230 | "original": { 231 | "owner": "nix-community", 232 | "repo": "nixpkgs.lib", 233 | "type": "github" 234 | } 235 | }, 236 | "nixpkgs_2": { 237 | "locked": { 238 | "lastModified": 1717432640, 239 | "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", 240 | "owner": "NixOS", 241 | "repo": "nixpkgs", 242 | "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", 243 | "type": "github" 244 | }, 245 | "original": { 246 | "owner": "NixOS", 247 | "ref": "release-24.05", 248 | "repo": "nixpkgs", 249 | "type": "github" 250 | } 251 | }, 252 | "nixpkgs_3": { 253 | "locked": { 254 | "lastModified": 1746807397, 255 | "narHash": "sha256-zU2z0jlkJGWLhdNr/8AJSxqK8XD0IlQgHp3VZcP56Aw=", 256 | "owner": "cachix", 257 | "repo": "devenv-nixpkgs", 258 | "rev": "c5208b594838ea8e6cca5997fbf784b7cca1ca90", 259 | "type": "github" 260 | }, 261 | "original": { 262 | "owner": "cachix", 263 | "ref": "rolling", 264 | "repo": "devenv-nixpkgs", 265 | "type": "github" 266 | } 267 | }, 268 | "nixpkgs_4": { 269 | "locked": { 270 | "lastModified": 1747467164, 271 | "narHash": "sha256-JBXbjJ0t6T6BbVc9iPVquQI9XSXCGQJD8c8SgnUquus=", 272 | "owner": "NixOS", 273 | "repo": "nixpkgs", 274 | "rev": "3fcbdcfc707e0aa42c541b7743e05820472bdaec", 275 | "type": "github" 276 | }, 277 | "original": { 278 | "owner": "NixOS", 279 | "ref": "nixpkgs-unstable", 280 | "repo": "nixpkgs", 281 | "type": "github" 282 | } 283 | }, 284 | "root": { 285 | "inputs": { 286 | "devenv": "devenv", 287 | "flake-parts": "flake-parts_2", 288 | "nixpkgs": "nixpkgs_4" 289 | } 290 | } 291 | }, 292 | "root": "root", 293 | "version": 7 294 | } 295 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Go libraries for interacting with Hashicorp Vault"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 6 | flake-parts.url = "github:hercules-ci/flake-parts"; 7 | devenv.url = "github:cachix/devenv"; 8 | }; 9 | 10 | outputs = inputs@{ flake-parts, ... }: 11 | flake-parts.lib.mkFlake { inherit inputs; } { 12 | imports = [ 13 | inputs.devenv.flakeModule 14 | ]; 15 | 16 | systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ]; 17 | 18 | perSystem = { config, self', inputs', pkgs, system, ... }: rec { 19 | devenv.shells = { 20 | default = { 21 | languages = { 22 | go.enable = true; 23 | go.package = pkgs.go_1_24; 24 | }; 25 | 26 | services = { 27 | vault = { 28 | enable = true; 29 | package = self'.packages.vault; 30 | }; 31 | }; 32 | 33 | pre-commit.hooks = { 34 | nixpkgs-fmt.enable = true; 35 | yamllint.enable = true; 36 | hadolint.enable = true; 37 | }; 38 | 39 | packages = with pkgs; [ 40 | gnumake 41 | 42 | goreleaser 43 | 44 | golangci-lint 45 | yamllint 46 | hadolint 47 | ] ++ [ 48 | self'.packages.licensei 49 | ]; 50 | 51 | env = { 52 | KUBECONFIG = "${config.devenv.shells.default.env.DEVENV_STATE}/kube/config"; 53 | 54 | VAULT_ADDR = "http://127.0.0.1:8200"; 55 | VAULT_TOKEN = "227e1cce-6bf7-30bb-2d2a-acc854318caf"; 56 | }; 57 | 58 | # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 59 | containers = pkgs.lib.mkForce { }; 60 | }; 61 | 62 | ci = devenv.shells.default; 63 | }; 64 | 65 | packages = { 66 | # TODO: create flake in source repo 67 | licensei = pkgs.buildGoModule rec { 68 | pname = "licensei"; 69 | version = "0.8.0"; 70 | 71 | src = pkgs.fetchFromGitHub { 72 | owner = "goph"; 73 | repo = "licensei"; 74 | rev = "v${version}"; 75 | sha256 = "sha256-Pvjmvfk0zkY2uSyLwAtzWNn5hqKImztkf8S6OhX8XoM="; 76 | }; 77 | 78 | vendorHash = "sha256-ZIpZ2tPLHwfWiBywN00lPI1R7u7lseENIiybL3+9xG8="; 79 | 80 | subPackages = [ "cmd/licensei" ]; 81 | 82 | ldflags = [ 83 | "-w" 84 | "-s" 85 | "-X main.version=v${version}" 86 | ]; 87 | }; 88 | 89 | vault = pkgs.buildGoModule rec { 90 | pname = "vault"; 91 | version = "1.14.8"; 92 | 93 | src = pkgs.fetchFromGitHub { 94 | owner = "hashicorp"; 95 | repo = "vault"; 96 | rev = "v${version}"; 97 | sha256 = "sha256-sGCODCBgsxyr96zu9ntPmMM/gHVBBO+oo5+XsdbCK4E="; 98 | }; 99 | 100 | vendorHash = "sha256-zpHjZjgCgf4b2FAJQ22eVgq0YGoVvxGYJ3h/3ZRiyrQ="; 101 | 102 | proxyVendor = true; 103 | 104 | subPackages = [ "." ]; 105 | 106 | tags = [ "vault" ]; 107 | ldflags = [ 108 | "-s" 109 | "-w" 110 | "-X github.com/hashicorp/vault/sdk/version.GitCommit=${src.rev}" 111 | "-X github.com/hashicorp/vault/sdk/version.Version=${version}" 112 | "-X github.com/hashicorp/vault/sdk/version.VersionPrerelease=" 113 | ]; 114 | }; 115 | }; 116 | }; 117 | }; 118 | } 119 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/bank-vaults/vault-env 2 | 3 | go 1.24.1 4 | 5 | require ( 6 | emperror.dev/errors v0.8.1 7 | github.com/bank-vaults/vault-sdk v0.10.2 8 | github.com/hashicorp/vault/api v1.16.0 9 | github.com/samber/slog-multi v1.4.0 10 | github.com/samber/slog-syslog v1.0.0 11 | github.com/spf13/cast v1.8.0 12 | ) 13 | 14 | require ( 15 | cel.dev/expr v0.19.1 // indirect 16 | cloud.google.com/go v0.116.0 // indirect 17 | cloud.google.com/go/auth v0.12.1 // indirect 18 | cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect 19 | cloud.google.com/go/compute/metadata v0.6.0 // indirect 20 | cloud.google.com/go/iam v1.3.0 // indirect 21 | cloud.google.com/go/kms v1.20.2 // indirect 22 | cloud.google.com/go/longrunning v0.6.3 // indirect 23 | cloud.google.com/go/monitoring v1.22.0 // indirect 24 | cloud.google.com/go/storage v1.48.0 // indirect 25 | dario.cat/mergo v1.0.1 // indirect 26 | github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect 27 | github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 // indirect 28 | github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect 29 | github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 // indirect 30 | github.com/Azure/go-autorest v14.2.0+incompatible // indirect 31 | github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect 32 | github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect 33 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect 34 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 // indirect 35 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect 36 | github.com/Masterminds/goutils v1.1.1 // indirect 37 | github.com/Masterminds/semver/v3 v3.3.1 // indirect 38 | github.com/Masterminds/sprig/v3 v3.3.0 // indirect 39 | github.com/aws/aws-sdk-go v1.55.5 // indirect 40 | github.com/aws/aws-sdk-go-v2 v1.32.6 // indirect 41 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect 42 | github.com/aws/aws-sdk-go-v2/config v1.28.6 // indirect 43 | github.com/aws/aws-sdk-go-v2/credentials v1.17.47 // indirect 44 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 // indirect 45 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.43 // indirect 46 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect 47 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect 48 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect 49 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25 // indirect 50 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect 51 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6 // indirect 52 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 // indirect 53 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 // indirect 54 | github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 // indirect 55 | github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect 56 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 // indirect 57 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 // indirect 58 | github.com/aws/smithy-go v1.22.1 // indirect 59 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 60 | github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect 61 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 62 | github.com/cncf/xds/go v0.0.0-20241213214725-57cfbe6fad57 // indirect 63 | github.com/envoyproxy/go-control-plane v0.13.1 // indirect 64 | github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect 65 | github.com/fatih/color v1.18.0 // indirect 66 | github.com/felixge/httpsnoop v1.0.4 // indirect 67 | github.com/fsnotify/fsnotify v1.8.0 // indirect 68 | github.com/go-jose/go-jose/v4 v4.0.5 // indirect 69 | github.com/go-logr/logr v1.4.2 // indirect 70 | github.com/go-logr/stdr v1.2.2 // indirect 71 | github.com/golang-jwt/jwt/v5 v5.2.2 // indirect 72 | github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect 73 | github.com/google/s2a-go v0.1.8 // indirect 74 | github.com/google/uuid v1.6.0 // indirect 75 | github.com/google/wire v0.6.0 // indirect 76 | github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect 77 | github.com/googleapis/gax-go/v2 v2.14.0 // indirect 78 | github.com/hashicorp/errwrap v1.1.0 // indirect 79 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 80 | github.com/hashicorp/go-hclog v1.6.3 // indirect 81 | github.com/hashicorp/go-multierror v1.1.1 // indirect 82 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 83 | github.com/hashicorp/go-rootcerts v1.0.2 // indirect 84 | github.com/hashicorp/go-secure-stdlib/awsutil v0.3.0 // indirect 85 | github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 // indirect 86 | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect 87 | github.com/hashicorp/go-sockaddr v1.0.7 // indirect 88 | github.com/hashicorp/go-uuid v1.0.3 // indirect 89 | github.com/hashicorp/hcl v1.0.1-vault-7 // indirect 90 | github.com/hashicorp/vault/api/auth/aws v0.8.0 // indirect 91 | github.com/hashicorp/vault/api/auth/azure v0.7.0 // indirect 92 | github.com/hashicorp/vault/api/auth/gcp v0.8.0 // indirect 93 | github.com/hashicorp/vault/api/auth/kubernetes v0.8.0 // indirect 94 | github.com/huandu/xstrings v1.5.0 // indirect 95 | github.com/jmespath/go-jmespath v0.4.0 // indirect 96 | github.com/kylelemons/godebug v1.1.0 // indirect 97 | github.com/mattn/go-colorable v0.1.13 // indirect 98 | github.com/mattn/go-isatty v0.0.20 // indirect 99 | github.com/mitchellh/copystructure v1.2.0 // indirect 100 | github.com/mitchellh/go-homedir v1.1.0 // indirect 101 | github.com/mitchellh/mapstructure v1.5.0 // indirect 102 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 103 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect 104 | github.com/pkg/errors v0.9.1 // indirect 105 | github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect 106 | github.com/ryanuber/go-glob v1.0.0 // indirect 107 | github.com/samber/lo v1.49.1 // indirect 108 | github.com/shopspring/decimal v1.4.0 // indirect 109 | go.opencensus.io v0.24.0 // indirect 110 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 111 | go.opentelemetry.io/contrib/detectors/gcp v1.33.0 // indirect 112 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect 113 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect 114 | go.opentelemetry.io/otel v1.33.0 // indirect 115 | go.opentelemetry.io/otel/metric v1.33.0 // indirect 116 | go.opentelemetry.io/otel/sdk v1.33.0 // indirect 117 | go.opentelemetry.io/otel/sdk/metric v1.33.0 // indirect 118 | go.opentelemetry.io/otel/trace v1.33.0 // indirect 119 | go.uber.org/multierr v1.11.0 // indirect 120 | gocloud.dev v0.40.0 // indirect 121 | golang.org/x/crypto v0.36.0 // indirect 122 | golang.org/x/net v0.38.0 // indirect 123 | golang.org/x/oauth2 v0.24.0 // indirect 124 | golang.org/x/sync v0.12.0 // indirect 125 | golang.org/x/sys v0.31.0 // indirect 126 | golang.org/x/text v0.23.0 // indirect 127 | golang.org/x/time v0.8.0 // indirect 128 | golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect 129 | google.golang.org/api v0.211.0 // indirect 130 | google.golang.org/genproto v0.0.0-20241209162323-e6fa225c2576 // indirect 131 | google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect 132 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect 133 | google.golang.org/grpc v1.68.1 // indirect 134 | google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3 // indirect 135 | google.golang.org/protobuf v1.35.2 // indirect 136 | gopkg.in/yaml.v2 v2.4.0 // indirect 137 | ) 138 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= 2 | cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= 3 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= 5 | cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= 6 | cloud.google.com/go/auth v0.12.1 h1:n2Bj25BUMM0nvE9D2XLTiImanwZhO3DkfWSYS/SAJP4= 7 | cloud.google.com/go/auth v0.12.1/go.mod h1:BFMu+TNpF3DmvfBO9ClqTR/SiqVIm7LukKF9mbendF4= 8 | cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= 9 | cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= 10 | cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= 11 | cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= 12 | cloud.google.com/go/iam v1.3.0 h1:4Wo2qTaGKFtajbLpF6I4mywg900u3TLlHDb6mriLDPU= 13 | cloud.google.com/go/iam v1.3.0/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= 14 | cloud.google.com/go/kms v1.20.2 h1:NGTHOxAyhDVUGVU5KngeyGScrg2D39X76Aphe6NC7S0= 15 | cloud.google.com/go/kms v1.20.2/go.mod h1:LywpNiVCvzYNJWS9JUcGJSVTNSwPwi0vBAotzDqn2nc= 16 | cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= 17 | cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= 18 | cloud.google.com/go/longrunning v0.6.3 h1:A2q2vuyXysRcwzqDpMMLSI6mb6o39miS52UEG/Rd2ng= 19 | cloud.google.com/go/longrunning v0.6.3/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= 20 | cloud.google.com/go/monitoring v1.22.0 h1:mQ0040B7dpuRq1+4YiQD43M2vW9HgoVxY98xhqGT+YI= 21 | cloud.google.com/go/monitoring v1.22.0/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= 22 | cloud.google.com/go/storage v1.48.0 h1:FhBDHACbVtdPx7S/AbcKujPWiHvfO6F8OXGgCEbB2+o= 23 | cloud.google.com/go/storage v1.48.0/go.mod h1:aFoDYNMAjv67lp+xcuZqjUKv/ctmplzQ3wJgodA7b+M= 24 | cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= 25 | cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= 26 | dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= 27 | dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 28 | emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= 29 | emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= 30 | github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= 31 | github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= 32 | github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= 33 | github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= 34 | github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= 35 | github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= 36 | github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= 37 | github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= 38 | github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c= 39 | github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc= 40 | github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 h1:mlmW46Q0B79I+Aj4azKC6xDMFN9a9SyZWESlGWYXbFs= 41 | github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0/go.mod h1:PXe2h+LKcWTX9afWdZoHyODqR4fBa5boUM/8uJfZ0Jo= 42 | github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= 43 | github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= 44 | github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= 45 | github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= 46 | github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= 47 | github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= 48 | github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= 49 | github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= 50 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 51 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= 52 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= 53 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 h1:o90wcURuxekmXrtxmYWTyNla0+ZEHhud6DI1ZTxd1vI= 54 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0/go.mod h1:6fTWu4m3jocfUZLYF5KsZC1TUfRvEjs7lM4crme/irw= 55 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0 h1:jJKWl98inONJAr/IZrdFQUWcwUO95DLY1XMD1ZIut+g= 56 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0/go.mod h1:l2fIqmwB+FKSfvn3bAD/0i+AXAxhIZjTK2svT/mgUXs= 57 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= 58 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= 59 | github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= 60 | github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 61 | github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= 62 | github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 63 | github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= 64 | github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= 65 | github.com/aws/aws-sdk-go v1.34.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= 66 | github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= 67 | github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= 68 | github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= 69 | github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= 70 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= 71 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= 72 | github.com/aws/aws-sdk-go-v2/config v1.28.6 h1:D89IKtGrs/I3QXOLNTH93NJYtDhm8SYa9Q5CsPShmyo= 73 | github.com/aws/aws-sdk-go-v2/config v1.28.6/go.mod h1:GDzxJ5wyyFSCoLkS+UhGB0dArhb9mI+Co4dHtoTxbko= 74 | github.com/aws/aws-sdk-go-v2/credentials v1.17.47 h1:48bA+3/fCdi2yAwVt+3COvmatZ6jUDNkDTIsqDiMUdw= 75 | github.com/aws/aws-sdk-go-v2/credentials v1.17.47/go.mod h1:+KdckOejLW3Ks3b0E3b5rHsr2f9yuORBum0WPnE5o5w= 76 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= 77 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= 78 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.43 h1:iLdpkYZ4cXIQMO7ud+cqMWR1xK5ESbt1rvN77tRi1BY= 79 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.43/go.mod h1:OgbsKPAswXDd5kxnR4vZov69p3oYjbvUyIRBAAV0y9o= 80 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= 81 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= 82 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= 83 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= 84 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= 85 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= 86 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25 h1:r67ps7oHCYnflpgDy2LZU0MAQtQbYIOqNNnqGO6xQkE= 87 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25/go.mod h1:GrGY+Q4fIokYLtjCVB/aFfCVL6hhGUFl8inD18fDalE= 88 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= 89 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= 90 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6 h1:HCpPsWqmYQieU7SS6E9HXfdAMSud0pteVXieJmcpIRI= 91 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6/go.mod h1:ngUiVRCco++u+soRRVBIvBZxSMMvOVMXA4PJ36JLfSw= 92 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 h1:50+XsN70RS7dwJ2CkVNXzj7U2L1HKP8nqTd3XWEXBN4= 93 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6/go.mod h1:WqgLmwY7so32kG01zD8CPTJWVWM+TzJoOVHwTg4aPug= 94 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 h1:BbGDtTi0T1DYlmjBiCr/le3wzhA37O8QTC5/Ab8+EXk= 95 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6/go.mod h1:hLMJt7Q8ePgViKupeymbqI0la+t9/iYFBjxQCFwuAwI= 96 | github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 h1:nyuzXooUNJexRT0Oy0UQY6AhOzxPxhtt4DcBIHyCnmw= 97 | github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0/go.mod h1:sT/iQz8JK3u/5gZkT+Hmr7GzVZehUMkRZpOaAwYXeGY= 98 | github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 h1:rLnYAfXQ3YAccocshIH5mzNNwZBkBo+bP6EhIxak6Hw= 99 | github.com/aws/aws-sdk-go-v2/service/sso v1.24.7/go.mod h1:ZHtuQJ6t9A/+YDuxOLnbryAmITtr8UysSny3qcyvJTc= 100 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 h1:JnhTZR3PiYDNKlXy50/pNeix9aGMo6lLpXwJ1mw8MD4= 101 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6/go.mod h1:URronUEGfXZN1VpdktPSD1EkAL9mfrV+2F4sjH38qOY= 102 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 h1:s4074ZO1Hk8qv65GqNXqDjmkf4HSQqJukaLuuW0TpDA= 103 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.2/go.mod h1:mVggCnIWoM09jP71Wh+ea7+5gAp53q+49wDFs1SW5z8= 104 | github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= 105 | github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= 106 | github.com/bank-vaults/vault-sdk v0.10.2 h1:DqVebQg2sly6NjHWUahf4wCSTmsA8WgzubFSgCp2hn8= 107 | github.com/bank-vaults/vault-sdk v0.10.2/go.mod h1:cjUlhXv/RXy/m8EuKZTlehNqZQ/EyngzRwKNp4n/zB0= 108 | github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 109 | github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 110 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 111 | github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= 112 | github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= 113 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 114 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 115 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 116 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 117 | github.com/cncf/xds/go v0.0.0-20241213214725-57cfbe6fad57 h1:put7Je9ZyxbHtwr7IqGrW4LLVUupJQ2gbsDshKISSgU= 118 | github.com/cncf/xds/go v0.0.0-20241213214725-57cfbe6fad57/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= 119 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 120 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 121 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 122 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 123 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 124 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 125 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 126 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 127 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 128 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 129 | github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE= 130 | github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= 131 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 132 | github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= 133 | github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= 134 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 135 | github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= 136 | github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= 137 | github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= 138 | github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 139 | github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= 140 | github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 141 | github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= 142 | github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= 143 | github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= 144 | github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= 145 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 146 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 147 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 148 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 149 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 150 | github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 151 | github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= 152 | github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 153 | github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= 154 | github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= 155 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 156 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 157 | github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= 158 | github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= 159 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 160 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 161 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 162 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 163 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 164 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 165 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 166 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 167 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 168 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 169 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 170 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 171 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 172 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 173 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 174 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 175 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 176 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 177 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 178 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 179 | github.com/google/go-replayers/grpcreplay v1.3.0 h1:1Keyy0m1sIpqstQmgz307zhiJ1pV4uIlFds5weTmxbo= 180 | github.com/google/go-replayers/grpcreplay v1.3.0/go.mod h1:v6NgKtkijC0d3e3RW8il6Sy5sqRVUwoQa4mHOGEy8DI= 181 | github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk= 182 | github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg= 183 | github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= 184 | github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= 185 | github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= 186 | github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= 187 | github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= 188 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 189 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 190 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 191 | github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= 192 | github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= 193 | github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= 194 | github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= 195 | github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= 196 | github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= 197 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 198 | github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 199 | github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 200 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 201 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 202 | github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 203 | github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= 204 | github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 205 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 206 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 207 | github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= 208 | github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= 209 | github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= 210 | github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= 211 | github.com/hashicorp/go-secure-stdlib/awsutil v0.3.0 h1:I8bynUKMh9I7JdwtW9voJ0xmHvBpxQtLjrMFDYmhOxY= 212 | github.com/hashicorp/go-secure-stdlib/awsutil v0.3.0/go.mod h1:oKHSQs4ivIfZ3fbXGQOop1XuDfdSb8RIsWTGaAanSfg= 213 | github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 h1:iBt4Ew4XEGLfh6/bPk4rSYmuZJGizr6/x/AEizP0CQc= 214 | github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8/go.mod h1:aiJI+PIApBRQG7FZTEBx5GiiX+HbOHilUdNxUZi4eV0= 215 | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= 216 | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= 217 | github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= 218 | github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= 219 | github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= 220 | github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 221 | github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= 222 | github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= 223 | github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= 224 | github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= 225 | github.com/hashicorp/vault/api/auth/aws v0.8.0 h1:6E14D7eHjV+Ytk8HmKLbTGS/LaXD9hP2FXe7IIKCrHc= 226 | github.com/hashicorp/vault/api/auth/aws v0.8.0/go.mod h1:SweK5366gCeO5krBk6Fpjz/MX2oa+iiIZz/Nu8/nMZw= 227 | github.com/hashicorp/vault/api/auth/azure v0.7.0 h1:h98KQWX2t1OD5ElKIsr/yAp/H2qII4e/a4ijREUcWqQ= 228 | github.com/hashicorp/vault/api/auth/azure v0.7.0/go.mod h1:hKpHZkUmCf7hJy91g/Fwoe7Fk/+eVbOq85NQTJiaB9U= 229 | github.com/hashicorp/vault/api/auth/gcp v0.8.0 h1:MGSR6zNXVUajVnlDeTBzu1wucCbrjel2ETKFI/YDYFI= 230 | github.com/hashicorp/vault/api/auth/gcp v0.8.0/go.mod h1:y/ArMZdRmKyU1iGNjauViy6qRDC/M72HFH+f6MRN+KI= 231 | github.com/hashicorp/vault/api/auth/kubernetes v0.8.0 h1:6jPcORq7OHwf+MCbaaUmiBvMhETAaZ7+i97WfZtF5kc= 232 | github.com/hashicorp/vault/api/auth/kubernetes v0.8.0/go.mod h1:nfl5sRUUork0ZSfV3xf+pgAFQSD5kSkL0k9axg523DM= 233 | github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= 234 | github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 235 | github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= 236 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 237 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 238 | github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= 239 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 240 | github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= 241 | github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= 242 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 243 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 244 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 245 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 246 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 247 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 248 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 249 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 250 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 251 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 252 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 253 | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 254 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 255 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 256 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 257 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 258 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 259 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 260 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 261 | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= 262 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 263 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 264 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 265 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 266 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 267 | github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= 268 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 269 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= 270 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= 271 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 272 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 273 | github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= 274 | github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= 275 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 276 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 277 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 278 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 279 | github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= 280 | github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= 281 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 282 | github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 283 | github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 284 | github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= 285 | github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= 286 | github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= 287 | github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= 288 | github.com/samber/slog-multi v1.4.0 h1:pwlPMIE7PrbTHQyKWDU+RIoxP1+HKTNOujk3/kdkbdg= 289 | github.com/samber/slog-multi v1.4.0/go.mod h1:FsQ4Uv2L+E/8TZt+/BVgYZ1LoDWCbfCU21wVIoMMrO8= 290 | github.com/samber/slog-syslog v1.0.0 h1:4tf8sNv9+qTQ6Fj8+N6U1ZEtUbqbAIzd+q26/NegWFM= 291 | github.com/samber/slog-syslog v1.0.0/go.mod h1:jjupk+yHPVSuXuGhKleoClYc/HEaC+Ro5X4YYeBrt6g= 292 | github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= 293 | github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= 294 | github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk= 295 | github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= 296 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 297 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 298 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 299 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 300 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 301 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 302 | github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 303 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 304 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 305 | github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 306 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 307 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 308 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 309 | go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= 310 | go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 311 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 312 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 313 | go.opentelemetry.io/contrib/detectors/gcp v1.33.0 h1:FVPoXEoILwgbZUu4X7YSgsESsAmGRgoYcnXkzgQPhP4= 314 | go.opentelemetry.io/contrib/detectors/gcp v1.33.0/go.mod h1:ZHrLmr4ikK2AwRj9QL+c9s2SOlgoSRyMpNVzUj2fZqI= 315 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc= 316 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0= 317 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= 318 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= 319 | go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= 320 | go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= 321 | go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= 322 | go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= 323 | go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= 324 | go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= 325 | go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= 326 | go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= 327 | go.opentelemetry.io/otel/sdk/metric v1.33.0 h1:Gs5VK9/WUJhNXZgn8MR6ITatvAmKeIuCtNbsP3JkNqU= 328 | go.opentelemetry.io/otel/sdk/metric v1.33.0/go.mod h1:dL5ykHZmm1B1nVRk9dDjChwDmt81MjVp3gLkQRwKf/Q= 329 | go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= 330 | go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= 331 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 332 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 333 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 334 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 335 | gocloud.dev v0.40.0 h1:f8LgP+4WDqOG/RXoUcyLpeIAGOcAbZrZbDQCUee10ng= 336 | gocloud.dev v0.40.0/go.mod h1:drz+VyYNBvrMTW0KZiBAYEdl8lbNZx+OQ7oQvdrFmSQ= 337 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 338 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 339 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 340 | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= 341 | golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= 342 | golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= 343 | golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= 344 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 345 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 346 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 347 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 348 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 349 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 350 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 351 | golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 352 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 353 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 354 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 355 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 356 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 357 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 358 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 359 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 360 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 361 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 362 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 363 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 364 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= 365 | golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= 366 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 367 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 368 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 369 | golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= 370 | golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 371 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 372 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 373 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 374 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 375 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 376 | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= 377 | golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 378 | golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= 379 | golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 380 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 381 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 382 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 383 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 384 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 385 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 386 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 387 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 388 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 389 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 390 | golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 391 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 392 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 393 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 394 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 395 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 396 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 397 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 398 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 399 | golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 400 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 401 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 402 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 403 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 404 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 405 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 406 | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= 407 | golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= 408 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 409 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 410 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 411 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 412 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 413 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 414 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 415 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 416 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 417 | golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= 418 | golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 419 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 420 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 421 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 422 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 423 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 424 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 425 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 426 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 427 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 428 | golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= 429 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 430 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 431 | golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= 432 | golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 433 | google.golang.org/api v0.211.0 h1:IUpLjq09jxBSV1lACO33CGY3jsRcbctfGzhj+ZSE/Bg= 434 | google.golang.org/api v0.211.0/go.mod h1:XOloB4MXFH4UTlQSGuNUxw0UT74qdENK8d6JNsXKLi0= 435 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 436 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 437 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 438 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 439 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 440 | google.golang.org/genproto v0.0.0-20241209162323-e6fa225c2576 h1:k48HcZ4FE6in0o8IflZCkc1lTc2u37nhGd8P+fo4r24= 441 | google.golang.org/genproto v0.0.0-20241209162323-e6fa225c2576/go.mod h1:DV2u3tCn/AcVjjmGYZKt6HyvY4w4y3ipAdHkMbe/0i4= 442 | google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= 443 | google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= 444 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= 445 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= 446 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 447 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 448 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 449 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 450 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 451 | google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= 452 | google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= 453 | google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3 h1:hUfOButuEtpc0UvYiaYRbNwxVYr0mQQOWq6X8beJ9Gc= 454 | google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3/go.mod h1:jzYlkSMbKypzuu6xoAEijsNVo9ZeDF1u/zCfFgsx7jg= 455 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 456 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 457 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 458 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 459 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 460 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 461 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 462 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 463 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 464 | google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= 465 | google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 466 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 467 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 468 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 469 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 470 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 471 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 472 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 473 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 474 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 475 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 476 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 477 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 478 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Banzai Cloud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "context" 19 | "fmt" 20 | "log/slog" 21 | "net" 22 | "os" 23 | "os/exec" 24 | "os/signal" 25 | "slices" 26 | "strings" 27 | "syscall" 28 | "time" 29 | 30 | "emperror.dev/errors" 31 | injector "github.com/bank-vaults/vault-sdk/injector/vault" 32 | "github.com/bank-vaults/vault-sdk/vault" 33 | vaultapi "github.com/hashicorp/vault/api" 34 | slogmulti "github.com/samber/slog-multi" 35 | slogsyslog "github.com/samber/slog-syslog" 36 | "github.com/spf13/cast" 37 | ) 38 | 39 | var Version = "dev" 40 | 41 | // The special value for VAULT_ENV which marks that the login token needs to be passed through to the application 42 | // which was acquired during the new Vault client creation 43 | const vaultLogin = "vault:login" 44 | 45 | type sanitizedEnviron struct { 46 | env []string 47 | login bool 48 | } 49 | 50 | type envType struct { 51 | login bool 52 | } 53 | 54 | var sanitizeEnvmap = map[string]envType{ 55 | "VAULT_TOKEN": {login: true}, 56 | "VAULT_ADDR": {login: true}, 57 | "VAULT_AGENT_ADDR": {login: true}, 58 | "VAULT_CACERT": {login: true}, 59 | "VAULT_CAPATH": {login: true}, 60 | "VAULT_CLIENT_CERT": {login: true}, 61 | "VAULT_CLIENT_KEY": {login: true}, 62 | "VAULT_CLIENT_TIMEOUT": {login: true}, 63 | "VAULT_SRV_LOOKUP": {login: true}, 64 | "VAULT_SKIP_VERIFY": {login: true}, 65 | "VAULT_NAMESPACE": {login: true}, 66 | "VAULT_TLS_SERVER_NAME": {login: true}, 67 | "VAULT_WRAP_TTL": {login: true}, 68 | "VAULT_MFA": {login: true}, 69 | "VAULT_MAX_RETRIES": {login: true}, 70 | "VAULT_CLUSTER_ADDR": {login: false}, 71 | "VAULT_REDIRECT_ADDR": {login: false}, 72 | "VAULT_CLI_NO_COLOR": {login: false}, 73 | "VAULT_RATE_LIMIT": {login: false}, 74 | "VAULT_ROLE": {login: false}, 75 | "VAULT_PATH": {login: false}, 76 | "VAULT_AUTH_METHOD": {login: false}, 77 | "VAULT_TRANSIT_KEY_ID": {login: false}, 78 | "VAULT_TRANSIT_PATH": {login: false}, 79 | "VAULT_TRANSIT_BATCH_SIZE": {login: false}, 80 | "VAULT_IGNORE_MISSING_SECRETS": {login: false}, 81 | "VAULT_ENV_PASSTHROUGH": {login: false}, 82 | "VAULT_JSON_LOG": {login: false}, 83 | "VAULT_LOG_LEVEL": {login: false}, 84 | "VAULT_REVOKE_TOKEN": {login: false}, 85 | "VAULT_ENV_DAEMON": {login: false}, 86 | "VAULT_ENV_FROM_PATH": {login: false}, 87 | "VAULT_ENV_DELAY": {login: false}, 88 | } 89 | 90 | // Appends variable an entry (name=value) into the environ list. 91 | // VAULT_* variables are not populated into this list if this is not a login scenario. 92 | func (e *sanitizedEnviron) append(name string, value string) { 93 | if envType, ok := sanitizeEnvmap[name]; !ok || (e.login && envType.login) { 94 | e.env = append(e.env, fmt.Sprintf("%s=%s", name, value)) 95 | } 96 | } 97 | 98 | type daemonSecretRenewer struct { 99 | client *vault.Client 100 | sigs chan os.Signal 101 | logger *slog.Logger 102 | } 103 | 104 | func (r daemonSecretRenewer) Renew(path string, secret *vaultapi.Secret) error { 105 | watcherInput := vaultapi.LifetimeWatcherInput{Secret: secret} 106 | watcher, err := r.client.RawClient().NewLifetimeWatcher(&watcherInput) 107 | if err != nil { 108 | return errors.Wrap(err, "failed to create secret watcher") 109 | } 110 | 111 | go watcher.Start() 112 | 113 | go func() { 114 | defer watcher.Stop() 115 | for { 116 | select { 117 | case renewOutput := <-watcher.RenewCh(): 118 | r.logger.Info("secret renewed", slog.String("path", path), slog.Duration("lease-duration", time.Duration(renewOutput.Secret.LeaseDuration)*time.Second)) 119 | case doneError := <-watcher.DoneCh(): 120 | if !secret.Renewable { 121 | leaseDuration := time.Duration(secret.LeaseDuration) * time.Second 122 | time.Sleep(leaseDuration) 123 | 124 | r.logger.Info("secret lease has expired", slog.String("path", path), slog.Duration("lease-duration", leaseDuration)) 125 | } 126 | 127 | r.logger.Info("secret renewal has stopped, sending SIGTERM to process", slog.String("path", path), slog.Any("done-error", doneError)) 128 | 129 | r.sigs <- syscall.SIGTERM 130 | 131 | timeout := <-time.After(10 * time.Second) 132 | r.logger.Info("killing process due to SIGTERM timeout", slog.Time("timeout", timeout)) 133 | r.sigs <- syscall.SIGKILL 134 | 135 | return 136 | } 137 | } 138 | }() 139 | 140 | return nil 141 | } 142 | 143 | func main() { 144 | var logger *slog.Logger 145 | { 146 | var level slog.Level 147 | 148 | err := level.UnmarshalText([]byte(os.Getenv("VAULT_LOG_LEVEL"))) 149 | if err != nil { // Silently fall back to info level 150 | level = slog.LevelInfo 151 | } 152 | 153 | levelFilter := func(levels ...slog.Level) func(ctx context.Context, r slog.Record) bool { 154 | return func(_ context.Context, r slog.Record) bool { 155 | return slices.Contains(levels, r.Level) 156 | } 157 | } 158 | 159 | router := slogmulti.Router() 160 | 161 | if cast.ToBool(os.Getenv("VAULT_JSON_LOG")) { 162 | // Send logs with level higher than warning to stderr 163 | router = router.Add( 164 | slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: level}), 165 | levelFilter(slog.LevelWarn, slog.LevelError), 166 | ) 167 | 168 | // Send info and debug logs to stdout 169 | router = router.Add( 170 | slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: level}), 171 | levelFilter(slog.LevelDebug, slog.LevelInfo), 172 | ) 173 | } else { 174 | // Send logs with level higher than warning to stderr 175 | router = router.Add( 176 | slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level}), 177 | levelFilter(slog.LevelWarn, slog.LevelError), 178 | ) 179 | 180 | // Send info and debug logs to stdout 181 | router = router.Add( 182 | slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: level}), 183 | levelFilter(slog.LevelDebug, slog.LevelInfo), 184 | ) 185 | } 186 | 187 | if logServerAddr := os.Getenv("VAULT_ENV_LOG_SERVER"); logServerAddr != "" { 188 | writer, err := net.Dial("udp", logServerAddr) 189 | 190 | // We silently ignore syslog connection errors for the lack of a better solution 191 | if err == nil { 192 | router = router.Add(slogsyslog.Option{Level: slog.LevelInfo, Writer: writer}.NewSyslogHandler()) 193 | } 194 | } 195 | 196 | // TODO: add level filter handler 197 | logger = slog.New(router.Handler()) 198 | logger = logger.With(slog.String("app", "vault-env")) 199 | 200 | slog.SetDefault(logger) 201 | } 202 | 203 | if len(os.Args) == 1 { 204 | logger.Error("no command is given, vault-env can't determine the entrypoint (command), please specify it explicitly or let the webhook query it (see documentation)") 205 | 206 | os.Exit(1) 207 | } 208 | 209 | daemonMode := cast.ToBool(os.Getenv("VAULT_ENV_DAEMON")) 210 | delayExec := cast.ToDuration(os.Getenv("VAULT_ENV_DELAY")) 211 | sigs := make(chan os.Signal, 1) 212 | 213 | entrypointCmd := os.Args[1:] 214 | 215 | binary, err := exec.LookPath(entrypointCmd[0]) 216 | if err != nil { 217 | logger.Error("binary not found", slog.String("binary", entrypointCmd[0])) 218 | 219 | os.Exit(1) 220 | } 221 | 222 | // Used both for reading secrets and transit encryption 223 | ignoreMissingSecrets := cast.ToBool(os.Getenv("VAULT_IGNORE_MISSING_SECRETS")) 224 | 225 | clientOptions := []vault.ClientOption{vault.ClientLogger(clientLogger{logger})} 226 | // The login procedure takes the token from a file (if using Vault Agent) 227 | // or requests one for itself (Kubernetes Auth, or GCP, etc...), 228 | // so if we got a VAULT_TOKEN for the special value with "vault:login" 229 | originalVaultTokenEnvVar := os.Getenv("VAULT_TOKEN") 230 | isLogin := originalVaultTokenEnvVar == vaultLogin 231 | if tokenFile := os.Getenv("VAULT_TOKEN_FILE"); tokenFile != "" { 232 | // load token from vault-agent .vault-token or injected webhook 233 | if b, err := os.ReadFile(tokenFile); err == nil { 234 | originalVaultTokenEnvVar = string(b) 235 | } else { 236 | logger.Error("could not read vault token file", slog.String("file", tokenFile)) 237 | 238 | os.Exit(1) 239 | } 240 | clientOptions = append(clientOptions, vault.ClientToken(originalVaultTokenEnvVar)) 241 | } else { 242 | if isLogin { 243 | _ = os.Unsetenv("VAULT_TOKEN") 244 | } 245 | // use role/path based authentication 246 | clientOptions = append(clientOptions, 247 | vault.ClientRole(os.Getenv("VAULT_ROLE")), 248 | vault.ClientAuthPath(os.Getenv("VAULT_PATH")), 249 | vault.ClientAuthMethod(os.Getenv("VAULT_AUTH_METHOD")), 250 | ) 251 | } 252 | 253 | client, err := vault.NewClientWithOptions(clientOptions...) 254 | if err != nil { 255 | logger.Error(fmt.Errorf("failed to create vault client: %w", err).Error()) 256 | 257 | os.Exit(1) 258 | } 259 | 260 | passthroughEnvVars := strings.Split(os.Getenv("VAULT_ENV_PASSTHROUGH"), ",") 261 | 262 | if isLogin { 263 | _ = os.Setenv("VAULT_TOKEN", vaultLogin) 264 | passthroughEnvVars = append(passthroughEnvVars, "VAULT_TOKEN") 265 | } 266 | 267 | // do not sanitize env vars specified in VAULT_ENV_PASSTHROUGH 268 | for _, envVar := range passthroughEnvVars { 269 | if trimmed := strings.TrimSpace(envVar); trimmed != "" { 270 | delete(sanitizeEnvmap, trimmed) 271 | } 272 | } 273 | 274 | // initial and sanitized environs 275 | environ := make(map[string]string, len(os.Environ())) 276 | sanitized := sanitizedEnviron{login: isLogin} 277 | 278 | config := injector.Config{ 279 | TransitKeyID: os.Getenv("VAULT_TRANSIT_KEY_ID"), 280 | TransitPath: os.Getenv("VAULT_TRANSIT_PATH"), 281 | TransitBatchSize: cast.ToInt(os.Getenv("VAULT_TRANSIT_BATCH_SIZE")), 282 | DaemonMode: daemonMode, 283 | IgnoreMissingSecrets: ignoreMissingSecrets, 284 | } 285 | 286 | var secretRenewer injector.SecretRenewer 287 | 288 | if daemonMode { 289 | secretRenewer = daemonSecretRenewer{client: client, sigs: sigs, logger: logger} 290 | } 291 | 292 | secretInjector := injector.NewSecretInjector(config, client, secretRenewer, logger) 293 | 294 | for _, env := range os.Environ() { 295 | split := strings.SplitN(env, "=", 2) 296 | name := split[0] 297 | value := split[1] 298 | environ[name] = value 299 | } 300 | 301 | inject := func(key, value string) { 302 | sanitized.append(key, value) 303 | } 304 | 305 | err = secretInjector.InjectSecretsFromVault(environ, inject) 306 | if err != nil { 307 | logger.Error(fmt.Errorf("failed to inject secrets from vault: %w", err).Error()) 308 | 309 | os.Exit(1) 310 | } 311 | 312 | if paths := os.Getenv("VAULT_ENV_FROM_PATH"); paths != "" { 313 | err = secretInjector.InjectSecretsFromVaultPath(paths, inject) 314 | } 315 | if err != nil { 316 | logger.Error(fmt.Errorf("failed to inject secrets from vault path: %w", err).Error()) 317 | 318 | os.Exit(1) 319 | } 320 | 321 | if cast.ToBool(os.Getenv("VAULT_REVOKE_TOKEN")) { 322 | // ref: https://www.vaultproject.io/api/auth/token/index.html#revoke-a-token-self- 323 | err = client.RawClient().Auth().Token().RevokeSelf(client.RawClient().Token()) 324 | if err != nil { 325 | // Do not exit on error, token revoking can be denied by policy 326 | logger.Warn("failed to revoke token") 327 | } 328 | 329 | client.Close() 330 | } 331 | 332 | if delayExec > 0 { 333 | logger.Info(fmt.Sprintf("sleeping for %s...", delayExec)) 334 | time.Sleep(delayExec) 335 | } 336 | 337 | logger.Info("spawning process", slog.String("entrypoint", fmt.Sprint(entrypointCmd))) 338 | 339 | if daemonMode { 340 | logger.Info("in daemon mode...") 341 | cmd := exec.Command(binary, entrypointCmd[1:]...) 342 | cmd.Env = append(os.Environ(), sanitized.env...) 343 | cmd.Stdin = os.Stdin 344 | cmd.Stderr = os.Stderr 345 | cmd.Stdout = os.Stdout 346 | 347 | signal.Notify(sigs) 348 | 349 | err = cmd.Start() 350 | if err != nil { 351 | logger.Error(fmt.Errorf("failed to start process: %w", err).Error(), slog.String("entrypoint", fmt.Sprint(entrypointCmd))) 352 | 353 | os.Exit(1) 354 | } 355 | 356 | go func() { 357 | for sig := range sigs { 358 | // We don't want to signal a non-running process. 359 | if cmd.ProcessState != nil && cmd.ProcessState.Exited() { 360 | break 361 | } 362 | 363 | err := cmd.Process.Signal(sig) 364 | if err != nil { 365 | logger.Warn(fmt.Errorf("failed to signal process: %w", err).Error(), slog.String("signal", sig.String())) 366 | } else if sig == syscall.SIGURG { 367 | logger.Debug("received signal", slog.String("signal", sig.String())) 368 | } else { 369 | logger.Info("received signal", slog.String("signal", sig.String())) 370 | } 371 | } 372 | }() 373 | 374 | err = cmd.Wait() 375 | 376 | close(sigs) 377 | 378 | if err != nil { 379 | exitCode := -1 380 | // try to get the original exit code if possible 381 | var exitError *exec.ExitError 382 | if errors.As(err, &exitError) { 383 | exitCode = exitError.ExitCode() 384 | } 385 | 386 | logger.Error(fmt.Errorf("failed to exec process: %w", err).Error(), slog.String("entrypoint", fmt.Sprint(entrypointCmd))) 387 | 388 | os.Exit(exitCode) 389 | } 390 | 391 | os.Exit(cmd.ProcessState.ExitCode()) 392 | } else { 393 | err = syscall.Exec(binary, entrypointCmd, sanitized.env) 394 | if err != nil { 395 | logger.Error(fmt.Errorf("failed to exec process: %w", err).Error(), slog.String("entrypoint", fmt.Sprint(entrypointCmd))) 396 | 397 | os.Exit(1) 398 | } 399 | } 400 | } 401 | --------------------------------------------------------------------------------