├── .dockerignore ├── .github └── workflows │ ├── docker-release.yaml │ ├── github-release.yaml │ └── test.yaml ├── .gitignore ├── .golangci.yaml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── go.mod ├── go.sum ├── main.go ├── mocks ├── GoogleSecretsManagerAPI.go ├── SSMAPI.go └── SecretsManagerAPI.go └── pkg └── secrets ├── aws ├── secrets.go └── secrets_test.go ├── google ├── interface.go ├── secrets.go └── secrets_test.go └── provider.go /.dockerignore: -------------------------------------------------------------------------------- 1 | # binaries 2 | .bin 3 | 4 | # coverage 5 | .cover 6 | 7 | # IDE 8 | .idea 9 | .vscode 10 | 11 | # CI/CD 12 | .github 13 | 14 | # helper files 15 | .gitignore 16 | *.todo 17 | 18 | # documentation 19 | *.md 20 | docs 21 | 22 | # customization and secrets 23 | .env 24 | 25 | # license 26 | LICENSE 27 | -------------------------------------------------------------------------------- /.github/workflows/docker-release.yaml: -------------------------------------------------------------------------------- 1 | name: docker 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - '[0-9]+.[0-9]+.[0-9]+' 8 | paths-ignore: 9 | - 'docs/**' 10 | - '*.md' 11 | 12 | jobs: 13 | release: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | 20 | - name: Set up QEMU 21 | uses: docker/setup-qemu-action@v2 22 | 23 | - name: Set up Docker buildx 24 | id: buildx 25 | uses: docker/setup-buildx-action@v2 26 | 27 | - name: Login to Docker Registry 28 | uses: docker/login-action@v2 29 | with: 30 | registry: ${{ secrets.DOCKER_REGISTRY }} 31 | username: ${{ secrets.DOCKER_USERNAME }} 32 | password: ${{ secrets.DOCKER_PASSWORD }} 33 | 34 | - name: Login to GitHub Container Registry 35 | uses: docker/login-action@v2 36 | with: 37 | registry: ghcr.io 38 | username: ${{ github.repository_owner }} 39 | password: ${{ secrets.CR_PAT }} 40 | 41 | - name: Available platforms 42 | run: echo "${{ steps.buildx.outputs.platforms }}" 43 | 44 | - name: Decide on image name 45 | id: nomenclator 46 | env: 47 | DOCKER_REPOSITORY: ${{ secrets.DOCKER_REPOSITORY }} 48 | run: | 49 | name=${DOCKER_REPOSITORY} 50 | if [ -z "$name" ]; then 51 | name=${{ github.repository }} 52 | fi 53 | echo ::set-output name=name::${name} 54 | echo ::debug::docker image name ${name} 55 | 56 | - name: Decide on tag 57 | id: tagger 58 | run: | 59 | tag=$(echo "${{ github.ref }}" | sed -e 's/^refs\/heads\///g' -e 's/^refs\/tags\///g' -e 's/^refs\/pull\///g' -e 's/\/merge$//g' | sed -e 's/master/latest/g') 60 | echo "::set-output name=tag::${tag}" 61 | echo "::debug::docker image tag ${tag}" 62 | 63 | - name: Build and push Docker image 64 | id: build-push 65 | uses: docker/build-push-action@v3 66 | with: 67 | build-args: VERSION=${{ steps.tagger.outputs.tag }} 68 | platforms: linux/amd64,linux/arm64 69 | tags: | 70 | ${{ steps.nomenclator.outputs.name }}:${{ steps.tagger.outputs.tag }} 71 | ${{ steps.nomenclator.outputs.name }}:latest 72 | ghcr.io/${{ github.repository }}:${{ steps.tagger.outputs.tag }} 73 | ghcr.io/${{ github.repository }}:latest 74 | push: true 75 | 76 | - name: Image digest 77 | run: echo "${{ steps.build-push.outputs.digest }}" -------------------------------------------------------------------------------- /.github/workflows/github-release.yaml: -------------------------------------------------------------------------------- 1 | name: github 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - '[0-9]+.[0-9]+.[0-9]+' 8 | paths-ignore: 9 | - 'docs/**' 10 | - '*.md' 11 | 12 | jobs: 13 | release: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | 20 | - name: Install Go 21 | uses: actions/setup-go@v3 22 | with: 23 | go-version: '>=1.21.0' 24 | 25 | - name: Cross-Platform build 26 | run: | 27 | make platfrom-build 28 | 29 | - name: Build Changelog 30 | id: build_changelog 31 | uses: mikepenz/release-changelog-builder-action@v3 32 | env: 33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 34 | 35 | - name: Create Release 36 | uses: softprops/action-gh-release@v1 37 | with: 38 | body: ${{steps.github_release.outputs.changelog}} 39 | files: | 40 | .bin/* 41 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: 3 | push: 4 | branches: 5 | - '*' 6 | tags: 7 | - '*' 8 | paths-ignore: 9 | - 'docs/**' 10 | - '*.md' 11 | pull_request: 12 | branches: 13 | - '*' 14 | env: 15 | GOPROXY: https://proxy.golang.org 16 | CGO_ENABLED: 0 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout code 23 | uses: actions/checkout@v3 24 | 25 | - name: Install Go 26 | uses: actions/setup-go@v3 27 | with: 28 | go-version: '>=1.21.0' 29 | 30 | - name: Lint 31 | run: | 32 | make lint 33 | 34 | - name: Test 35 | run: | 36 | make test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # code coverage 2 | .cover 3 | 4 | # git repo 5 | .git 6 | 7 | # IDE customization 8 | .idea 9 | .vscode 10 | 11 | # binaries 12 | .bin 13 | 14 | # env customization 15 | .env 16 | 17 | # changelog 18 | CHANGELOG.md 19 | 20 | # vendor 21 | vendor 22 | 23 | # temporary 24 | **/.DS_Store 25 | **/debug 26 | **/debug.test 27 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | run: 2 | # which dirs to skip 3 | skip-dirs: 4 | - mocks 5 | # Timeout for analysis, e.g. 30s, 5m. 6 | # Default: 1m 7 | timeout: 5m 8 | # Exit code when at least one issue was found. 9 | # Default: 1 10 | issues-exit-code: 2 11 | # Include test files or not. 12 | # Default: true 13 | tests: false 14 | 15 | linters-settings: 16 | govet: 17 | check-shadowing: true 18 | gocyclo: 19 | min-complexity: 15 20 | maligned: 21 | suggest-new: true 22 | dupl: 23 | threshold: 100 24 | goconst: 25 | min-len: 2 26 | min-occurrences: 2 27 | misspell: 28 | locale: US 29 | ignore-words: 30 | - "cancelled" 31 | goimports: 32 | local-prefixes: github.com/golangci/golangci-lint 33 | gocritic: 34 | enabled-tags: 35 | - diagnostic 36 | - experimental 37 | - opinionated 38 | - performance 39 | - style 40 | disabled-checks: 41 | - dupImport # https://github.com/go-critic/go-critic/issues/845 42 | - ifElseChain 43 | - octalLiteral 44 | - rangeValCopy 45 | - unnamedResult 46 | - whyNoLint 47 | - wrapperFunc 48 | funlen: 49 | lines: 105 50 | statements: 50 51 | 52 | linters: 53 | # please, do not use `enable-all`: it's deprecated and will be removed soon. 54 | # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint 55 | disable-all: true 56 | enable: 57 | - asciicheck 58 | - bidichk 59 | - bodyclose 60 | # - containedctx 61 | # - contextcheck disabled because of generics 62 | - dupword 63 | - decorder 64 | # - depguard 65 | - dogsled 66 | - dupl 67 | - durationcheck 68 | - errcheck 69 | - errchkjson 70 | - errname 71 | - errorlint 72 | - exhaustive 73 | # - exhaustivestruct TODO: check how to fix it 74 | - exportloopref 75 | # - forbidigo TODO: configure forbidden code patterns 76 | # - forcetypeassert 77 | - funlen 78 | - gci 79 | # - gochecknoglobals TODO: remove globals from code 80 | # - gochecknoinits TODO: remove main.init 81 | - gocognit 82 | - goconst 83 | - gocritic 84 | - gocyclo 85 | # - godox 86 | - goerr113 87 | - gofmt 88 | - goimports 89 | - gomnd 90 | # - gomoddirectives 91 | - gosec 92 | - gosimple 93 | - govet 94 | - goprintffuncname 95 | - grouper 96 | - importas 97 | # - ireturn TODO: not sure if it is a good linter 98 | - ineffassign 99 | - interfacebloat 100 | - loggercheck 101 | - maintidx 102 | - makezero 103 | - misspell 104 | - nakedret 105 | # - nestif 106 | - nilerr 107 | - nilnil 108 | # - noctx 109 | - nolintlint 110 | - prealloc 111 | - predeclared 112 | - promlinter 113 | - reassign 114 | - revive 115 | # - rowserrcheck disabled because of generics 116 | # - staticcheck doesn't work with go1.19 117 | # - structcheck disabled because of generics 118 | - stylecheck 119 | - tenv 120 | - testableexamples 121 | - typecheck 122 | - unconvert 123 | - unparam 124 | - unused 125 | # - varnamelen TODO: review naming 126 | # - varcheck depricated 1.49 127 | # - wastedassign disabled because of generics 128 | - whitespace 129 | - wrapcheck 130 | # - wsl 131 | 132 | issues: 133 | exclude-rules: 134 | - path: _test\.go 135 | linters: 136 | - funlen 137 | - bodyclose 138 | - gosec 139 | - dupl 140 | - gocognit 141 | - goconst 142 | - gocyclo 143 | exclude: 144 | - Using the variable on range scope `tt` in function literal 145 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:experimental 2 | 3 | FROM --platform=${BUILDPLATFORM} golang:1.22-alpine as builder 4 | # passed by buildkit 5 | ARG TARGETOS 6 | ARG TARGETARCH 7 | # add CA certificates and TZ for local time 8 | RUN apk --update add ca-certificates make git 9 | # Create and change to the app directory. 10 | RUN mkdir -p /go/src/app 11 | WORKDIR /go/src/app 12 | # Retrieve application dependencies. 13 | # This allows the container build to reuse cached dependencies. 14 | # Expecting to copy go.mod and if present go.sum. 15 | COPY go.mod . 16 | COPY go.sum . 17 | RUN --mount=type=cache,target=/go/mod go mod download 18 | # Copy local code to the container image. 19 | COPY . . 20 | # Build the binary. 21 | RUN --mount=type=cache,target=/root/.cache/go-build TARGETOS=${TARGETOS} TARGETARCH=${TARGETARCH} make 22 | 23 | # final image 24 | FROM busybox:1.36 25 | # copy certificates 26 | COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ 27 | # copy the binary to the production image from the builder stage. 28 | COPY --from=builder /go/src/app/.bin/secrets-init /secrets-init 29 | RUN adduser -D -u 1000 secrets-init 30 | USER 1000 31 | 32 | ENTRYPOINT ["/secrets-init"] 33 | CMD ["--version"] 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MODULE = $(shell env GO111MODULE=on $(GO) list -m) 2 | DATE ?= $(shell date +%FT%T%z) 3 | VERSION ?= $(shell git describe --tags --always --dirty --match="*" 2> /dev/null || \ 4 | cat $(CURDIR)/.version 2> /dev/null || echo v0) 5 | COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null) 6 | BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null) 7 | PKGS = $(or $(PKG),$(shell env GO111MODULE=on $(GO) list ./...)) 8 | TESTPKGS = $(shell env GO111MODULE=on $(GO) list -f \ 9 | '{{ if or .TestGoFiles .XTestGoFiles }}{{ .ImportPath }}{{ end }}' \ 10 | $(PKGS)) 11 | BIN = $(CURDIR)/.bin 12 | LINT_CONFIG = $(CURDIR)/.golangci.yaml 13 | PLATFORMS = darwin linux 14 | ARCHITECTURES = amd64 arm64 15 | TARGETOS ?= $(GOOS) 16 | TARGETARCH ?= $(GOARCH) 17 | LDFLAGS_VERSION = -s -w -X main.Version=$(VERSION) -X main.BuildDate=$(DATE) -X main.GitCommit=$(COMMIT) -X main.GitBranch=$(BRANCH) 18 | 19 | DOCKER = docker 20 | GO = go 21 | TIMEOUT = 15 22 | V = 0 23 | Q = $(if $(filter 1,$V),,@) 24 | M = $(shell printf "\033[34;1m▶\033[0m") 25 | 26 | export GO111MODULE=on 27 | export CGO_ENABLED=0 28 | export GOPROXY=https://proxy.golang.org 29 | 30 | .PHONY: all 31 | all: fmt lint test ; $(info $(M) building executable...) @ ## Build program binary 32 | $Q env GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) $(GO) build \ 33 | -tags release \ 34 | -ldflags "$(LDFLAGS_VERSION) -X main.Platform=$(TARGETOS)/$(TARGETARCH)" \ 35 | -o $(BIN)/$(basename $(MODULE)) main.go 36 | 37 | # Release for multiple platforms 38 | 39 | .PHONY: platfrom-build 40 | platfrom-build: clean lint test ; $(info $(M) building binaries for multiple os/arch...) @ ## Build program binary for platforms and os 41 | $(foreach GOOS, $(PLATFORMS),\ 42 | $(foreach GOARCH, $(ARCHITECTURES), \ 43 | $(shell \ 44 | GOPROXY=$(GOPROXY) CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) \ 45 | $(GO) build \ 46 | -tags release \ 47 | -ldflags "$(LDFLAGS_VERSION) -X main.Platform=$(GOOS)/$(GOARCH)" \ 48 | -o $(BIN)/$(basename $(MODULE))-$(GOOS)-$(GOARCH) main.go || true))) 49 | 50 | # Tools 51 | 52 | setup-tools: setup-lint setup-gocov setup-gocov-xml setup-go2xunit setup-mockery setup-ghr 53 | 54 | setup-lint: 55 | $(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1 56 | setup-gocov: 57 | $(GO) install github.com/axw/gocov/... 58 | setup-gocov-xml: 59 | $(GO) install github.com/AlekSi/gocov-xml 60 | setup-go2xunit: 61 | $(GO) install github.com/tebeka/go2xunit 62 | setup-mockery: 63 | $(GO) install github.com/vektra/mockery/v2/ 64 | setup-ghr: 65 | $(GO) install github.com/tcnksm/ghr@v0.13.0 66 | 67 | GOLINT=golangci-lint 68 | GOCOV=gocov 69 | GOCOVXML=gocov-xml 70 | GO2XUNIT=go2xunit 71 | GOMOCK=mockery 72 | 73 | # Tests 74 | 75 | TEST_TARGETS := test-default test-bench test-short test-verbose test-race 76 | .PHONY: $(TEST_TARGETS) test-xml check test tests 77 | test-bench: ARGS=-run=__absolutelynothing__ -bench=. ## Run benchmarks 78 | test-short: ARGS=-short ## Run only short tests 79 | test-verbose: ARGS=-v ## Run tests in verbose mode with coverage reporting 80 | test-race: ARGS=-race ## Run tests with race detector 81 | $(TEST_TARGETS): NAME=$(MAKECMDGOALS:test-%=%) 82 | $(TEST_TARGETS): test 83 | check test tests: fmt ; $(info $(M) running $(NAME:%=% )tests...) @ ## Run tests 84 | $Q $(GO) test -timeout $(TIMEOUT)s $(ARGS) $(TESTPKGS) 85 | 86 | test-xml: fmt lint | $(GO2XUNIT) ; $(info $(M) running xUnit tests...) @ ## Run tests with xUnit output 87 | $Q mkdir -p test 88 | $Q 2>&1 $(GO) test -timeout $(TIMEOUT)s -v $(TESTPKGS) | tee test/tests.output 89 | $(GO2XUNIT) -fail -input test/tests.output -output test/tests.xml 90 | 91 | COVERAGE_MODE = atomic 92 | COVERAGE_PROFILE = $(COVERAGE_DIR)/profile.out 93 | COVERAGE_XML = $(COVERAGE_DIR)/coverage.xml 94 | COVERAGE_HTML = $(COVERAGE_DIR)/index.html 95 | .PHONY: test-coverage test-coverage-tools 96 | test-coverage-tools: | $(GOCOV) $(GOCOVXML) 97 | test-coverage: COVERAGE_DIR := $(CURDIR)/test/coverage.$(shell date -u +"%Y-%m-%dT%H:%M:%SZ") 98 | test-coverage: fmt lint test-coverage-tools ; $(info $(M) running coverage tests...) @ ## Run coverage tests 99 | $Q mkdir -p $(COVERAGE_DIR) 100 | $Q $(GO) test \ 101 | -coverpkg=$$($(GO) list -f '{{ join .Deps "\n" }}' $(TESTPKGS) | \ 102 | grep '^$(MODULE)/' | \ 103 | tr '\n' ',' | sed 's/,$$//') \ 104 | -covermode=$(COVERAGE_MODE) \ 105 | -coverprofile="$(COVERAGE_PROFILE)" $(TESTPKGS) 106 | $Q $(GO) tool cover -html=$(COVERAGE_PROFILE) -o $(COVERAGE_HTML) 107 | $Q $(GOCOV) convert $(COVERAGE_PROFILE) | $(GOCOVXML) > $(COVERAGE_XML) 108 | 109 | .PHONY: lint 110 | lint: setup-lint ; $(info $(M) running golangci-lint) @ ## Run golangci-lint 111 | $Q $(GOLINT) run --timeout=5m -v -c $(LINT_CONFIG) ./... 112 | 113 | .PHONY: fmt 114 | fmt: ; $(info $(M) running gofmt...) @ ## Run gofmt on all source files 115 | $Q $(GO) fmt $(PKGS) 116 | 117 | .PHONY: mock 118 | mock: ; $(info $(M) generating mocks...) @ ## Run mockery 119 | $Q $(GO) mod vendor -v 120 | $Q $(GOMOCK) --name SecretsManagerAPI --dir vendor/github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface 121 | $Q $(GOMOCK) --name SSMAPI --dir vendor/github.com/aws/aws-sdk-go/service/ssm/ssmiface 122 | $Q $(GOMOCK) --name GoogleSecretsManagerAPI --dir pkg/secrets/google 123 | $Q rm -rf vendor 124 | 125 | # Misc 126 | 127 | # generate CHANGELOG.md changelog file 128 | .PHONY: changelog 129 | changelog: ; $(info $(M) generating changelog...) @ ## Generating CAHNGELOG.md 130 | ifndef GITHUB_TOKEN 131 | $(error GITHUB_TOKEN is undefined) 132 | endif 133 | $Q $(DOCKER) run --rm \ 134 | -v $(CURDIR):/usr/local/src/app \ 135 | -w /usr/local/src/app githubchangeloggenerator/github-changelog-generator \ 136 | --user doitintl --project secrets-init \ 137 | --token $(GITHUB_TOKEN) 138 | 139 | 140 | .PHONY: clean 141 | clean: ; $(info $(M) cleaning...) @ ## Cleanup everything 142 | @rm -rf $(BIN) 143 | @rm -rf test/tests.* test/coverage.* 144 | 145 | .PHONY: help 146 | help: 147 | @grep -E '^[ a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ 148 | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' 149 | 150 | .PHONY: version 151 | version: 152 | @echo $(VERSION) 153 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![test](https://github.com/doitintl/secrets-init/actions/workflows/test.yaml/badge.svg)](https://github.com/doitintl/secrets-init/actions/workflows/test.yaml) [![Go Report Card](https://goreportcard.com/badge/github.com/doitintl/secrets-init)](https://goreportcard.com/report/github.com/doitintl/secrets-init) [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/doitintl/secrets-init?label=image)](https://github.com/doitintl/secrets-init/pkgs/container/secrets-init) 2 | 3 | ## Blog Post 4 | 5 | [Kubernetes and Secrets Management in the Cloud](https://blog.doit-intl.com/kubernetes-and-secrets-management-in-cloud-858533c20dca?source=friends_link&sk=bb41e29ce4d082d6e69df38bb91244ef) 6 | 7 | # secrets-init 8 | 9 | `secrets-init` is a minimalistic init system designed to run as PID 1 inside container environments, similar to [dumb-init](https://github.com/Yelp/dumb-init), integrated with multiple secrets manager services: 10 | 11 | - [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) 12 | - [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) 13 | - [Google Secret Manager](https://cloud.google.com/secret-manager/docs/) 14 | 15 | ## Why you need an init system 16 | 17 | Please [read Yelp *dumb-init* repo explanation](https://github.com/Yelp/dumb-init/blob/v1.2.0/README.md#why-you-need-an-init-system) 18 | 19 | Summary: 20 | 21 | - Proper signal forwarding 22 | - Orphaned zombies reaping 23 | 24 | ## What `secrets-init` does 25 | 26 | `secrets-init` runs as `PID 1`, acting like a simple init system. It launches a single process and then proxies all received signals to a session rooted at that child process. 27 | 28 | `secrets-init` also passes almost all environment variables without modification, replacing _secret variables_ with values from secret management services. 29 | 30 | ### Integration with AWS Secrets Manager 31 | 32 | User can put AWS secret ARN as environment variable value. The `secrets-init` will resolve any environment value, using specified ARN, to referenced secret value. 33 | 34 | If the secret is saved as a Key/Value pair, all the keys are applied to as environment variables and passed. The environment variable passed is ignored unless it is inside the key/value pair. 35 | ```sh 36 | # environment variable passed to `secrets-init` 37 | MY_DB_PASSWORD=arn:aws:secretsmanager:$AWS_REGION:$AWS_ACCOUNT_ID:secret:mydbpassword-cdma3 38 | 39 | # environment variable passed to child process, resolved by `secrets-init` 40 | MY_DB_PASSWORD=very-secret-password 41 | ``` 42 | 43 | ### Integration with AWS Systems Manager Parameter Store 44 | 45 | It is possible to use AWS Systems Manager Parameter Store to store application parameters and secrets. 46 | 47 | User can put AWS Parameter Store ARN as environment variable value. The `secrets-init` will resolve any environment value, using specified ARN, to referenced parameter value. 48 | 49 | ```sh 50 | # environment variable passed to `secrets-init` 51 | MY_API_KEY=arn:aws:ssm:$AWS_REGION:$AWS_ACCOUNT_ID:parameter/api/key 52 | # OR versioned parameter 53 | MY_API_KEY=arn:aws:ssm:$AWS_REGION:$AWS_ACCOUNT_ID:parameter/api/key:$VERSION 54 | 55 | # environment variable passed to child process, resolved by `secrets-init` 56 | MY_API_KEY=key-123456789 57 | ``` 58 | 59 | ### Integration with Google Secret Manager 60 | 61 | User can put Google secret name (prefixed with `gcp:secretmanager:`) as environment variable value. The `secrets-init` will resolve any environment value, using specified name, to referenced secret value. 62 | 63 | ```sh 64 | # environment variable passed to `secrets-init` 65 | MY_DB_PASSWORD=gcp:secretmanager:projects/$PROJECT_ID/secrets/mydbpassword 66 | # OR versioned secret (with version or 'latest') 67 | MY_DB_PASSWORD=gcp:secretmanager:projects/$PROJECT_ID/secrets/mydbpassword/versions/2 68 | 69 | # environment variable passed to child process, resolved by `secrets-init` 70 | MY_DB_PASSWORD=very-secret-password 71 | ``` 72 | 73 | #### Project auto-detection 74 | 75 | If secret-manager is running in an environment where the Google metadata server is available, or the `-google-project` flag is set, the secret path may be omitted, and the current project is used. 76 | 77 | ```sh 78 | MY_DB_PASSWORD=mydbpassword 79 | MY_DB_PASSWORD=mydbpassword/versions/2 80 | ``` 81 | 82 | ### Requirement 83 | 84 | #### Container 85 | 86 | If you are building a Docker container, make sure to include the `ca-certificates` package, or use already prepared [doitintl/secrets-init](https://github.com/doitintl/secrets-init/pkgs/container/secrets-init) Docker container (`linux/amd64`, `linux/arm64`). 87 | 88 | #### AWS 89 | 90 | In order to resolve AWS secrets from AWS Secrets Manager and Parameter Store, `secrets-init` should run under IAM role that has permission to access desired secrets. 91 | 92 | This can be achieved by assigning IAM Role to Kubernetes Pod or ECS Task. It's possible to assign IAM Role to EC2 instance, where container is running, but this option is less secure. 93 | 94 | #### Google Cloud 95 | 96 | In order to resolve Google secrets from Google Secret Manager, `secrets-init` should run under IAM role that has permission to access desired secrets. 97 | 98 | This can be achieved by assigning IAM Role to Kubernetes Pod with [Workload Identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity). It's possible to assign IAM Role to GCE instance, where container is running, but this option is less secure. 99 | 100 | ## Kubernetes `secrets-init` admission webhook 101 | 102 | The [kube-secrets-init](https://github.com/doitintl/kube-secrets-init) implements Kubernetes [admission webhook](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) that injects `secrets-init` [initContainer](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) into any Pod that references cloud secrets (AWS Secrets Manager, AWS SSM Parameter Store and Google Secrets Manager) implicitly or explicitly. 103 | 104 | ## Code Reference 105 | 106 | Initial init system code was copied from [go-init](https://github.com/pablo-ruth/go-init) project. 107 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module secrets-init 2 | 3 | go 1.22 4 | 5 | require ( 6 | cloud.google.com/go/compute v1.10.0 7 | cloud.google.com/go/secretmanager v1.8.0 8 | github.com/aws/aws-sdk-go v1.44.128 9 | github.com/googleapis/gax-go/v2 v2.6.0 10 | github.com/pkg/errors v0.9.1 11 | github.com/sirupsen/logrus v1.9.0 12 | github.com/stretchr/testify v1.8.1 13 | github.com/urfave/cli/v2 v2.23.0 14 | golang.org/x/sys v0.12.0 15 | google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e 16 | ) 17 | 18 | require ( 19 | cloud.google.com/go/iam v0.5.0 // indirect 20 | github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect 23 | github.com/golang/protobuf v1.5.2 // indirect 24 | github.com/google/go-cmp v0.5.9 // indirect 25 | github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect 26 | github.com/jmespath/go-jmespath v0.4.0 // indirect 27 | github.com/kr/pretty v0.1.0 // indirect 28 | github.com/pmezard/go-difflib v1.0.0 // indirect 29 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 30 | github.com/stretchr/objx v0.5.0 // indirect 31 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect 32 | go.opencensus.io v0.23.0 // indirect 33 | golang.org/x/net v0.15.0 // indirect 34 | golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1 // indirect 35 | golang.org/x/text v0.13.0 // indirect 36 | google.golang.org/api v0.99.0 // indirect 37 | google.golang.org/appengine v1.6.7 // indirect 38 | google.golang.org/grpc v1.50.1 // indirect 39 | google.golang.org/protobuf v1.28.1 // indirect 40 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect 41 | gopkg.in/yaml.v3 v3.0.1 // indirect 42 | ) 43 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.104.0 h1:gSmWO7DY1vOm0MVU6DNXM11BWHHsTUmsC5cv1fuW5X8= 3 | cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= 4 | cloud.google.com/go/compute v1.10.0 h1:aoLIYaA1fX3ywihqpBk2APQKOo20nXsp1GEZQbx5Jk4= 5 | cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= 6 | cloud.google.com/go/iam v0.5.0 h1:fz9X5zyTWBmamZsqvqZqD7khbifcZF/q+Z1J8pfhIUg= 7 | cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= 8 | cloud.google.com/go/secretmanager v1.8.0 h1:4wYWL2t10q+xUtFFS0QuWlqwQguMrwC6FDpjtMM6cUI= 9 | cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= 10 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 11 | github.com/aws/aws-sdk-go v1.44.128 h1:X34pX5t0LIZXjBY11yf9JKMP3c1aZgirh+5PjtaZyJ4= 12 | github.com/aws/aws-sdk-go v1.44.128/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= 13 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 14 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 15 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 16 | github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= 17 | github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 18 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 19 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 20 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 21 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 22 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 23 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 24 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 25 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 26 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= 27 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 28 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 29 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 30 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 31 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 32 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 33 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 34 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 35 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 36 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 37 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 38 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 39 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 40 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 41 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 42 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 43 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 44 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 45 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 46 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 47 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 48 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 49 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 50 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 51 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 52 | github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= 53 | github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= 54 | github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= 55 | github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= 56 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 57 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 58 | github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= 59 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 60 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 61 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 62 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 63 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 64 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 65 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 66 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 67 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 68 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 69 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 70 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 71 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 72 | github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= 73 | github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 74 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 75 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 76 | github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= 77 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 78 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 79 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 80 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 81 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 82 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= 83 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 84 | github.com/urfave/cli/v2 v2.23.0 h1:pkly7gKIeYv3olPAeNajNpLjeJrmTPYCoZWaV+2VfvE= 85 | github.com/urfave/cli/v2 v2.23.0/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= 86 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= 87 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= 88 | go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= 89 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 90 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 91 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 92 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 93 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 94 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 95 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 96 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 97 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 98 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 99 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 100 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 101 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 102 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 103 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 104 | golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= 105 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= 106 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 107 | golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1 h1:3VPzK7eqH25j7GYw5w6g/GzNRc0/fYtrxz27z1gD4W0= 108 | golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= 109 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 110 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 111 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 112 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 113 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 114 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 115 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 116 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 117 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 118 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 119 | golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= 120 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 121 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 122 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 123 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 124 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 125 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 126 | golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= 127 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 128 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 129 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 130 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 131 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 132 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 133 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 134 | google.golang.org/api v0.99.0 h1:tsBtOIklCE2OFxhmcYSVqGwSAN/Y897srxmcvAQnwK8= 135 | google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= 136 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 137 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 138 | google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= 139 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 140 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 141 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 142 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 143 | google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e h1:halCgTFuLWDRD61piiNSxPsARANGD3Xl16hPrLgLiIg= 144 | google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= 145 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 146 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 147 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 148 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 149 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 150 | google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= 151 | google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= 152 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 153 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 154 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 155 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 156 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 157 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 158 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 159 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 160 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 161 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 162 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 163 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 164 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 165 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 166 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 167 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 168 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 169 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 170 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 171 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 172 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 173 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 174 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 175 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "os" 8 | "os/exec" 9 | "os/signal" 10 | "path/filepath" 11 | "runtime" 12 | "syscall" 13 | 14 | "secrets-init/pkg/secrets" //nolint:gci 15 | "secrets-init/pkg/secrets/aws" 16 | "secrets-init/pkg/secrets/google" 17 | 18 | "github.com/pkg/errors" 19 | log "github.com/sirupsen/logrus" 20 | "github.com/urfave/cli/v2" 21 | "golang.org/x/sys/unix" //nolint:gci 22 | ) 23 | 24 | var ( 25 | // Version contains the current Version. 26 | Version = "dev" 27 | // BuildDate contains a string with the build BuildDate. 28 | BuildDate = "unknown" 29 | // GitCommit git commit sha 30 | GitCommit = "dirty" 31 | // GitBranch git branch 32 | GitBranch = "dirty" 33 | // Platform OS/ARCH 34 | Platform = "" 35 | ) 36 | 37 | func main() { 38 | app := &cli.App{ 39 | Before: setLogFormatter, 40 | Flags: []cli.Flag{ 41 | &cli.StringFlag{ 42 | Name: "log-format, l", 43 | Usage: "select logrus formatter ['json', 'text']", 44 | Value: "text", 45 | EnvVars: []string{"SECRETS_INIT_LOG_FORMAT", "LOG_FORMAT"}, 46 | }, 47 | &cli.StringFlag{ 48 | Name: "provider, p", 49 | Usage: "supported secrets manager provider ['aws', 'google']", 50 | Value: "aws", 51 | EnvVars: []string{"SECRETS_INIT_SECRETS_PROVIDER", "SECRETS_PROVIDER"}, 52 | }, 53 | &cli.BoolFlag{ 54 | Name: "exit-early", 55 | Usage: "exit when a provider fails or a secret is not found", 56 | EnvVars: []string{"SECRETS_INIT_EXIT_EARLY", "EXIT_EARLY"}, 57 | }, 58 | &cli.StringFlag{ 59 | Name: "google-project", 60 | Usage: "the google cloud project for secrets without a project prefix", 61 | EnvVars: []string{"SECRETS_INIT_GOOGLE_PROJECT", "GOOGLE_PROJECT"}, 62 | }, 63 | &cli.BoolFlag{ 64 | Name: "interactive", 65 | Aliases: []string{"i"}, 66 | Usage: "use this flag if the command expects some input from the stdin", 67 | }, 68 | }, 69 | Commands: []*cli.Command{ 70 | { 71 | Name: "copy", 72 | Aliases: []string{"cp"}, 73 | Usage: "copy itself to a destination folder", 74 | ArgsUsage: "destination", 75 | Action: copyCmd, 76 | }, 77 | }, 78 | Name: "secrets-init", 79 | Usage: "enrich environment variables with secrets from secret manager", 80 | Action: mainCmd, 81 | Version: Version, 82 | } 83 | cli.VersionPrinter = func(_ *cli.Context) { 84 | fmt.Printf("version: %s\n", Version) 85 | fmt.Printf(" build date: %s\n", BuildDate) 86 | fmt.Printf(" commit: %s\n", GitCommit) 87 | fmt.Printf(" branch: %s\n", GitBranch) 88 | fmt.Printf(" platform: %s\n", Platform) 89 | fmt.Printf(" built with: %s\n", runtime.Version()) 90 | } 91 | 92 | err := app.Run(os.Args) 93 | if err != nil { 94 | log.Fatal(err) 95 | } 96 | } 97 | 98 | func copyCmd(c *cli.Context) error { 99 | if c.Args().Len() != 1 { 100 | return errors.New("must specify copy destination") 101 | } 102 | // full path of current executable 103 | src := os.Args[0] 104 | // destination path 105 | dest := filepath.Join(c.Args().First(), filepath.Base(src)) 106 | // copy file with current file mode flags 107 | sourceFileStat, err := os.Stat(src) 108 | if err != nil { 109 | return errors.Wrap(err, "failed to stat source file") 110 | } 111 | if !sourceFileStat.Mode().IsRegular() { 112 | return errors.Errorf("%s is not a regular file", src) 113 | } 114 | source, err := os.Open(src) 115 | if err != nil { 116 | return errors.Wrap(err, "failed to open source file") 117 | } 118 | srcInfo, err := source.Stat() 119 | if err != nil { 120 | return errors.Wrap(err, "failed to stat source file") 121 | } 122 | defer func() { _ = source.Close() }() 123 | destination, err := os.Create(dest) 124 | if err != nil { 125 | return errors.Wrapf(err, "failed to create %s", dest) 126 | } 127 | defer func() { _ = destination.Close() }() 128 | _, err = io.Copy(destination, source) 129 | if err != nil { 130 | return errors.Wrap(err, "failed to copy file") 131 | } 132 | err = destination.Chmod(srcInfo.Mode()) 133 | if err != nil { 134 | return errors.Wrap(err, "failed to set file mode") 135 | } 136 | return nil 137 | } 138 | 139 | func mainCmd(c *cli.Context) error { 140 | ctx := context.Background() 141 | 142 | // get provider 143 | var provider secrets.Provider 144 | var err error 145 | if c.String("provider") == "aws" { 146 | provider, err = aws.NewAwsSecretsProvider() 147 | } else if c.String("provider") == "google" { 148 | provider, err = google.NewGoogleSecretsProvider(ctx, c.String("google-project")) 149 | } 150 | if err != nil { 151 | log.WithField("provider", c.String("provider")).WithError(err).Error("failed to initialize secrets provider") 152 | if c.Bool("exit-early") { 153 | os.Exit(1) 154 | } 155 | } 156 | 157 | // Launch main command 158 | var childPid int 159 | childPid, err = run(ctx, provider, c.Bool("exit-early"), c.Bool("interactive"), c.Args().Slice()) 160 | if err != nil { 161 | log.WithError(err).Error("failed to run") 162 | os.Exit(1) 163 | } 164 | 165 | // Routine to reap zombies (it's the job of init) 166 | removeZombies(childPid) 167 | return nil 168 | } 169 | 170 | func removeZombies(childPid int) { 171 | var exitCode int 172 | for { 173 | var status syscall.WaitStatus 174 | 175 | // wait for an orphaned zombie process 176 | pid, err := syscall.Wait4(-1, &status, 0, nil) 177 | 178 | if pid == -1 { 179 | // if errno == ECHILD then no children remain; exit cleanly 180 | if errors.Is(err, syscall.ECHILD) { 181 | break 182 | } 183 | log.WithError(err).Error("unexpected wait4 error") 184 | os.Exit(1) 185 | } 186 | // check if pid is child, if so save 187 | // PID is > 0 if a child was reaped, and we immediately check if another one is waiting 188 | if pid == childPid { 189 | exitCode = status.ExitStatus() 190 | } 191 | continue 192 | } 193 | // no more children, exit with the same code as the child process 194 | os.Exit(exitCode) 195 | } 196 | 197 | // run passed command 198 | func run(ctx context.Context, provider secrets.Provider, exitEarly, interactive bool, commandSlice []string) (childPid int, err error) { 199 | var commandStr string 200 | var argsSlice []string 201 | 202 | if len(commandSlice) == 0 { 203 | log.Warn("no command specified") 204 | return childPid, err 205 | } 206 | 207 | // split command and arguments 208 | commandStr = commandSlice[0] 209 | // if there is args 210 | if len(commandSlice) > 1 { 211 | argsSlice = commandSlice[1:] 212 | } 213 | 214 | // register a channel to receive system signals 215 | sigs := make(chan os.Signal, 1) 216 | signal.Notify(sigs) 217 | 218 | // define a command and rebind its stdout and stdin 219 | cmd := exec.Command(commandStr, argsSlice...) 220 | cmd.Stdout = os.Stdout 221 | cmd.Stderr = os.Stderr 222 | // create a dedicated pidgroup used to forward signals to the main process and its children 223 | procAttrs := &syscall.SysProcAttr{Setpgid: true} 224 | // rebind stdin if -i flag is set 225 | if interactive { 226 | cmd.Stdin = os.Stdin 227 | // setting 'Foreground' to true will bind current TTY to the child process 228 | procAttrs = &syscall.SysProcAttr{Setpgid: true, Foreground: true} 229 | } 230 | // set child process attributes 231 | cmd.SysProcAttr = procAttrs 232 | 233 | // set environment variables 234 | if provider != nil { 235 | cmd.Env, err = provider.ResolveSecrets(ctx, os.Environ()) 236 | if err != nil { 237 | log.WithError(err).Error("failed to resolve secrets") 238 | if exitEarly { 239 | log.Error("Exiting early unable to retrieve secrets") 240 | os.Exit(1) 241 | } 242 | } 243 | } else { 244 | log.Warn("no secrets provider available; using environment without resolving secrets") 245 | cmd.Env = os.Environ() 246 | } 247 | 248 | // start the specified command 249 | log.WithFields(log.Fields{ 250 | "command": commandStr, 251 | "args": argsSlice, 252 | "env": cmd.Env, 253 | }).Debug("starting command") 254 | err = cmd.Start() 255 | if err != nil { 256 | return childPid, errors.Wrap(err, "failed to start command") 257 | } 258 | childPid = cmd.Process.Pid 259 | 260 | // Goroutine for signals forwarding 261 | go func() { 262 | for sig := range sigs { 263 | // ignore: 264 | // - SIGCHLD signals, since these are only useful for secrets-init 265 | // - SIGURG signals, since they are used internally by the secrets-init 266 | // go runtime (see https://github.com/golang/go/issues/37942) and are of 267 | // no interest to the child process 268 | if sig != syscall.SIGCHLD && sig != syscall.SIGURG { 269 | // forward signal to the main process and its children 270 | e := syscall.Kill(-cmd.Process.Pid, sig.(syscall.Signal)) 271 | if e != nil { 272 | log.WithFields(log.Fields{ 273 | "pid": cmd.Process.Pid, 274 | "path": cmd.Path, 275 | "args": cmd.Args, 276 | "signal": unix.SignalName(sig.(syscall.Signal)), 277 | }).WithError(e).Error("failed to send system signal to the process") 278 | } 279 | } 280 | } 281 | }() 282 | 283 | return childPid, nil 284 | } 285 | 286 | func setLogFormatter(c *cli.Context) error { 287 | if c.String("log-format") == "json" { 288 | log.SetFormatter(&log.JSONFormatter{}) 289 | } else if c.String("log-format") == "text" { 290 | log.SetFormatter(&log.TextFormatter{}) 291 | } 292 | return nil 293 | } 294 | -------------------------------------------------------------------------------- /mocks/GoogleSecretsManagerAPI.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.14.0. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | context "context" 7 | 8 | gax "github.com/googleapis/gax-go/v2" 9 | 10 | mock "github.com/stretchr/testify/mock" 11 | 12 | secretmanager "google.golang.org/genproto/googleapis/cloud/secretmanager/v1" 13 | ) 14 | 15 | // GoogleSecretsManagerAPI is an autogenerated mock type for the GoogleSecretsManagerAPI type 16 | type GoogleSecretsManagerAPI struct { 17 | mock.Mock 18 | } 19 | 20 | // AccessSecretVersion provides a mock function with given fields: ctx, req, opts 21 | func (_m *GoogleSecretsManagerAPI) AccessSecretVersion(ctx context.Context, req *secretmanager.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretmanager.AccessSecretVersionResponse, error) { 22 | _va := make([]interface{}, len(opts)) 23 | for _i := range opts { 24 | _va[_i] = opts[_i] 25 | } 26 | var _ca []interface{} 27 | _ca = append(_ca, ctx, req) 28 | _ca = append(_ca, _va...) 29 | ret := _m.Called(_ca...) 30 | 31 | var r0 *secretmanager.AccessSecretVersionResponse 32 | if rf, ok := ret.Get(0).(func(context.Context, *secretmanager.AccessSecretVersionRequest, ...gax.CallOption) *secretmanager.AccessSecretVersionResponse); ok { 33 | r0 = rf(ctx, req, opts...) 34 | } else { 35 | if ret.Get(0) != nil { 36 | r0 = ret.Get(0).(*secretmanager.AccessSecretVersionResponse) 37 | } 38 | } 39 | 40 | var r1 error 41 | if rf, ok := ret.Get(1).(func(context.Context, *secretmanager.AccessSecretVersionRequest, ...gax.CallOption) error); ok { 42 | r1 = rf(ctx, req, opts...) 43 | } else { 44 | r1 = ret.Error(1) 45 | } 46 | 47 | return r0, r1 48 | } 49 | 50 | type mockConstructorTestingTNewGoogleSecretsManagerAPI interface { 51 | mock.TestingT 52 | Cleanup(func()) 53 | } 54 | 55 | // NewGoogleSecretsManagerAPI creates a new instance of GoogleSecretsManagerAPI. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 56 | func NewGoogleSecretsManagerAPI(t mockConstructorTestingTNewGoogleSecretsManagerAPI) *GoogleSecretsManagerAPI { 57 | mock := &GoogleSecretsManagerAPI{} 58 | mock.Mock.Test(t) 59 | 60 | t.Cleanup(func() { mock.AssertExpectations(t) }) 61 | 62 | return mock 63 | } 64 | -------------------------------------------------------------------------------- /mocks/SecretsManagerAPI.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.14.0. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | context "context" 7 | 8 | request "github.com/aws/aws-sdk-go/aws/request" 9 | mock "github.com/stretchr/testify/mock" 10 | 11 | secretsmanager "github.com/aws/aws-sdk-go/service/secretsmanager" 12 | ) 13 | 14 | // SecretsManagerAPI is an autogenerated mock type for the SecretsManagerAPI type 15 | type SecretsManagerAPI struct { 16 | mock.Mock 17 | } 18 | 19 | // CancelRotateSecret provides a mock function with given fields: _a0 20 | func (_m *SecretsManagerAPI) CancelRotateSecret(_a0 *secretsmanager.CancelRotateSecretInput) (*secretsmanager.CancelRotateSecretOutput, error) { 21 | ret := _m.Called(_a0) 22 | 23 | var r0 *secretsmanager.CancelRotateSecretOutput 24 | if rf, ok := ret.Get(0).(func(*secretsmanager.CancelRotateSecretInput) *secretsmanager.CancelRotateSecretOutput); ok { 25 | r0 = rf(_a0) 26 | } else { 27 | if ret.Get(0) != nil { 28 | r0 = ret.Get(0).(*secretsmanager.CancelRotateSecretOutput) 29 | } 30 | } 31 | 32 | var r1 error 33 | if rf, ok := ret.Get(1).(func(*secretsmanager.CancelRotateSecretInput) error); ok { 34 | r1 = rf(_a0) 35 | } else { 36 | r1 = ret.Error(1) 37 | } 38 | 39 | return r0, r1 40 | } 41 | 42 | // CancelRotateSecretRequest provides a mock function with given fields: _a0 43 | func (_m *SecretsManagerAPI) CancelRotateSecretRequest(_a0 *secretsmanager.CancelRotateSecretInput) (*request.Request, *secretsmanager.CancelRotateSecretOutput) { 44 | ret := _m.Called(_a0) 45 | 46 | var r0 *request.Request 47 | if rf, ok := ret.Get(0).(func(*secretsmanager.CancelRotateSecretInput) *request.Request); ok { 48 | r0 = rf(_a0) 49 | } else { 50 | if ret.Get(0) != nil { 51 | r0 = ret.Get(0).(*request.Request) 52 | } 53 | } 54 | 55 | var r1 *secretsmanager.CancelRotateSecretOutput 56 | if rf, ok := ret.Get(1).(func(*secretsmanager.CancelRotateSecretInput) *secretsmanager.CancelRotateSecretOutput); ok { 57 | r1 = rf(_a0) 58 | } else { 59 | if ret.Get(1) != nil { 60 | r1 = ret.Get(1).(*secretsmanager.CancelRotateSecretOutput) 61 | } 62 | } 63 | 64 | return r0, r1 65 | } 66 | 67 | // CancelRotateSecretWithContext provides a mock function with given fields: _a0, _a1, _a2 68 | func (_m *SecretsManagerAPI) CancelRotateSecretWithContext(_a0 context.Context, _a1 *secretsmanager.CancelRotateSecretInput, _a2 ...request.Option) (*secretsmanager.CancelRotateSecretOutput, error) { 69 | _va := make([]interface{}, len(_a2)) 70 | for _i := range _a2 { 71 | _va[_i] = _a2[_i] 72 | } 73 | var _ca []interface{} 74 | _ca = append(_ca, _a0, _a1) 75 | _ca = append(_ca, _va...) 76 | ret := _m.Called(_ca...) 77 | 78 | var r0 *secretsmanager.CancelRotateSecretOutput 79 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.CancelRotateSecretInput, ...request.Option) *secretsmanager.CancelRotateSecretOutput); ok { 80 | r0 = rf(_a0, _a1, _a2...) 81 | } else { 82 | if ret.Get(0) != nil { 83 | r0 = ret.Get(0).(*secretsmanager.CancelRotateSecretOutput) 84 | } 85 | } 86 | 87 | var r1 error 88 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.CancelRotateSecretInput, ...request.Option) error); ok { 89 | r1 = rf(_a0, _a1, _a2...) 90 | } else { 91 | r1 = ret.Error(1) 92 | } 93 | 94 | return r0, r1 95 | } 96 | 97 | // CreateSecret provides a mock function with given fields: _a0 98 | func (_m *SecretsManagerAPI) CreateSecret(_a0 *secretsmanager.CreateSecretInput) (*secretsmanager.CreateSecretOutput, error) { 99 | ret := _m.Called(_a0) 100 | 101 | var r0 *secretsmanager.CreateSecretOutput 102 | if rf, ok := ret.Get(0).(func(*secretsmanager.CreateSecretInput) *secretsmanager.CreateSecretOutput); ok { 103 | r0 = rf(_a0) 104 | } else { 105 | if ret.Get(0) != nil { 106 | r0 = ret.Get(0).(*secretsmanager.CreateSecretOutput) 107 | } 108 | } 109 | 110 | var r1 error 111 | if rf, ok := ret.Get(1).(func(*secretsmanager.CreateSecretInput) error); ok { 112 | r1 = rf(_a0) 113 | } else { 114 | r1 = ret.Error(1) 115 | } 116 | 117 | return r0, r1 118 | } 119 | 120 | // CreateSecretRequest provides a mock function with given fields: _a0 121 | func (_m *SecretsManagerAPI) CreateSecretRequest(_a0 *secretsmanager.CreateSecretInput) (*request.Request, *secretsmanager.CreateSecretOutput) { 122 | ret := _m.Called(_a0) 123 | 124 | var r0 *request.Request 125 | if rf, ok := ret.Get(0).(func(*secretsmanager.CreateSecretInput) *request.Request); ok { 126 | r0 = rf(_a0) 127 | } else { 128 | if ret.Get(0) != nil { 129 | r0 = ret.Get(0).(*request.Request) 130 | } 131 | } 132 | 133 | var r1 *secretsmanager.CreateSecretOutput 134 | if rf, ok := ret.Get(1).(func(*secretsmanager.CreateSecretInput) *secretsmanager.CreateSecretOutput); ok { 135 | r1 = rf(_a0) 136 | } else { 137 | if ret.Get(1) != nil { 138 | r1 = ret.Get(1).(*secretsmanager.CreateSecretOutput) 139 | } 140 | } 141 | 142 | return r0, r1 143 | } 144 | 145 | // CreateSecretWithContext provides a mock function with given fields: _a0, _a1, _a2 146 | func (_m *SecretsManagerAPI) CreateSecretWithContext(_a0 context.Context, _a1 *secretsmanager.CreateSecretInput, _a2 ...request.Option) (*secretsmanager.CreateSecretOutput, error) { 147 | _va := make([]interface{}, len(_a2)) 148 | for _i := range _a2 { 149 | _va[_i] = _a2[_i] 150 | } 151 | var _ca []interface{} 152 | _ca = append(_ca, _a0, _a1) 153 | _ca = append(_ca, _va...) 154 | ret := _m.Called(_ca...) 155 | 156 | var r0 *secretsmanager.CreateSecretOutput 157 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.CreateSecretInput, ...request.Option) *secretsmanager.CreateSecretOutput); ok { 158 | r0 = rf(_a0, _a1, _a2...) 159 | } else { 160 | if ret.Get(0) != nil { 161 | r0 = ret.Get(0).(*secretsmanager.CreateSecretOutput) 162 | } 163 | } 164 | 165 | var r1 error 166 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.CreateSecretInput, ...request.Option) error); ok { 167 | r1 = rf(_a0, _a1, _a2...) 168 | } else { 169 | r1 = ret.Error(1) 170 | } 171 | 172 | return r0, r1 173 | } 174 | 175 | // DeleteResourcePolicy provides a mock function with given fields: _a0 176 | func (_m *SecretsManagerAPI) DeleteResourcePolicy(_a0 *secretsmanager.DeleteResourcePolicyInput) (*secretsmanager.DeleteResourcePolicyOutput, error) { 177 | ret := _m.Called(_a0) 178 | 179 | var r0 *secretsmanager.DeleteResourcePolicyOutput 180 | if rf, ok := ret.Get(0).(func(*secretsmanager.DeleteResourcePolicyInput) *secretsmanager.DeleteResourcePolicyOutput); ok { 181 | r0 = rf(_a0) 182 | } else { 183 | if ret.Get(0) != nil { 184 | r0 = ret.Get(0).(*secretsmanager.DeleteResourcePolicyOutput) 185 | } 186 | } 187 | 188 | var r1 error 189 | if rf, ok := ret.Get(1).(func(*secretsmanager.DeleteResourcePolicyInput) error); ok { 190 | r1 = rf(_a0) 191 | } else { 192 | r1 = ret.Error(1) 193 | } 194 | 195 | return r0, r1 196 | } 197 | 198 | // DeleteResourcePolicyRequest provides a mock function with given fields: _a0 199 | func (_m *SecretsManagerAPI) DeleteResourcePolicyRequest(_a0 *secretsmanager.DeleteResourcePolicyInput) (*request.Request, *secretsmanager.DeleteResourcePolicyOutput) { 200 | ret := _m.Called(_a0) 201 | 202 | var r0 *request.Request 203 | if rf, ok := ret.Get(0).(func(*secretsmanager.DeleteResourcePolicyInput) *request.Request); ok { 204 | r0 = rf(_a0) 205 | } else { 206 | if ret.Get(0) != nil { 207 | r0 = ret.Get(0).(*request.Request) 208 | } 209 | } 210 | 211 | var r1 *secretsmanager.DeleteResourcePolicyOutput 212 | if rf, ok := ret.Get(1).(func(*secretsmanager.DeleteResourcePolicyInput) *secretsmanager.DeleteResourcePolicyOutput); ok { 213 | r1 = rf(_a0) 214 | } else { 215 | if ret.Get(1) != nil { 216 | r1 = ret.Get(1).(*secretsmanager.DeleteResourcePolicyOutput) 217 | } 218 | } 219 | 220 | return r0, r1 221 | } 222 | 223 | // DeleteResourcePolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 224 | func (_m *SecretsManagerAPI) DeleteResourcePolicyWithContext(_a0 context.Context, _a1 *secretsmanager.DeleteResourcePolicyInput, _a2 ...request.Option) (*secretsmanager.DeleteResourcePolicyOutput, error) { 225 | _va := make([]interface{}, len(_a2)) 226 | for _i := range _a2 { 227 | _va[_i] = _a2[_i] 228 | } 229 | var _ca []interface{} 230 | _ca = append(_ca, _a0, _a1) 231 | _ca = append(_ca, _va...) 232 | ret := _m.Called(_ca...) 233 | 234 | var r0 *secretsmanager.DeleteResourcePolicyOutput 235 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.DeleteResourcePolicyInput, ...request.Option) *secretsmanager.DeleteResourcePolicyOutput); ok { 236 | r0 = rf(_a0, _a1, _a2...) 237 | } else { 238 | if ret.Get(0) != nil { 239 | r0 = ret.Get(0).(*secretsmanager.DeleteResourcePolicyOutput) 240 | } 241 | } 242 | 243 | var r1 error 244 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.DeleteResourcePolicyInput, ...request.Option) error); ok { 245 | r1 = rf(_a0, _a1, _a2...) 246 | } else { 247 | r1 = ret.Error(1) 248 | } 249 | 250 | return r0, r1 251 | } 252 | 253 | // DeleteSecret provides a mock function with given fields: _a0 254 | func (_m *SecretsManagerAPI) DeleteSecret(_a0 *secretsmanager.DeleteSecretInput) (*secretsmanager.DeleteSecretOutput, error) { 255 | ret := _m.Called(_a0) 256 | 257 | var r0 *secretsmanager.DeleteSecretOutput 258 | if rf, ok := ret.Get(0).(func(*secretsmanager.DeleteSecretInput) *secretsmanager.DeleteSecretOutput); ok { 259 | r0 = rf(_a0) 260 | } else { 261 | if ret.Get(0) != nil { 262 | r0 = ret.Get(0).(*secretsmanager.DeleteSecretOutput) 263 | } 264 | } 265 | 266 | var r1 error 267 | if rf, ok := ret.Get(1).(func(*secretsmanager.DeleteSecretInput) error); ok { 268 | r1 = rf(_a0) 269 | } else { 270 | r1 = ret.Error(1) 271 | } 272 | 273 | return r0, r1 274 | } 275 | 276 | // DeleteSecretRequest provides a mock function with given fields: _a0 277 | func (_m *SecretsManagerAPI) DeleteSecretRequest(_a0 *secretsmanager.DeleteSecretInput) (*request.Request, *secretsmanager.DeleteSecretOutput) { 278 | ret := _m.Called(_a0) 279 | 280 | var r0 *request.Request 281 | if rf, ok := ret.Get(0).(func(*secretsmanager.DeleteSecretInput) *request.Request); ok { 282 | r0 = rf(_a0) 283 | } else { 284 | if ret.Get(0) != nil { 285 | r0 = ret.Get(0).(*request.Request) 286 | } 287 | } 288 | 289 | var r1 *secretsmanager.DeleteSecretOutput 290 | if rf, ok := ret.Get(1).(func(*secretsmanager.DeleteSecretInput) *secretsmanager.DeleteSecretOutput); ok { 291 | r1 = rf(_a0) 292 | } else { 293 | if ret.Get(1) != nil { 294 | r1 = ret.Get(1).(*secretsmanager.DeleteSecretOutput) 295 | } 296 | } 297 | 298 | return r0, r1 299 | } 300 | 301 | // DeleteSecretWithContext provides a mock function with given fields: _a0, _a1, _a2 302 | func (_m *SecretsManagerAPI) DeleteSecretWithContext(_a0 context.Context, _a1 *secretsmanager.DeleteSecretInput, _a2 ...request.Option) (*secretsmanager.DeleteSecretOutput, error) { 303 | _va := make([]interface{}, len(_a2)) 304 | for _i := range _a2 { 305 | _va[_i] = _a2[_i] 306 | } 307 | var _ca []interface{} 308 | _ca = append(_ca, _a0, _a1) 309 | _ca = append(_ca, _va...) 310 | ret := _m.Called(_ca...) 311 | 312 | var r0 *secretsmanager.DeleteSecretOutput 313 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.DeleteSecretInput, ...request.Option) *secretsmanager.DeleteSecretOutput); ok { 314 | r0 = rf(_a0, _a1, _a2...) 315 | } else { 316 | if ret.Get(0) != nil { 317 | r0 = ret.Get(0).(*secretsmanager.DeleteSecretOutput) 318 | } 319 | } 320 | 321 | var r1 error 322 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.DeleteSecretInput, ...request.Option) error); ok { 323 | r1 = rf(_a0, _a1, _a2...) 324 | } else { 325 | r1 = ret.Error(1) 326 | } 327 | 328 | return r0, r1 329 | } 330 | 331 | // DescribeSecret provides a mock function with given fields: _a0 332 | func (_m *SecretsManagerAPI) DescribeSecret(_a0 *secretsmanager.DescribeSecretInput) (*secretsmanager.DescribeSecretOutput, error) { 333 | ret := _m.Called(_a0) 334 | 335 | var r0 *secretsmanager.DescribeSecretOutput 336 | if rf, ok := ret.Get(0).(func(*secretsmanager.DescribeSecretInput) *secretsmanager.DescribeSecretOutput); ok { 337 | r0 = rf(_a0) 338 | } else { 339 | if ret.Get(0) != nil { 340 | r0 = ret.Get(0).(*secretsmanager.DescribeSecretOutput) 341 | } 342 | } 343 | 344 | var r1 error 345 | if rf, ok := ret.Get(1).(func(*secretsmanager.DescribeSecretInput) error); ok { 346 | r1 = rf(_a0) 347 | } else { 348 | r1 = ret.Error(1) 349 | } 350 | 351 | return r0, r1 352 | } 353 | 354 | // DescribeSecretRequest provides a mock function with given fields: _a0 355 | func (_m *SecretsManagerAPI) DescribeSecretRequest(_a0 *secretsmanager.DescribeSecretInput) (*request.Request, *secretsmanager.DescribeSecretOutput) { 356 | ret := _m.Called(_a0) 357 | 358 | var r0 *request.Request 359 | if rf, ok := ret.Get(0).(func(*secretsmanager.DescribeSecretInput) *request.Request); ok { 360 | r0 = rf(_a0) 361 | } else { 362 | if ret.Get(0) != nil { 363 | r0 = ret.Get(0).(*request.Request) 364 | } 365 | } 366 | 367 | var r1 *secretsmanager.DescribeSecretOutput 368 | if rf, ok := ret.Get(1).(func(*secretsmanager.DescribeSecretInput) *secretsmanager.DescribeSecretOutput); ok { 369 | r1 = rf(_a0) 370 | } else { 371 | if ret.Get(1) != nil { 372 | r1 = ret.Get(1).(*secretsmanager.DescribeSecretOutput) 373 | } 374 | } 375 | 376 | return r0, r1 377 | } 378 | 379 | // DescribeSecretWithContext provides a mock function with given fields: _a0, _a1, _a2 380 | func (_m *SecretsManagerAPI) DescribeSecretWithContext(_a0 context.Context, _a1 *secretsmanager.DescribeSecretInput, _a2 ...request.Option) (*secretsmanager.DescribeSecretOutput, error) { 381 | _va := make([]interface{}, len(_a2)) 382 | for _i := range _a2 { 383 | _va[_i] = _a2[_i] 384 | } 385 | var _ca []interface{} 386 | _ca = append(_ca, _a0, _a1) 387 | _ca = append(_ca, _va...) 388 | ret := _m.Called(_ca...) 389 | 390 | var r0 *secretsmanager.DescribeSecretOutput 391 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.DescribeSecretInput, ...request.Option) *secretsmanager.DescribeSecretOutput); ok { 392 | r0 = rf(_a0, _a1, _a2...) 393 | } else { 394 | if ret.Get(0) != nil { 395 | r0 = ret.Get(0).(*secretsmanager.DescribeSecretOutput) 396 | } 397 | } 398 | 399 | var r1 error 400 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.DescribeSecretInput, ...request.Option) error); ok { 401 | r1 = rf(_a0, _a1, _a2...) 402 | } else { 403 | r1 = ret.Error(1) 404 | } 405 | 406 | return r0, r1 407 | } 408 | 409 | // GetRandomPassword provides a mock function with given fields: _a0 410 | func (_m *SecretsManagerAPI) GetRandomPassword(_a0 *secretsmanager.GetRandomPasswordInput) (*secretsmanager.GetRandomPasswordOutput, error) { 411 | ret := _m.Called(_a0) 412 | 413 | var r0 *secretsmanager.GetRandomPasswordOutput 414 | if rf, ok := ret.Get(0).(func(*secretsmanager.GetRandomPasswordInput) *secretsmanager.GetRandomPasswordOutput); ok { 415 | r0 = rf(_a0) 416 | } else { 417 | if ret.Get(0) != nil { 418 | r0 = ret.Get(0).(*secretsmanager.GetRandomPasswordOutput) 419 | } 420 | } 421 | 422 | var r1 error 423 | if rf, ok := ret.Get(1).(func(*secretsmanager.GetRandomPasswordInput) error); ok { 424 | r1 = rf(_a0) 425 | } else { 426 | r1 = ret.Error(1) 427 | } 428 | 429 | return r0, r1 430 | } 431 | 432 | // GetRandomPasswordRequest provides a mock function with given fields: _a0 433 | func (_m *SecretsManagerAPI) GetRandomPasswordRequest(_a0 *secretsmanager.GetRandomPasswordInput) (*request.Request, *secretsmanager.GetRandomPasswordOutput) { 434 | ret := _m.Called(_a0) 435 | 436 | var r0 *request.Request 437 | if rf, ok := ret.Get(0).(func(*secretsmanager.GetRandomPasswordInput) *request.Request); ok { 438 | r0 = rf(_a0) 439 | } else { 440 | if ret.Get(0) != nil { 441 | r0 = ret.Get(0).(*request.Request) 442 | } 443 | } 444 | 445 | var r1 *secretsmanager.GetRandomPasswordOutput 446 | if rf, ok := ret.Get(1).(func(*secretsmanager.GetRandomPasswordInput) *secretsmanager.GetRandomPasswordOutput); ok { 447 | r1 = rf(_a0) 448 | } else { 449 | if ret.Get(1) != nil { 450 | r1 = ret.Get(1).(*secretsmanager.GetRandomPasswordOutput) 451 | } 452 | } 453 | 454 | return r0, r1 455 | } 456 | 457 | // GetRandomPasswordWithContext provides a mock function with given fields: _a0, _a1, _a2 458 | func (_m *SecretsManagerAPI) GetRandomPasswordWithContext(_a0 context.Context, _a1 *secretsmanager.GetRandomPasswordInput, _a2 ...request.Option) (*secretsmanager.GetRandomPasswordOutput, error) { 459 | _va := make([]interface{}, len(_a2)) 460 | for _i := range _a2 { 461 | _va[_i] = _a2[_i] 462 | } 463 | var _ca []interface{} 464 | _ca = append(_ca, _a0, _a1) 465 | _ca = append(_ca, _va...) 466 | ret := _m.Called(_ca...) 467 | 468 | var r0 *secretsmanager.GetRandomPasswordOutput 469 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.GetRandomPasswordInput, ...request.Option) *secretsmanager.GetRandomPasswordOutput); ok { 470 | r0 = rf(_a0, _a1, _a2...) 471 | } else { 472 | if ret.Get(0) != nil { 473 | r0 = ret.Get(0).(*secretsmanager.GetRandomPasswordOutput) 474 | } 475 | } 476 | 477 | var r1 error 478 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.GetRandomPasswordInput, ...request.Option) error); ok { 479 | r1 = rf(_a0, _a1, _a2...) 480 | } else { 481 | r1 = ret.Error(1) 482 | } 483 | 484 | return r0, r1 485 | } 486 | 487 | // GetResourcePolicy provides a mock function with given fields: _a0 488 | func (_m *SecretsManagerAPI) GetResourcePolicy(_a0 *secretsmanager.GetResourcePolicyInput) (*secretsmanager.GetResourcePolicyOutput, error) { 489 | ret := _m.Called(_a0) 490 | 491 | var r0 *secretsmanager.GetResourcePolicyOutput 492 | if rf, ok := ret.Get(0).(func(*secretsmanager.GetResourcePolicyInput) *secretsmanager.GetResourcePolicyOutput); ok { 493 | r0 = rf(_a0) 494 | } else { 495 | if ret.Get(0) != nil { 496 | r0 = ret.Get(0).(*secretsmanager.GetResourcePolicyOutput) 497 | } 498 | } 499 | 500 | var r1 error 501 | if rf, ok := ret.Get(1).(func(*secretsmanager.GetResourcePolicyInput) error); ok { 502 | r1 = rf(_a0) 503 | } else { 504 | r1 = ret.Error(1) 505 | } 506 | 507 | return r0, r1 508 | } 509 | 510 | // GetResourcePolicyRequest provides a mock function with given fields: _a0 511 | func (_m *SecretsManagerAPI) GetResourcePolicyRequest(_a0 *secretsmanager.GetResourcePolicyInput) (*request.Request, *secretsmanager.GetResourcePolicyOutput) { 512 | ret := _m.Called(_a0) 513 | 514 | var r0 *request.Request 515 | if rf, ok := ret.Get(0).(func(*secretsmanager.GetResourcePolicyInput) *request.Request); ok { 516 | r0 = rf(_a0) 517 | } else { 518 | if ret.Get(0) != nil { 519 | r0 = ret.Get(0).(*request.Request) 520 | } 521 | } 522 | 523 | var r1 *secretsmanager.GetResourcePolicyOutput 524 | if rf, ok := ret.Get(1).(func(*secretsmanager.GetResourcePolicyInput) *secretsmanager.GetResourcePolicyOutput); ok { 525 | r1 = rf(_a0) 526 | } else { 527 | if ret.Get(1) != nil { 528 | r1 = ret.Get(1).(*secretsmanager.GetResourcePolicyOutput) 529 | } 530 | } 531 | 532 | return r0, r1 533 | } 534 | 535 | // GetResourcePolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 536 | func (_m *SecretsManagerAPI) GetResourcePolicyWithContext(_a0 context.Context, _a1 *secretsmanager.GetResourcePolicyInput, _a2 ...request.Option) (*secretsmanager.GetResourcePolicyOutput, error) { 537 | _va := make([]interface{}, len(_a2)) 538 | for _i := range _a2 { 539 | _va[_i] = _a2[_i] 540 | } 541 | var _ca []interface{} 542 | _ca = append(_ca, _a0, _a1) 543 | _ca = append(_ca, _va...) 544 | ret := _m.Called(_ca...) 545 | 546 | var r0 *secretsmanager.GetResourcePolicyOutput 547 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.GetResourcePolicyInput, ...request.Option) *secretsmanager.GetResourcePolicyOutput); ok { 548 | r0 = rf(_a0, _a1, _a2...) 549 | } else { 550 | if ret.Get(0) != nil { 551 | r0 = ret.Get(0).(*secretsmanager.GetResourcePolicyOutput) 552 | } 553 | } 554 | 555 | var r1 error 556 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.GetResourcePolicyInput, ...request.Option) error); ok { 557 | r1 = rf(_a0, _a1, _a2...) 558 | } else { 559 | r1 = ret.Error(1) 560 | } 561 | 562 | return r0, r1 563 | } 564 | 565 | // GetSecretValue provides a mock function with given fields: _a0 566 | func (_m *SecretsManagerAPI) GetSecretValue(_a0 *secretsmanager.GetSecretValueInput) (*secretsmanager.GetSecretValueOutput, error) { 567 | ret := _m.Called(_a0) 568 | 569 | var r0 *secretsmanager.GetSecretValueOutput 570 | if rf, ok := ret.Get(0).(func(*secretsmanager.GetSecretValueInput) *secretsmanager.GetSecretValueOutput); ok { 571 | r0 = rf(_a0) 572 | } else { 573 | if ret.Get(0) != nil { 574 | r0 = ret.Get(0).(*secretsmanager.GetSecretValueOutput) 575 | } 576 | } 577 | 578 | var r1 error 579 | if rf, ok := ret.Get(1).(func(*secretsmanager.GetSecretValueInput) error); ok { 580 | r1 = rf(_a0) 581 | } else { 582 | r1 = ret.Error(1) 583 | } 584 | 585 | return r0, r1 586 | } 587 | 588 | // GetSecretValueRequest provides a mock function with given fields: _a0 589 | func (_m *SecretsManagerAPI) GetSecretValueRequest(_a0 *secretsmanager.GetSecretValueInput) (*request.Request, *secretsmanager.GetSecretValueOutput) { 590 | ret := _m.Called(_a0) 591 | 592 | var r0 *request.Request 593 | if rf, ok := ret.Get(0).(func(*secretsmanager.GetSecretValueInput) *request.Request); ok { 594 | r0 = rf(_a0) 595 | } else { 596 | if ret.Get(0) != nil { 597 | r0 = ret.Get(0).(*request.Request) 598 | } 599 | } 600 | 601 | var r1 *secretsmanager.GetSecretValueOutput 602 | if rf, ok := ret.Get(1).(func(*secretsmanager.GetSecretValueInput) *secretsmanager.GetSecretValueOutput); ok { 603 | r1 = rf(_a0) 604 | } else { 605 | if ret.Get(1) != nil { 606 | r1 = ret.Get(1).(*secretsmanager.GetSecretValueOutput) 607 | } 608 | } 609 | 610 | return r0, r1 611 | } 612 | 613 | // GetSecretValueWithContext provides a mock function with given fields: _a0, _a1, _a2 614 | func (_m *SecretsManagerAPI) GetSecretValueWithContext(_a0 context.Context, _a1 *secretsmanager.GetSecretValueInput, _a2 ...request.Option) (*secretsmanager.GetSecretValueOutput, error) { 615 | _va := make([]interface{}, len(_a2)) 616 | for _i := range _a2 { 617 | _va[_i] = _a2[_i] 618 | } 619 | var _ca []interface{} 620 | _ca = append(_ca, _a0, _a1) 621 | _ca = append(_ca, _va...) 622 | ret := _m.Called(_ca...) 623 | 624 | var r0 *secretsmanager.GetSecretValueOutput 625 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.GetSecretValueInput, ...request.Option) *secretsmanager.GetSecretValueOutput); ok { 626 | r0 = rf(_a0, _a1, _a2...) 627 | } else { 628 | if ret.Get(0) != nil { 629 | r0 = ret.Get(0).(*secretsmanager.GetSecretValueOutput) 630 | } 631 | } 632 | 633 | var r1 error 634 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.GetSecretValueInput, ...request.Option) error); ok { 635 | r1 = rf(_a0, _a1, _a2...) 636 | } else { 637 | r1 = ret.Error(1) 638 | } 639 | 640 | return r0, r1 641 | } 642 | 643 | // ListSecretVersionIds provides a mock function with given fields: _a0 644 | func (_m *SecretsManagerAPI) ListSecretVersionIds(_a0 *secretsmanager.ListSecretVersionIdsInput) (*secretsmanager.ListSecretVersionIdsOutput, error) { 645 | ret := _m.Called(_a0) 646 | 647 | var r0 *secretsmanager.ListSecretVersionIdsOutput 648 | if rf, ok := ret.Get(0).(func(*secretsmanager.ListSecretVersionIdsInput) *secretsmanager.ListSecretVersionIdsOutput); ok { 649 | r0 = rf(_a0) 650 | } else { 651 | if ret.Get(0) != nil { 652 | r0 = ret.Get(0).(*secretsmanager.ListSecretVersionIdsOutput) 653 | } 654 | } 655 | 656 | var r1 error 657 | if rf, ok := ret.Get(1).(func(*secretsmanager.ListSecretVersionIdsInput) error); ok { 658 | r1 = rf(_a0) 659 | } else { 660 | r1 = ret.Error(1) 661 | } 662 | 663 | return r0, r1 664 | } 665 | 666 | // ListSecretVersionIdsPages provides a mock function with given fields: _a0, _a1 667 | func (_m *SecretsManagerAPI) ListSecretVersionIdsPages(_a0 *secretsmanager.ListSecretVersionIdsInput, _a1 func(*secretsmanager.ListSecretVersionIdsOutput, bool) bool) error { 668 | ret := _m.Called(_a0, _a1) 669 | 670 | var r0 error 671 | if rf, ok := ret.Get(0).(func(*secretsmanager.ListSecretVersionIdsInput, func(*secretsmanager.ListSecretVersionIdsOutput, bool) bool) error); ok { 672 | r0 = rf(_a0, _a1) 673 | } else { 674 | r0 = ret.Error(0) 675 | } 676 | 677 | return r0 678 | } 679 | 680 | // ListSecretVersionIdsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 681 | func (_m *SecretsManagerAPI) ListSecretVersionIdsPagesWithContext(_a0 context.Context, _a1 *secretsmanager.ListSecretVersionIdsInput, _a2 func(*secretsmanager.ListSecretVersionIdsOutput, bool) bool, _a3 ...request.Option) error { 682 | _va := make([]interface{}, len(_a3)) 683 | for _i := range _a3 { 684 | _va[_i] = _a3[_i] 685 | } 686 | var _ca []interface{} 687 | _ca = append(_ca, _a0, _a1, _a2) 688 | _ca = append(_ca, _va...) 689 | ret := _m.Called(_ca...) 690 | 691 | var r0 error 692 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.ListSecretVersionIdsInput, func(*secretsmanager.ListSecretVersionIdsOutput, bool) bool, ...request.Option) error); ok { 693 | r0 = rf(_a0, _a1, _a2, _a3...) 694 | } else { 695 | r0 = ret.Error(0) 696 | } 697 | 698 | return r0 699 | } 700 | 701 | // ListSecretVersionIdsRequest provides a mock function with given fields: _a0 702 | func (_m *SecretsManagerAPI) ListSecretVersionIdsRequest(_a0 *secretsmanager.ListSecretVersionIdsInput) (*request.Request, *secretsmanager.ListSecretVersionIdsOutput) { 703 | ret := _m.Called(_a0) 704 | 705 | var r0 *request.Request 706 | if rf, ok := ret.Get(0).(func(*secretsmanager.ListSecretVersionIdsInput) *request.Request); ok { 707 | r0 = rf(_a0) 708 | } else { 709 | if ret.Get(0) != nil { 710 | r0 = ret.Get(0).(*request.Request) 711 | } 712 | } 713 | 714 | var r1 *secretsmanager.ListSecretVersionIdsOutput 715 | if rf, ok := ret.Get(1).(func(*secretsmanager.ListSecretVersionIdsInput) *secretsmanager.ListSecretVersionIdsOutput); ok { 716 | r1 = rf(_a0) 717 | } else { 718 | if ret.Get(1) != nil { 719 | r1 = ret.Get(1).(*secretsmanager.ListSecretVersionIdsOutput) 720 | } 721 | } 722 | 723 | return r0, r1 724 | } 725 | 726 | // ListSecretVersionIdsWithContext provides a mock function with given fields: _a0, _a1, _a2 727 | func (_m *SecretsManagerAPI) ListSecretVersionIdsWithContext(_a0 context.Context, _a1 *secretsmanager.ListSecretVersionIdsInput, _a2 ...request.Option) (*secretsmanager.ListSecretVersionIdsOutput, error) { 728 | _va := make([]interface{}, len(_a2)) 729 | for _i := range _a2 { 730 | _va[_i] = _a2[_i] 731 | } 732 | var _ca []interface{} 733 | _ca = append(_ca, _a0, _a1) 734 | _ca = append(_ca, _va...) 735 | ret := _m.Called(_ca...) 736 | 737 | var r0 *secretsmanager.ListSecretVersionIdsOutput 738 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.ListSecretVersionIdsInput, ...request.Option) *secretsmanager.ListSecretVersionIdsOutput); ok { 739 | r0 = rf(_a0, _a1, _a2...) 740 | } else { 741 | if ret.Get(0) != nil { 742 | r0 = ret.Get(0).(*secretsmanager.ListSecretVersionIdsOutput) 743 | } 744 | } 745 | 746 | var r1 error 747 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.ListSecretVersionIdsInput, ...request.Option) error); ok { 748 | r1 = rf(_a0, _a1, _a2...) 749 | } else { 750 | r1 = ret.Error(1) 751 | } 752 | 753 | return r0, r1 754 | } 755 | 756 | // ListSecrets provides a mock function with given fields: _a0 757 | func (_m *SecretsManagerAPI) ListSecrets(_a0 *secretsmanager.ListSecretsInput) (*secretsmanager.ListSecretsOutput, error) { 758 | ret := _m.Called(_a0) 759 | 760 | var r0 *secretsmanager.ListSecretsOutput 761 | if rf, ok := ret.Get(0).(func(*secretsmanager.ListSecretsInput) *secretsmanager.ListSecretsOutput); ok { 762 | r0 = rf(_a0) 763 | } else { 764 | if ret.Get(0) != nil { 765 | r0 = ret.Get(0).(*secretsmanager.ListSecretsOutput) 766 | } 767 | } 768 | 769 | var r1 error 770 | if rf, ok := ret.Get(1).(func(*secretsmanager.ListSecretsInput) error); ok { 771 | r1 = rf(_a0) 772 | } else { 773 | r1 = ret.Error(1) 774 | } 775 | 776 | return r0, r1 777 | } 778 | 779 | // ListSecretsPages provides a mock function with given fields: _a0, _a1 780 | func (_m *SecretsManagerAPI) ListSecretsPages(_a0 *secretsmanager.ListSecretsInput, _a1 func(*secretsmanager.ListSecretsOutput, bool) bool) error { 781 | ret := _m.Called(_a0, _a1) 782 | 783 | var r0 error 784 | if rf, ok := ret.Get(0).(func(*secretsmanager.ListSecretsInput, func(*secretsmanager.ListSecretsOutput, bool) bool) error); ok { 785 | r0 = rf(_a0, _a1) 786 | } else { 787 | r0 = ret.Error(0) 788 | } 789 | 790 | return r0 791 | } 792 | 793 | // ListSecretsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 794 | func (_m *SecretsManagerAPI) ListSecretsPagesWithContext(_a0 context.Context, _a1 *secretsmanager.ListSecretsInput, _a2 func(*secretsmanager.ListSecretsOutput, bool) bool, _a3 ...request.Option) error { 795 | _va := make([]interface{}, len(_a3)) 796 | for _i := range _a3 { 797 | _va[_i] = _a3[_i] 798 | } 799 | var _ca []interface{} 800 | _ca = append(_ca, _a0, _a1, _a2) 801 | _ca = append(_ca, _va...) 802 | ret := _m.Called(_ca...) 803 | 804 | var r0 error 805 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.ListSecretsInput, func(*secretsmanager.ListSecretsOutput, bool) bool, ...request.Option) error); ok { 806 | r0 = rf(_a0, _a1, _a2, _a3...) 807 | } else { 808 | r0 = ret.Error(0) 809 | } 810 | 811 | return r0 812 | } 813 | 814 | // ListSecretsRequest provides a mock function with given fields: _a0 815 | func (_m *SecretsManagerAPI) ListSecretsRequest(_a0 *secretsmanager.ListSecretsInput) (*request.Request, *secretsmanager.ListSecretsOutput) { 816 | ret := _m.Called(_a0) 817 | 818 | var r0 *request.Request 819 | if rf, ok := ret.Get(0).(func(*secretsmanager.ListSecretsInput) *request.Request); ok { 820 | r0 = rf(_a0) 821 | } else { 822 | if ret.Get(0) != nil { 823 | r0 = ret.Get(0).(*request.Request) 824 | } 825 | } 826 | 827 | var r1 *secretsmanager.ListSecretsOutput 828 | if rf, ok := ret.Get(1).(func(*secretsmanager.ListSecretsInput) *secretsmanager.ListSecretsOutput); ok { 829 | r1 = rf(_a0) 830 | } else { 831 | if ret.Get(1) != nil { 832 | r1 = ret.Get(1).(*secretsmanager.ListSecretsOutput) 833 | } 834 | } 835 | 836 | return r0, r1 837 | } 838 | 839 | // ListSecretsWithContext provides a mock function with given fields: _a0, _a1, _a2 840 | func (_m *SecretsManagerAPI) ListSecretsWithContext(_a0 context.Context, _a1 *secretsmanager.ListSecretsInput, _a2 ...request.Option) (*secretsmanager.ListSecretsOutput, error) { 841 | _va := make([]interface{}, len(_a2)) 842 | for _i := range _a2 { 843 | _va[_i] = _a2[_i] 844 | } 845 | var _ca []interface{} 846 | _ca = append(_ca, _a0, _a1) 847 | _ca = append(_ca, _va...) 848 | ret := _m.Called(_ca...) 849 | 850 | var r0 *secretsmanager.ListSecretsOutput 851 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.ListSecretsInput, ...request.Option) *secretsmanager.ListSecretsOutput); ok { 852 | r0 = rf(_a0, _a1, _a2...) 853 | } else { 854 | if ret.Get(0) != nil { 855 | r0 = ret.Get(0).(*secretsmanager.ListSecretsOutput) 856 | } 857 | } 858 | 859 | var r1 error 860 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.ListSecretsInput, ...request.Option) error); ok { 861 | r1 = rf(_a0, _a1, _a2...) 862 | } else { 863 | r1 = ret.Error(1) 864 | } 865 | 866 | return r0, r1 867 | } 868 | 869 | // PutResourcePolicy provides a mock function with given fields: _a0 870 | func (_m *SecretsManagerAPI) PutResourcePolicy(_a0 *secretsmanager.PutResourcePolicyInput) (*secretsmanager.PutResourcePolicyOutput, error) { 871 | ret := _m.Called(_a0) 872 | 873 | var r0 *secretsmanager.PutResourcePolicyOutput 874 | if rf, ok := ret.Get(0).(func(*secretsmanager.PutResourcePolicyInput) *secretsmanager.PutResourcePolicyOutput); ok { 875 | r0 = rf(_a0) 876 | } else { 877 | if ret.Get(0) != nil { 878 | r0 = ret.Get(0).(*secretsmanager.PutResourcePolicyOutput) 879 | } 880 | } 881 | 882 | var r1 error 883 | if rf, ok := ret.Get(1).(func(*secretsmanager.PutResourcePolicyInput) error); ok { 884 | r1 = rf(_a0) 885 | } else { 886 | r1 = ret.Error(1) 887 | } 888 | 889 | return r0, r1 890 | } 891 | 892 | // PutResourcePolicyRequest provides a mock function with given fields: _a0 893 | func (_m *SecretsManagerAPI) PutResourcePolicyRequest(_a0 *secretsmanager.PutResourcePolicyInput) (*request.Request, *secretsmanager.PutResourcePolicyOutput) { 894 | ret := _m.Called(_a0) 895 | 896 | var r0 *request.Request 897 | if rf, ok := ret.Get(0).(func(*secretsmanager.PutResourcePolicyInput) *request.Request); ok { 898 | r0 = rf(_a0) 899 | } else { 900 | if ret.Get(0) != nil { 901 | r0 = ret.Get(0).(*request.Request) 902 | } 903 | } 904 | 905 | var r1 *secretsmanager.PutResourcePolicyOutput 906 | if rf, ok := ret.Get(1).(func(*secretsmanager.PutResourcePolicyInput) *secretsmanager.PutResourcePolicyOutput); ok { 907 | r1 = rf(_a0) 908 | } else { 909 | if ret.Get(1) != nil { 910 | r1 = ret.Get(1).(*secretsmanager.PutResourcePolicyOutput) 911 | } 912 | } 913 | 914 | return r0, r1 915 | } 916 | 917 | // PutResourcePolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 918 | func (_m *SecretsManagerAPI) PutResourcePolicyWithContext(_a0 context.Context, _a1 *secretsmanager.PutResourcePolicyInput, _a2 ...request.Option) (*secretsmanager.PutResourcePolicyOutput, error) { 919 | _va := make([]interface{}, len(_a2)) 920 | for _i := range _a2 { 921 | _va[_i] = _a2[_i] 922 | } 923 | var _ca []interface{} 924 | _ca = append(_ca, _a0, _a1) 925 | _ca = append(_ca, _va...) 926 | ret := _m.Called(_ca...) 927 | 928 | var r0 *secretsmanager.PutResourcePolicyOutput 929 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.PutResourcePolicyInput, ...request.Option) *secretsmanager.PutResourcePolicyOutput); ok { 930 | r0 = rf(_a0, _a1, _a2...) 931 | } else { 932 | if ret.Get(0) != nil { 933 | r0 = ret.Get(0).(*secretsmanager.PutResourcePolicyOutput) 934 | } 935 | } 936 | 937 | var r1 error 938 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.PutResourcePolicyInput, ...request.Option) error); ok { 939 | r1 = rf(_a0, _a1, _a2...) 940 | } else { 941 | r1 = ret.Error(1) 942 | } 943 | 944 | return r0, r1 945 | } 946 | 947 | // PutSecretValue provides a mock function with given fields: _a0 948 | func (_m *SecretsManagerAPI) PutSecretValue(_a0 *secretsmanager.PutSecretValueInput) (*secretsmanager.PutSecretValueOutput, error) { 949 | ret := _m.Called(_a0) 950 | 951 | var r0 *secretsmanager.PutSecretValueOutput 952 | if rf, ok := ret.Get(0).(func(*secretsmanager.PutSecretValueInput) *secretsmanager.PutSecretValueOutput); ok { 953 | r0 = rf(_a0) 954 | } else { 955 | if ret.Get(0) != nil { 956 | r0 = ret.Get(0).(*secretsmanager.PutSecretValueOutput) 957 | } 958 | } 959 | 960 | var r1 error 961 | if rf, ok := ret.Get(1).(func(*secretsmanager.PutSecretValueInput) error); ok { 962 | r1 = rf(_a0) 963 | } else { 964 | r1 = ret.Error(1) 965 | } 966 | 967 | return r0, r1 968 | } 969 | 970 | // PutSecretValueRequest provides a mock function with given fields: _a0 971 | func (_m *SecretsManagerAPI) PutSecretValueRequest(_a0 *secretsmanager.PutSecretValueInput) (*request.Request, *secretsmanager.PutSecretValueOutput) { 972 | ret := _m.Called(_a0) 973 | 974 | var r0 *request.Request 975 | if rf, ok := ret.Get(0).(func(*secretsmanager.PutSecretValueInput) *request.Request); ok { 976 | r0 = rf(_a0) 977 | } else { 978 | if ret.Get(0) != nil { 979 | r0 = ret.Get(0).(*request.Request) 980 | } 981 | } 982 | 983 | var r1 *secretsmanager.PutSecretValueOutput 984 | if rf, ok := ret.Get(1).(func(*secretsmanager.PutSecretValueInput) *secretsmanager.PutSecretValueOutput); ok { 985 | r1 = rf(_a0) 986 | } else { 987 | if ret.Get(1) != nil { 988 | r1 = ret.Get(1).(*secretsmanager.PutSecretValueOutput) 989 | } 990 | } 991 | 992 | return r0, r1 993 | } 994 | 995 | // PutSecretValueWithContext provides a mock function with given fields: _a0, _a1, _a2 996 | func (_m *SecretsManagerAPI) PutSecretValueWithContext(_a0 context.Context, _a1 *secretsmanager.PutSecretValueInput, _a2 ...request.Option) (*secretsmanager.PutSecretValueOutput, error) { 997 | _va := make([]interface{}, len(_a2)) 998 | for _i := range _a2 { 999 | _va[_i] = _a2[_i] 1000 | } 1001 | var _ca []interface{} 1002 | _ca = append(_ca, _a0, _a1) 1003 | _ca = append(_ca, _va...) 1004 | ret := _m.Called(_ca...) 1005 | 1006 | var r0 *secretsmanager.PutSecretValueOutput 1007 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.PutSecretValueInput, ...request.Option) *secretsmanager.PutSecretValueOutput); ok { 1008 | r0 = rf(_a0, _a1, _a2...) 1009 | } else { 1010 | if ret.Get(0) != nil { 1011 | r0 = ret.Get(0).(*secretsmanager.PutSecretValueOutput) 1012 | } 1013 | } 1014 | 1015 | var r1 error 1016 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.PutSecretValueInput, ...request.Option) error); ok { 1017 | r1 = rf(_a0, _a1, _a2...) 1018 | } else { 1019 | r1 = ret.Error(1) 1020 | } 1021 | 1022 | return r0, r1 1023 | } 1024 | 1025 | // RemoveRegionsFromReplication provides a mock function with given fields: _a0 1026 | func (_m *SecretsManagerAPI) RemoveRegionsFromReplication(_a0 *secretsmanager.RemoveRegionsFromReplicationInput) (*secretsmanager.RemoveRegionsFromReplicationOutput, error) { 1027 | ret := _m.Called(_a0) 1028 | 1029 | var r0 *secretsmanager.RemoveRegionsFromReplicationOutput 1030 | if rf, ok := ret.Get(0).(func(*secretsmanager.RemoveRegionsFromReplicationInput) *secretsmanager.RemoveRegionsFromReplicationOutput); ok { 1031 | r0 = rf(_a0) 1032 | } else { 1033 | if ret.Get(0) != nil { 1034 | r0 = ret.Get(0).(*secretsmanager.RemoveRegionsFromReplicationOutput) 1035 | } 1036 | } 1037 | 1038 | var r1 error 1039 | if rf, ok := ret.Get(1).(func(*secretsmanager.RemoveRegionsFromReplicationInput) error); ok { 1040 | r1 = rf(_a0) 1041 | } else { 1042 | r1 = ret.Error(1) 1043 | } 1044 | 1045 | return r0, r1 1046 | } 1047 | 1048 | // RemoveRegionsFromReplicationRequest provides a mock function with given fields: _a0 1049 | func (_m *SecretsManagerAPI) RemoveRegionsFromReplicationRequest(_a0 *secretsmanager.RemoveRegionsFromReplicationInput) (*request.Request, *secretsmanager.RemoveRegionsFromReplicationOutput) { 1050 | ret := _m.Called(_a0) 1051 | 1052 | var r0 *request.Request 1053 | if rf, ok := ret.Get(0).(func(*secretsmanager.RemoveRegionsFromReplicationInput) *request.Request); ok { 1054 | r0 = rf(_a0) 1055 | } else { 1056 | if ret.Get(0) != nil { 1057 | r0 = ret.Get(0).(*request.Request) 1058 | } 1059 | } 1060 | 1061 | var r1 *secretsmanager.RemoveRegionsFromReplicationOutput 1062 | if rf, ok := ret.Get(1).(func(*secretsmanager.RemoveRegionsFromReplicationInput) *secretsmanager.RemoveRegionsFromReplicationOutput); ok { 1063 | r1 = rf(_a0) 1064 | } else { 1065 | if ret.Get(1) != nil { 1066 | r1 = ret.Get(1).(*secretsmanager.RemoveRegionsFromReplicationOutput) 1067 | } 1068 | } 1069 | 1070 | return r0, r1 1071 | } 1072 | 1073 | // RemoveRegionsFromReplicationWithContext provides a mock function with given fields: _a0, _a1, _a2 1074 | func (_m *SecretsManagerAPI) RemoveRegionsFromReplicationWithContext(_a0 context.Context, _a1 *secretsmanager.RemoveRegionsFromReplicationInput, _a2 ...request.Option) (*secretsmanager.RemoveRegionsFromReplicationOutput, error) { 1075 | _va := make([]interface{}, len(_a2)) 1076 | for _i := range _a2 { 1077 | _va[_i] = _a2[_i] 1078 | } 1079 | var _ca []interface{} 1080 | _ca = append(_ca, _a0, _a1) 1081 | _ca = append(_ca, _va...) 1082 | ret := _m.Called(_ca...) 1083 | 1084 | var r0 *secretsmanager.RemoveRegionsFromReplicationOutput 1085 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.RemoveRegionsFromReplicationInput, ...request.Option) *secretsmanager.RemoveRegionsFromReplicationOutput); ok { 1086 | r0 = rf(_a0, _a1, _a2...) 1087 | } else { 1088 | if ret.Get(0) != nil { 1089 | r0 = ret.Get(0).(*secretsmanager.RemoveRegionsFromReplicationOutput) 1090 | } 1091 | } 1092 | 1093 | var r1 error 1094 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.RemoveRegionsFromReplicationInput, ...request.Option) error); ok { 1095 | r1 = rf(_a0, _a1, _a2...) 1096 | } else { 1097 | r1 = ret.Error(1) 1098 | } 1099 | 1100 | return r0, r1 1101 | } 1102 | 1103 | // ReplicateSecretToRegions provides a mock function with given fields: _a0 1104 | func (_m *SecretsManagerAPI) ReplicateSecretToRegions(_a0 *secretsmanager.ReplicateSecretToRegionsInput) (*secretsmanager.ReplicateSecretToRegionsOutput, error) { 1105 | ret := _m.Called(_a0) 1106 | 1107 | var r0 *secretsmanager.ReplicateSecretToRegionsOutput 1108 | if rf, ok := ret.Get(0).(func(*secretsmanager.ReplicateSecretToRegionsInput) *secretsmanager.ReplicateSecretToRegionsOutput); ok { 1109 | r0 = rf(_a0) 1110 | } else { 1111 | if ret.Get(0) != nil { 1112 | r0 = ret.Get(0).(*secretsmanager.ReplicateSecretToRegionsOutput) 1113 | } 1114 | } 1115 | 1116 | var r1 error 1117 | if rf, ok := ret.Get(1).(func(*secretsmanager.ReplicateSecretToRegionsInput) error); ok { 1118 | r1 = rf(_a0) 1119 | } else { 1120 | r1 = ret.Error(1) 1121 | } 1122 | 1123 | return r0, r1 1124 | } 1125 | 1126 | // ReplicateSecretToRegionsRequest provides a mock function with given fields: _a0 1127 | func (_m *SecretsManagerAPI) ReplicateSecretToRegionsRequest(_a0 *secretsmanager.ReplicateSecretToRegionsInput) (*request.Request, *secretsmanager.ReplicateSecretToRegionsOutput) { 1128 | ret := _m.Called(_a0) 1129 | 1130 | var r0 *request.Request 1131 | if rf, ok := ret.Get(0).(func(*secretsmanager.ReplicateSecretToRegionsInput) *request.Request); ok { 1132 | r0 = rf(_a0) 1133 | } else { 1134 | if ret.Get(0) != nil { 1135 | r0 = ret.Get(0).(*request.Request) 1136 | } 1137 | } 1138 | 1139 | var r1 *secretsmanager.ReplicateSecretToRegionsOutput 1140 | if rf, ok := ret.Get(1).(func(*secretsmanager.ReplicateSecretToRegionsInput) *secretsmanager.ReplicateSecretToRegionsOutput); ok { 1141 | r1 = rf(_a0) 1142 | } else { 1143 | if ret.Get(1) != nil { 1144 | r1 = ret.Get(1).(*secretsmanager.ReplicateSecretToRegionsOutput) 1145 | } 1146 | } 1147 | 1148 | return r0, r1 1149 | } 1150 | 1151 | // ReplicateSecretToRegionsWithContext provides a mock function with given fields: _a0, _a1, _a2 1152 | func (_m *SecretsManagerAPI) ReplicateSecretToRegionsWithContext(_a0 context.Context, _a1 *secretsmanager.ReplicateSecretToRegionsInput, _a2 ...request.Option) (*secretsmanager.ReplicateSecretToRegionsOutput, error) { 1153 | _va := make([]interface{}, len(_a2)) 1154 | for _i := range _a2 { 1155 | _va[_i] = _a2[_i] 1156 | } 1157 | var _ca []interface{} 1158 | _ca = append(_ca, _a0, _a1) 1159 | _ca = append(_ca, _va...) 1160 | ret := _m.Called(_ca...) 1161 | 1162 | var r0 *secretsmanager.ReplicateSecretToRegionsOutput 1163 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.ReplicateSecretToRegionsInput, ...request.Option) *secretsmanager.ReplicateSecretToRegionsOutput); ok { 1164 | r0 = rf(_a0, _a1, _a2...) 1165 | } else { 1166 | if ret.Get(0) != nil { 1167 | r0 = ret.Get(0).(*secretsmanager.ReplicateSecretToRegionsOutput) 1168 | } 1169 | } 1170 | 1171 | var r1 error 1172 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.ReplicateSecretToRegionsInput, ...request.Option) error); ok { 1173 | r1 = rf(_a0, _a1, _a2...) 1174 | } else { 1175 | r1 = ret.Error(1) 1176 | } 1177 | 1178 | return r0, r1 1179 | } 1180 | 1181 | // RestoreSecret provides a mock function with given fields: _a0 1182 | func (_m *SecretsManagerAPI) RestoreSecret(_a0 *secretsmanager.RestoreSecretInput) (*secretsmanager.RestoreSecretOutput, error) { 1183 | ret := _m.Called(_a0) 1184 | 1185 | var r0 *secretsmanager.RestoreSecretOutput 1186 | if rf, ok := ret.Get(0).(func(*secretsmanager.RestoreSecretInput) *secretsmanager.RestoreSecretOutput); ok { 1187 | r0 = rf(_a0) 1188 | } else { 1189 | if ret.Get(0) != nil { 1190 | r0 = ret.Get(0).(*secretsmanager.RestoreSecretOutput) 1191 | } 1192 | } 1193 | 1194 | var r1 error 1195 | if rf, ok := ret.Get(1).(func(*secretsmanager.RestoreSecretInput) error); ok { 1196 | r1 = rf(_a0) 1197 | } else { 1198 | r1 = ret.Error(1) 1199 | } 1200 | 1201 | return r0, r1 1202 | } 1203 | 1204 | // RestoreSecretRequest provides a mock function with given fields: _a0 1205 | func (_m *SecretsManagerAPI) RestoreSecretRequest(_a0 *secretsmanager.RestoreSecretInput) (*request.Request, *secretsmanager.RestoreSecretOutput) { 1206 | ret := _m.Called(_a0) 1207 | 1208 | var r0 *request.Request 1209 | if rf, ok := ret.Get(0).(func(*secretsmanager.RestoreSecretInput) *request.Request); ok { 1210 | r0 = rf(_a0) 1211 | } else { 1212 | if ret.Get(0) != nil { 1213 | r0 = ret.Get(0).(*request.Request) 1214 | } 1215 | } 1216 | 1217 | var r1 *secretsmanager.RestoreSecretOutput 1218 | if rf, ok := ret.Get(1).(func(*secretsmanager.RestoreSecretInput) *secretsmanager.RestoreSecretOutput); ok { 1219 | r1 = rf(_a0) 1220 | } else { 1221 | if ret.Get(1) != nil { 1222 | r1 = ret.Get(1).(*secretsmanager.RestoreSecretOutput) 1223 | } 1224 | } 1225 | 1226 | return r0, r1 1227 | } 1228 | 1229 | // RestoreSecretWithContext provides a mock function with given fields: _a0, _a1, _a2 1230 | func (_m *SecretsManagerAPI) RestoreSecretWithContext(_a0 context.Context, _a1 *secretsmanager.RestoreSecretInput, _a2 ...request.Option) (*secretsmanager.RestoreSecretOutput, error) { 1231 | _va := make([]interface{}, len(_a2)) 1232 | for _i := range _a2 { 1233 | _va[_i] = _a2[_i] 1234 | } 1235 | var _ca []interface{} 1236 | _ca = append(_ca, _a0, _a1) 1237 | _ca = append(_ca, _va...) 1238 | ret := _m.Called(_ca...) 1239 | 1240 | var r0 *secretsmanager.RestoreSecretOutput 1241 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.RestoreSecretInput, ...request.Option) *secretsmanager.RestoreSecretOutput); ok { 1242 | r0 = rf(_a0, _a1, _a2...) 1243 | } else { 1244 | if ret.Get(0) != nil { 1245 | r0 = ret.Get(0).(*secretsmanager.RestoreSecretOutput) 1246 | } 1247 | } 1248 | 1249 | var r1 error 1250 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.RestoreSecretInput, ...request.Option) error); ok { 1251 | r1 = rf(_a0, _a1, _a2...) 1252 | } else { 1253 | r1 = ret.Error(1) 1254 | } 1255 | 1256 | return r0, r1 1257 | } 1258 | 1259 | // RotateSecret provides a mock function with given fields: _a0 1260 | func (_m *SecretsManagerAPI) RotateSecret(_a0 *secretsmanager.RotateSecretInput) (*secretsmanager.RotateSecretOutput, error) { 1261 | ret := _m.Called(_a0) 1262 | 1263 | var r0 *secretsmanager.RotateSecretOutput 1264 | if rf, ok := ret.Get(0).(func(*secretsmanager.RotateSecretInput) *secretsmanager.RotateSecretOutput); ok { 1265 | r0 = rf(_a0) 1266 | } else { 1267 | if ret.Get(0) != nil { 1268 | r0 = ret.Get(0).(*secretsmanager.RotateSecretOutput) 1269 | } 1270 | } 1271 | 1272 | var r1 error 1273 | if rf, ok := ret.Get(1).(func(*secretsmanager.RotateSecretInput) error); ok { 1274 | r1 = rf(_a0) 1275 | } else { 1276 | r1 = ret.Error(1) 1277 | } 1278 | 1279 | return r0, r1 1280 | } 1281 | 1282 | // RotateSecretRequest provides a mock function with given fields: _a0 1283 | func (_m *SecretsManagerAPI) RotateSecretRequest(_a0 *secretsmanager.RotateSecretInput) (*request.Request, *secretsmanager.RotateSecretOutput) { 1284 | ret := _m.Called(_a0) 1285 | 1286 | var r0 *request.Request 1287 | if rf, ok := ret.Get(0).(func(*secretsmanager.RotateSecretInput) *request.Request); ok { 1288 | r0 = rf(_a0) 1289 | } else { 1290 | if ret.Get(0) != nil { 1291 | r0 = ret.Get(0).(*request.Request) 1292 | } 1293 | } 1294 | 1295 | var r1 *secretsmanager.RotateSecretOutput 1296 | if rf, ok := ret.Get(1).(func(*secretsmanager.RotateSecretInput) *secretsmanager.RotateSecretOutput); ok { 1297 | r1 = rf(_a0) 1298 | } else { 1299 | if ret.Get(1) != nil { 1300 | r1 = ret.Get(1).(*secretsmanager.RotateSecretOutput) 1301 | } 1302 | } 1303 | 1304 | return r0, r1 1305 | } 1306 | 1307 | // RotateSecretWithContext provides a mock function with given fields: _a0, _a1, _a2 1308 | func (_m *SecretsManagerAPI) RotateSecretWithContext(_a0 context.Context, _a1 *secretsmanager.RotateSecretInput, _a2 ...request.Option) (*secretsmanager.RotateSecretOutput, error) { 1309 | _va := make([]interface{}, len(_a2)) 1310 | for _i := range _a2 { 1311 | _va[_i] = _a2[_i] 1312 | } 1313 | var _ca []interface{} 1314 | _ca = append(_ca, _a0, _a1) 1315 | _ca = append(_ca, _va...) 1316 | ret := _m.Called(_ca...) 1317 | 1318 | var r0 *secretsmanager.RotateSecretOutput 1319 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.RotateSecretInput, ...request.Option) *secretsmanager.RotateSecretOutput); ok { 1320 | r0 = rf(_a0, _a1, _a2...) 1321 | } else { 1322 | if ret.Get(0) != nil { 1323 | r0 = ret.Get(0).(*secretsmanager.RotateSecretOutput) 1324 | } 1325 | } 1326 | 1327 | var r1 error 1328 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.RotateSecretInput, ...request.Option) error); ok { 1329 | r1 = rf(_a0, _a1, _a2...) 1330 | } else { 1331 | r1 = ret.Error(1) 1332 | } 1333 | 1334 | return r0, r1 1335 | } 1336 | 1337 | // StopReplicationToReplica provides a mock function with given fields: _a0 1338 | func (_m *SecretsManagerAPI) StopReplicationToReplica(_a0 *secretsmanager.StopReplicationToReplicaInput) (*secretsmanager.StopReplicationToReplicaOutput, error) { 1339 | ret := _m.Called(_a0) 1340 | 1341 | var r0 *secretsmanager.StopReplicationToReplicaOutput 1342 | if rf, ok := ret.Get(0).(func(*secretsmanager.StopReplicationToReplicaInput) *secretsmanager.StopReplicationToReplicaOutput); ok { 1343 | r0 = rf(_a0) 1344 | } else { 1345 | if ret.Get(0) != nil { 1346 | r0 = ret.Get(0).(*secretsmanager.StopReplicationToReplicaOutput) 1347 | } 1348 | } 1349 | 1350 | var r1 error 1351 | if rf, ok := ret.Get(1).(func(*secretsmanager.StopReplicationToReplicaInput) error); ok { 1352 | r1 = rf(_a0) 1353 | } else { 1354 | r1 = ret.Error(1) 1355 | } 1356 | 1357 | return r0, r1 1358 | } 1359 | 1360 | // StopReplicationToReplicaRequest provides a mock function with given fields: _a0 1361 | func (_m *SecretsManagerAPI) StopReplicationToReplicaRequest(_a0 *secretsmanager.StopReplicationToReplicaInput) (*request.Request, *secretsmanager.StopReplicationToReplicaOutput) { 1362 | ret := _m.Called(_a0) 1363 | 1364 | var r0 *request.Request 1365 | if rf, ok := ret.Get(0).(func(*secretsmanager.StopReplicationToReplicaInput) *request.Request); ok { 1366 | r0 = rf(_a0) 1367 | } else { 1368 | if ret.Get(0) != nil { 1369 | r0 = ret.Get(0).(*request.Request) 1370 | } 1371 | } 1372 | 1373 | var r1 *secretsmanager.StopReplicationToReplicaOutput 1374 | if rf, ok := ret.Get(1).(func(*secretsmanager.StopReplicationToReplicaInput) *secretsmanager.StopReplicationToReplicaOutput); ok { 1375 | r1 = rf(_a0) 1376 | } else { 1377 | if ret.Get(1) != nil { 1378 | r1 = ret.Get(1).(*secretsmanager.StopReplicationToReplicaOutput) 1379 | } 1380 | } 1381 | 1382 | return r0, r1 1383 | } 1384 | 1385 | // StopReplicationToReplicaWithContext provides a mock function with given fields: _a0, _a1, _a2 1386 | func (_m *SecretsManagerAPI) StopReplicationToReplicaWithContext(_a0 context.Context, _a1 *secretsmanager.StopReplicationToReplicaInput, _a2 ...request.Option) (*secretsmanager.StopReplicationToReplicaOutput, error) { 1387 | _va := make([]interface{}, len(_a2)) 1388 | for _i := range _a2 { 1389 | _va[_i] = _a2[_i] 1390 | } 1391 | var _ca []interface{} 1392 | _ca = append(_ca, _a0, _a1) 1393 | _ca = append(_ca, _va...) 1394 | ret := _m.Called(_ca...) 1395 | 1396 | var r0 *secretsmanager.StopReplicationToReplicaOutput 1397 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.StopReplicationToReplicaInput, ...request.Option) *secretsmanager.StopReplicationToReplicaOutput); ok { 1398 | r0 = rf(_a0, _a1, _a2...) 1399 | } else { 1400 | if ret.Get(0) != nil { 1401 | r0 = ret.Get(0).(*secretsmanager.StopReplicationToReplicaOutput) 1402 | } 1403 | } 1404 | 1405 | var r1 error 1406 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.StopReplicationToReplicaInput, ...request.Option) error); ok { 1407 | r1 = rf(_a0, _a1, _a2...) 1408 | } else { 1409 | r1 = ret.Error(1) 1410 | } 1411 | 1412 | return r0, r1 1413 | } 1414 | 1415 | // TagResource provides a mock function with given fields: _a0 1416 | func (_m *SecretsManagerAPI) TagResource(_a0 *secretsmanager.TagResourceInput) (*secretsmanager.TagResourceOutput, error) { 1417 | ret := _m.Called(_a0) 1418 | 1419 | var r0 *secretsmanager.TagResourceOutput 1420 | if rf, ok := ret.Get(0).(func(*secretsmanager.TagResourceInput) *secretsmanager.TagResourceOutput); ok { 1421 | r0 = rf(_a0) 1422 | } else { 1423 | if ret.Get(0) != nil { 1424 | r0 = ret.Get(0).(*secretsmanager.TagResourceOutput) 1425 | } 1426 | } 1427 | 1428 | var r1 error 1429 | if rf, ok := ret.Get(1).(func(*secretsmanager.TagResourceInput) error); ok { 1430 | r1 = rf(_a0) 1431 | } else { 1432 | r1 = ret.Error(1) 1433 | } 1434 | 1435 | return r0, r1 1436 | } 1437 | 1438 | // TagResourceRequest provides a mock function with given fields: _a0 1439 | func (_m *SecretsManagerAPI) TagResourceRequest(_a0 *secretsmanager.TagResourceInput) (*request.Request, *secretsmanager.TagResourceOutput) { 1440 | ret := _m.Called(_a0) 1441 | 1442 | var r0 *request.Request 1443 | if rf, ok := ret.Get(0).(func(*secretsmanager.TagResourceInput) *request.Request); ok { 1444 | r0 = rf(_a0) 1445 | } else { 1446 | if ret.Get(0) != nil { 1447 | r0 = ret.Get(0).(*request.Request) 1448 | } 1449 | } 1450 | 1451 | var r1 *secretsmanager.TagResourceOutput 1452 | if rf, ok := ret.Get(1).(func(*secretsmanager.TagResourceInput) *secretsmanager.TagResourceOutput); ok { 1453 | r1 = rf(_a0) 1454 | } else { 1455 | if ret.Get(1) != nil { 1456 | r1 = ret.Get(1).(*secretsmanager.TagResourceOutput) 1457 | } 1458 | } 1459 | 1460 | return r0, r1 1461 | } 1462 | 1463 | // TagResourceWithContext provides a mock function with given fields: _a0, _a1, _a2 1464 | func (_m *SecretsManagerAPI) TagResourceWithContext(_a0 context.Context, _a1 *secretsmanager.TagResourceInput, _a2 ...request.Option) (*secretsmanager.TagResourceOutput, error) { 1465 | _va := make([]interface{}, len(_a2)) 1466 | for _i := range _a2 { 1467 | _va[_i] = _a2[_i] 1468 | } 1469 | var _ca []interface{} 1470 | _ca = append(_ca, _a0, _a1) 1471 | _ca = append(_ca, _va...) 1472 | ret := _m.Called(_ca...) 1473 | 1474 | var r0 *secretsmanager.TagResourceOutput 1475 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.TagResourceInput, ...request.Option) *secretsmanager.TagResourceOutput); ok { 1476 | r0 = rf(_a0, _a1, _a2...) 1477 | } else { 1478 | if ret.Get(0) != nil { 1479 | r0 = ret.Get(0).(*secretsmanager.TagResourceOutput) 1480 | } 1481 | } 1482 | 1483 | var r1 error 1484 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.TagResourceInput, ...request.Option) error); ok { 1485 | r1 = rf(_a0, _a1, _a2...) 1486 | } else { 1487 | r1 = ret.Error(1) 1488 | } 1489 | 1490 | return r0, r1 1491 | } 1492 | 1493 | // UntagResource provides a mock function with given fields: _a0 1494 | func (_m *SecretsManagerAPI) UntagResource(_a0 *secretsmanager.UntagResourceInput) (*secretsmanager.UntagResourceOutput, error) { 1495 | ret := _m.Called(_a0) 1496 | 1497 | var r0 *secretsmanager.UntagResourceOutput 1498 | if rf, ok := ret.Get(0).(func(*secretsmanager.UntagResourceInput) *secretsmanager.UntagResourceOutput); ok { 1499 | r0 = rf(_a0) 1500 | } else { 1501 | if ret.Get(0) != nil { 1502 | r0 = ret.Get(0).(*secretsmanager.UntagResourceOutput) 1503 | } 1504 | } 1505 | 1506 | var r1 error 1507 | if rf, ok := ret.Get(1).(func(*secretsmanager.UntagResourceInput) error); ok { 1508 | r1 = rf(_a0) 1509 | } else { 1510 | r1 = ret.Error(1) 1511 | } 1512 | 1513 | return r0, r1 1514 | } 1515 | 1516 | // UntagResourceRequest provides a mock function with given fields: _a0 1517 | func (_m *SecretsManagerAPI) UntagResourceRequest(_a0 *secretsmanager.UntagResourceInput) (*request.Request, *secretsmanager.UntagResourceOutput) { 1518 | ret := _m.Called(_a0) 1519 | 1520 | var r0 *request.Request 1521 | if rf, ok := ret.Get(0).(func(*secretsmanager.UntagResourceInput) *request.Request); ok { 1522 | r0 = rf(_a0) 1523 | } else { 1524 | if ret.Get(0) != nil { 1525 | r0 = ret.Get(0).(*request.Request) 1526 | } 1527 | } 1528 | 1529 | var r1 *secretsmanager.UntagResourceOutput 1530 | if rf, ok := ret.Get(1).(func(*secretsmanager.UntagResourceInput) *secretsmanager.UntagResourceOutput); ok { 1531 | r1 = rf(_a0) 1532 | } else { 1533 | if ret.Get(1) != nil { 1534 | r1 = ret.Get(1).(*secretsmanager.UntagResourceOutput) 1535 | } 1536 | } 1537 | 1538 | return r0, r1 1539 | } 1540 | 1541 | // UntagResourceWithContext provides a mock function with given fields: _a0, _a1, _a2 1542 | func (_m *SecretsManagerAPI) UntagResourceWithContext(_a0 context.Context, _a1 *secretsmanager.UntagResourceInput, _a2 ...request.Option) (*secretsmanager.UntagResourceOutput, error) { 1543 | _va := make([]interface{}, len(_a2)) 1544 | for _i := range _a2 { 1545 | _va[_i] = _a2[_i] 1546 | } 1547 | var _ca []interface{} 1548 | _ca = append(_ca, _a0, _a1) 1549 | _ca = append(_ca, _va...) 1550 | ret := _m.Called(_ca...) 1551 | 1552 | var r0 *secretsmanager.UntagResourceOutput 1553 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.UntagResourceInput, ...request.Option) *secretsmanager.UntagResourceOutput); ok { 1554 | r0 = rf(_a0, _a1, _a2...) 1555 | } else { 1556 | if ret.Get(0) != nil { 1557 | r0 = ret.Get(0).(*secretsmanager.UntagResourceOutput) 1558 | } 1559 | } 1560 | 1561 | var r1 error 1562 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.UntagResourceInput, ...request.Option) error); ok { 1563 | r1 = rf(_a0, _a1, _a2...) 1564 | } else { 1565 | r1 = ret.Error(1) 1566 | } 1567 | 1568 | return r0, r1 1569 | } 1570 | 1571 | // UpdateSecret provides a mock function with given fields: _a0 1572 | func (_m *SecretsManagerAPI) UpdateSecret(_a0 *secretsmanager.UpdateSecretInput) (*secretsmanager.UpdateSecretOutput, error) { 1573 | ret := _m.Called(_a0) 1574 | 1575 | var r0 *secretsmanager.UpdateSecretOutput 1576 | if rf, ok := ret.Get(0).(func(*secretsmanager.UpdateSecretInput) *secretsmanager.UpdateSecretOutput); ok { 1577 | r0 = rf(_a0) 1578 | } else { 1579 | if ret.Get(0) != nil { 1580 | r0 = ret.Get(0).(*secretsmanager.UpdateSecretOutput) 1581 | } 1582 | } 1583 | 1584 | var r1 error 1585 | if rf, ok := ret.Get(1).(func(*secretsmanager.UpdateSecretInput) error); ok { 1586 | r1 = rf(_a0) 1587 | } else { 1588 | r1 = ret.Error(1) 1589 | } 1590 | 1591 | return r0, r1 1592 | } 1593 | 1594 | // UpdateSecretRequest provides a mock function with given fields: _a0 1595 | func (_m *SecretsManagerAPI) UpdateSecretRequest(_a0 *secretsmanager.UpdateSecretInput) (*request.Request, *secretsmanager.UpdateSecretOutput) { 1596 | ret := _m.Called(_a0) 1597 | 1598 | var r0 *request.Request 1599 | if rf, ok := ret.Get(0).(func(*secretsmanager.UpdateSecretInput) *request.Request); ok { 1600 | r0 = rf(_a0) 1601 | } else { 1602 | if ret.Get(0) != nil { 1603 | r0 = ret.Get(0).(*request.Request) 1604 | } 1605 | } 1606 | 1607 | var r1 *secretsmanager.UpdateSecretOutput 1608 | if rf, ok := ret.Get(1).(func(*secretsmanager.UpdateSecretInput) *secretsmanager.UpdateSecretOutput); ok { 1609 | r1 = rf(_a0) 1610 | } else { 1611 | if ret.Get(1) != nil { 1612 | r1 = ret.Get(1).(*secretsmanager.UpdateSecretOutput) 1613 | } 1614 | } 1615 | 1616 | return r0, r1 1617 | } 1618 | 1619 | // UpdateSecretVersionStage provides a mock function with given fields: _a0 1620 | func (_m *SecretsManagerAPI) UpdateSecretVersionStage(_a0 *secretsmanager.UpdateSecretVersionStageInput) (*secretsmanager.UpdateSecretVersionStageOutput, error) { 1621 | ret := _m.Called(_a0) 1622 | 1623 | var r0 *secretsmanager.UpdateSecretVersionStageOutput 1624 | if rf, ok := ret.Get(0).(func(*secretsmanager.UpdateSecretVersionStageInput) *secretsmanager.UpdateSecretVersionStageOutput); ok { 1625 | r0 = rf(_a0) 1626 | } else { 1627 | if ret.Get(0) != nil { 1628 | r0 = ret.Get(0).(*secretsmanager.UpdateSecretVersionStageOutput) 1629 | } 1630 | } 1631 | 1632 | var r1 error 1633 | if rf, ok := ret.Get(1).(func(*secretsmanager.UpdateSecretVersionStageInput) error); ok { 1634 | r1 = rf(_a0) 1635 | } else { 1636 | r1 = ret.Error(1) 1637 | } 1638 | 1639 | return r0, r1 1640 | } 1641 | 1642 | // UpdateSecretVersionStageRequest provides a mock function with given fields: _a0 1643 | func (_m *SecretsManagerAPI) UpdateSecretVersionStageRequest(_a0 *secretsmanager.UpdateSecretVersionStageInput) (*request.Request, *secretsmanager.UpdateSecretVersionStageOutput) { 1644 | ret := _m.Called(_a0) 1645 | 1646 | var r0 *request.Request 1647 | if rf, ok := ret.Get(0).(func(*secretsmanager.UpdateSecretVersionStageInput) *request.Request); ok { 1648 | r0 = rf(_a0) 1649 | } else { 1650 | if ret.Get(0) != nil { 1651 | r0 = ret.Get(0).(*request.Request) 1652 | } 1653 | } 1654 | 1655 | var r1 *secretsmanager.UpdateSecretVersionStageOutput 1656 | if rf, ok := ret.Get(1).(func(*secretsmanager.UpdateSecretVersionStageInput) *secretsmanager.UpdateSecretVersionStageOutput); ok { 1657 | r1 = rf(_a0) 1658 | } else { 1659 | if ret.Get(1) != nil { 1660 | r1 = ret.Get(1).(*secretsmanager.UpdateSecretVersionStageOutput) 1661 | } 1662 | } 1663 | 1664 | return r0, r1 1665 | } 1666 | 1667 | // UpdateSecretVersionStageWithContext provides a mock function with given fields: _a0, _a1, _a2 1668 | func (_m *SecretsManagerAPI) UpdateSecretVersionStageWithContext(_a0 context.Context, _a1 *secretsmanager.UpdateSecretVersionStageInput, _a2 ...request.Option) (*secretsmanager.UpdateSecretVersionStageOutput, error) { 1669 | _va := make([]interface{}, len(_a2)) 1670 | for _i := range _a2 { 1671 | _va[_i] = _a2[_i] 1672 | } 1673 | var _ca []interface{} 1674 | _ca = append(_ca, _a0, _a1) 1675 | _ca = append(_ca, _va...) 1676 | ret := _m.Called(_ca...) 1677 | 1678 | var r0 *secretsmanager.UpdateSecretVersionStageOutput 1679 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.UpdateSecretVersionStageInput, ...request.Option) *secretsmanager.UpdateSecretVersionStageOutput); ok { 1680 | r0 = rf(_a0, _a1, _a2...) 1681 | } else { 1682 | if ret.Get(0) != nil { 1683 | r0 = ret.Get(0).(*secretsmanager.UpdateSecretVersionStageOutput) 1684 | } 1685 | } 1686 | 1687 | var r1 error 1688 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.UpdateSecretVersionStageInput, ...request.Option) error); ok { 1689 | r1 = rf(_a0, _a1, _a2...) 1690 | } else { 1691 | r1 = ret.Error(1) 1692 | } 1693 | 1694 | return r0, r1 1695 | } 1696 | 1697 | // UpdateSecretWithContext provides a mock function with given fields: _a0, _a1, _a2 1698 | func (_m *SecretsManagerAPI) UpdateSecretWithContext(_a0 context.Context, _a1 *secretsmanager.UpdateSecretInput, _a2 ...request.Option) (*secretsmanager.UpdateSecretOutput, error) { 1699 | _va := make([]interface{}, len(_a2)) 1700 | for _i := range _a2 { 1701 | _va[_i] = _a2[_i] 1702 | } 1703 | var _ca []interface{} 1704 | _ca = append(_ca, _a0, _a1) 1705 | _ca = append(_ca, _va...) 1706 | ret := _m.Called(_ca...) 1707 | 1708 | var r0 *secretsmanager.UpdateSecretOutput 1709 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.UpdateSecretInput, ...request.Option) *secretsmanager.UpdateSecretOutput); ok { 1710 | r0 = rf(_a0, _a1, _a2...) 1711 | } else { 1712 | if ret.Get(0) != nil { 1713 | r0 = ret.Get(0).(*secretsmanager.UpdateSecretOutput) 1714 | } 1715 | } 1716 | 1717 | var r1 error 1718 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.UpdateSecretInput, ...request.Option) error); ok { 1719 | r1 = rf(_a0, _a1, _a2...) 1720 | } else { 1721 | r1 = ret.Error(1) 1722 | } 1723 | 1724 | return r0, r1 1725 | } 1726 | 1727 | // ValidateResourcePolicy provides a mock function with given fields: _a0 1728 | func (_m *SecretsManagerAPI) ValidateResourcePolicy(_a0 *secretsmanager.ValidateResourcePolicyInput) (*secretsmanager.ValidateResourcePolicyOutput, error) { 1729 | ret := _m.Called(_a0) 1730 | 1731 | var r0 *secretsmanager.ValidateResourcePolicyOutput 1732 | if rf, ok := ret.Get(0).(func(*secretsmanager.ValidateResourcePolicyInput) *secretsmanager.ValidateResourcePolicyOutput); ok { 1733 | r0 = rf(_a0) 1734 | } else { 1735 | if ret.Get(0) != nil { 1736 | r0 = ret.Get(0).(*secretsmanager.ValidateResourcePolicyOutput) 1737 | } 1738 | } 1739 | 1740 | var r1 error 1741 | if rf, ok := ret.Get(1).(func(*secretsmanager.ValidateResourcePolicyInput) error); ok { 1742 | r1 = rf(_a0) 1743 | } else { 1744 | r1 = ret.Error(1) 1745 | } 1746 | 1747 | return r0, r1 1748 | } 1749 | 1750 | // ValidateResourcePolicyRequest provides a mock function with given fields: _a0 1751 | func (_m *SecretsManagerAPI) ValidateResourcePolicyRequest(_a0 *secretsmanager.ValidateResourcePolicyInput) (*request.Request, *secretsmanager.ValidateResourcePolicyOutput) { 1752 | ret := _m.Called(_a0) 1753 | 1754 | var r0 *request.Request 1755 | if rf, ok := ret.Get(0).(func(*secretsmanager.ValidateResourcePolicyInput) *request.Request); ok { 1756 | r0 = rf(_a0) 1757 | } else { 1758 | if ret.Get(0) != nil { 1759 | r0 = ret.Get(0).(*request.Request) 1760 | } 1761 | } 1762 | 1763 | var r1 *secretsmanager.ValidateResourcePolicyOutput 1764 | if rf, ok := ret.Get(1).(func(*secretsmanager.ValidateResourcePolicyInput) *secretsmanager.ValidateResourcePolicyOutput); ok { 1765 | r1 = rf(_a0) 1766 | } else { 1767 | if ret.Get(1) != nil { 1768 | r1 = ret.Get(1).(*secretsmanager.ValidateResourcePolicyOutput) 1769 | } 1770 | } 1771 | 1772 | return r0, r1 1773 | } 1774 | 1775 | // ValidateResourcePolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 1776 | func (_m *SecretsManagerAPI) ValidateResourcePolicyWithContext(_a0 context.Context, _a1 *secretsmanager.ValidateResourcePolicyInput, _a2 ...request.Option) (*secretsmanager.ValidateResourcePolicyOutput, error) { 1777 | _va := make([]interface{}, len(_a2)) 1778 | for _i := range _a2 { 1779 | _va[_i] = _a2[_i] 1780 | } 1781 | var _ca []interface{} 1782 | _ca = append(_ca, _a0, _a1) 1783 | _ca = append(_ca, _va...) 1784 | ret := _m.Called(_ca...) 1785 | 1786 | var r0 *secretsmanager.ValidateResourcePolicyOutput 1787 | if rf, ok := ret.Get(0).(func(context.Context, *secretsmanager.ValidateResourcePolicyInput, ...request.Option) *secretsmanager.ValidateResourcePolicyOutput); ok { 1788 | r0 = rf(_a0, _a1, _a2...) 1789 | } else { 1790 | if ret.Get(0) != nil { 1791 | r0 = ret.Get(0).(*secretsmanager.ValidateResourcePolicyOutput) 1792 | } 1793 | } 1794 | 1795 | var r1 error 1796 | if rf, ok := ret.Get(1).(func(context.Context, *secretsmanager.ValidateResourcePolicyInput, ...request.Option) error); ok { 1797 | r1 = rf(_a0, _a1, _a2...) 1798 | } else { 1799 | r1 = ret.Error(1) 1800 | } 1801 | 1802 | return r0, r1 1803 | } 1804 | 1805 | type mockConstructorTestingTNewSecretsManagerAPI interface { 1806 | mock.TestingT 1807 | Cleanup(func()) 1808 | } 1809 | 1810 | // NewSecretsManagerAPI creates a new instance of SecretsManagerAPI. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 1811 | func NewSecretsManagerAPI(t mockConstructorTestingTNewSecretsManagerAPI) *SecretsManagerAPI { 1812 | mock := &SecretsManagerAPI{} 1813 | mock.Mock.Test(t) 1814 | 1815 | t.Cleanup(func() { mock.AssertExpectations(t) }) 1816 | 1817 | return mock 1818 | } 1819 | -------------------------------------------------------------------------------- /pkg/secrets/aws/secrets.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "sort" 7 | "strings" 8 | 9 | "secrets-init/pkg/secrets" //nolint:gci 10 | 11 | "github.com/aws/aws-sdk-go/aws/session" 12 | "github.com/aws/aws-sdk-go/service/secretsmanager" 13 | "github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface" 14 | "github.com/aws/aws-sdk-go/service/ssm" 15 | "github.com/aws/aws-sdk-go/service/ssm/ssmiface" 16 | "github.com/pkg/errors" //nolint:gci 17 | ) 18 | 19 | const ( 20 | paramNameTokens = 6 21 | paramNameTokensWithVersion = 7 22 | ) 23 | 24 | // SecretsProvider AWS secrets provider 25 | type SecretsProvider struct { 26 | session *session.Session 27 | sm secretsmanageriface.SecretsManagerAPI 28 | ssm ssmiface.SSMAPI 29 | } 30 | 31 | // NewAwsSecretsProvider init AWS Secrets Provider 32 | func NewAwsSecretsProvider() (secrets.Provider, error) { 33 | var err error 34 | sp := SecretsProvider{} 35 | // create AWS session 36 | sp.session, err = session.NewSessionWithOptions(session.Options{SharedConfigState: session.SharedConfigEnable}) 37 | if err != nil { 38 | return nil, errors.Wrap(err, "failed to create AWS session") 39 | } 40 | // init AWS Secrets Manager client 41 | sp.sm = secretsmanager.New(sp.session) 42 | // init AWS SSM client 43 | sp.ssm = ssm.New(sp.session) 44 | return &sp, nil 45 | } 46 | 47 | // ResolveSecrets replaces all passed variables values prefixed with 'aws:aws:secretsmanager' and 'arn:aws:ssm:REGION:ACCOUNT:parameter' 48 | // by corresponding secrets from AWS Secret Manager and AWS Parameter Store 49 | func (sp *SecretsProvider) ResolveSecrets(_ context.Context, vars []string) ([]string, error) { 50 | envs := make([]string, 0, len(vars)) 51 | 52 | for _, env := range vars { 53 | kv := strings.Split(env, "=") 54 | key, value := kv[0], kv[1] 55 | if strings.HasPrefix(value, "arn:aws:secretsmanager") || strings.HasPrefix(value, "arn:aws-cn:secretsmanager") { 56 | // get secret value 57 | secret, err := sp.sm.GetSecretValue(&secretsmanager.GetSecretValueInput{SecretId: &value}) 58 | if err != nil { 59 | return vars, errors.Wrap(err, "failed to get secret from AWS Secrets Manager") 60 | } 61 | if IsJSON(secret.SecretString) { 62 | var keyValueSecret map[string]string 63 | err = json.Unmarshal([]byte(*secret.SecretString), &keyValueSecret) 64 | if err != nil { 65 | return vars, errors.Wrap(err, "failed to decode key/value secret") 66 | } 67 | for key, value := range keyValueSecret { 68 | e := key + "=" + value 69 | envs = append(envs, e) 70 | } 71 | continue // We continue to not add this ENV variable but only the environment variables that exists in the JSON 72 | } 73 | env = key + "=" + *secret.SecretString 74 | } else if (strings.HasPrefix(value, "arn:aws:ssm") || strings.HasPrefix(value, "arn:aws-cn:ssm")) && strings.Contains(value, ":parameter/") { 75 | tokens := strings.Split(value, ":") 76 | // valid parameter ARN arn:aws:ssm:REGION:ACCOUNT:parameter/PATH 77 | // or arn:aws:ssm:REGION:ACCOUNT:parameter/PATH:VERSION 78 | if len(tokens) == paramNameTokens || len(tokens) == paramNameTokensWithVersion { 79 | // get SSM parameter name (path) 80 | paramName := strings.TrimPrefix(tokens[5], "parameter") 81 | 82 | if len(tokens) == paramNameTokensWithVersion { 83 | paramName = paramName + ":" + tokens[6] 84 | } 85 | 86 | // get AWS SSM API 87 | withDecryption := true 88 | param, err := sp.ssm.GetParameter(&ssm.GetParameterInput{ 89 | Name: ¶mName, 90 | WithDecryption: &withDecryption, 91 | }) 92 | if err != nil { 93 | return vars, errors.Wrap(err, "failed to get secret from AWS Parameters Store") 94 | } 95 | env = key + "=" + *param.Parameter.Value 96 | } 97 | } 98 | envs = append(envs, env) 99 | } 100 | sort.Strings(envs) 101 | return envs, nil 102 | } 103 | 104 | func IsJSON(str *string) bool { 105 | if str == nil { 106 | return false 107 | } 108 | var js json.RawMessage 109 | return json.Unmarshal([]byte(*str), &js) == nil 110 | } 111 | -------------------------------------------------------------------------------- /pkg/secrets/aws/secrets_test.go: -------------------------------------------------------------------------------- 1 | // nolint 2 | package aws 3 | 4 | import ( 5 | "context" 6 | "errors" 7 | "reflect" 8 | "testing" 9 | 10 | "secrets-init/mocks" 11 | "secrets-init/pkg/secrets" 12 | 13 | "github.com/aws/aws-sdk-go/service/secretsmanager" 14 | "github.com/aws/aws-sdk-go/service/ssm" 15 | ) 16 | 17 | func TestSecretsProvider_ResolveSecrets(t *testing.T) { 18 | tests := []struct { 19 | name string 20 | vars []string 21 | mockServiceProvider func(*mocks.SecretsManagerAPI, *mocks.SSMAPI) secrets.Provider 22 | want []string 23 | wantErr bool 24 | }{ 25 | { 26 | name: "get single secret from Secrets Manager", 27 | vars: []string{ 28 | "test-secret=arn:aws:secretsmanager:12345678", 29 | }, 30 | want: []string{ 31 | "test-secret=test-secret-value", 32 | }, 33 | mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider { 34 | sp := SecretsProvider{sm: mockSM, ssm: mockSSM} 35 | secretName := "arn:aws:secretsmanager:12345678" 36 | secretValue := "test-secret-value" 37 | valueInput := secretsmanager.GetSecretValueInput{SecretId: &secretName} 38 | valueOutput := secretsmanager.GetSecretValueOutput{SecretString: &secretValue} 39 | mockSM.On("GetSecretValue", &valueInput).Return(&valueOutput, nil) 40 | return &sp 41 | }, 42 | }, 43 | { 44 | name: "get 2 secrets from Secrets Manager", 45 | vars: []string{ 46 | "test-secret-1=arn:aws:secretsmanager:12345678", 47 | "non-secret=hello", 48 | "test-secret-2=arn:aws:secretsmanager:87654321", 49 | }, 50 | want: []string{ 51 | "non-secret=hello", 52 | "test-secret-1=test-secret-value-1", 53 | "test-secret-2=test-secret-value-2", 54 | }, 55 | mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider { 56 | sp := SecretsProvider{sm: mockSM, ssm: mockSSM} 57 | vars := map[string]string{ 58 | "arn:aws:secretsmanager:12345678": "test-secret-value-1", 59 | "arn:aws:secretsmanager:87654321": "test-secret-value-2", 60 | } 61 | for n, v := range vars { 62 | name := n 63 | value := v 64 | valueInput := secretsmanager.GetSecretValueInput{SecretId: &name} 65 | valueOutput := secretsmanager.GetSecretValueOutput{SecretString: &value} 66 | mockSM.On("GetSecretValue", &valueInput).Return(&valueOutput, nil) 67 | } 68 | return &sp 69 | }, 70 | }, 71 | { 72 | name: "get all secrets from from Secrets Manager json", 73 | vars: []string{ 74 | "test-secret-1=arn:aws:secretsmanager:12345678-json", 75 | }, 76 | want: []string{ 77 | "TEST_1=test-secret-value-1", 78 | "TEST_2=test-secret-value-2", 79 | }, 80 | mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider { 81 | sp := SecretsProvider{sm: mockSM, ssm: mockSSM} 82 | vars := map[string]string{ 83 | "arn:aws:secretsmanager:12345678-json": "{\n \"TEST_1\": \"test-secret-value-1\",\n \"TEST_2\": \"test-secret-value-2\"\n}", 84 | } 85 | for n, v := range vars { 86 | name := n 87 | value := v 88 | valueInput := secretsmanager.GetSecretValueInput{SecretId: &name} 89 | valueOutput := secretsmanager.GetSecretValueOutput{SecretString: &value} 90 | mockSM.On("GetSecretValue", &valueInput).Return(&valueOutput, nil) 91 | } 92 | return &sp 93 | }, 94 | }, 95 | { 96 | name: "no secrets", 97 | vars: []string{ 98 | "non-secret-1=hello-1", 99 | "non-secret-2=hello-2", 100 | }, 101 | want: []string{ 102 | "non-secret-1=hello-1", 103 | "non-secret-2=hello-2", 104 | }, 105 | mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider { 106 | return &SecretsProvider{sm: mockSM, ssm: mockSSM} 107 | }, 108 | }, 109 | { 110 | name: "error getting secret from Secrets Manager", 111 | vars: []string{ 112 | "test-secret=arn:aws:secretsmanager:12345678", 113 | "non-secret=hello", 114 | }, 115 | want: []string{ 116 | "test-secret=arn:aws:secretsmanager:12345678", 117 | "non-secret=hello", 118 | }, 119 | wantErr: true, 120 | mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider { 121 | sp := SecretsProvider{sm: mockSM, ssm: mockSSM} 122 | secretName := "arn:aws:secretsmanager:12345678" 123 | valueInput := secretsmanager.GetSecretValueInput{SecretId: &secretName} 124 | mockSM.On("GetSecretValue", &valueInput).Return(nil, errors.New("test error")) 125 | return &sp 126 | }, 127 | }, 128 | { 129 | name: "get single secret from SSM Parameter", 130 | vars: []string{ 131 | "test-secret=arn:aws:ssm:us-east-1:12345678:parameter/secrets/test-secret", 132 | }, 133 | want: []string{ 134 | "test-secret=test-secret-value", 135 | }, 136 | mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider { 137 | sp := SecretsProvider{sm: mockSM, ssm: mockSSM} 138 | secretName := "/secrets/test-secret" 139 | secretValue := "test-secret-value" 140 | withDecryption := true 141 | valueInput := ssm.GetParameterInput{Name: &secretName, WithDecryption: &withDecryption} 142 | valueOutput := ssm.GetParameterOutput{Parameter: &ssm.Parameter{Value: &secretValue}} 143 | mockSSM.On("GetParameter", &valueInput).Return(&valueOutput, nil) 144 | return &sp 145 | }, 146 | }, 147 | { 148 | name: "error getting secret from SSM Parameter Store", 149 | vars: []string{ 150 | "test-secret=arn:aws:ssm:us-east-1:12345678:parameter/secrets/test-secret", 151 | "non-secret=hello", 152 | }, 153 | want: []string{ 154 | "test-secret=arn:aws:ssm:us-east-1:12345678:parameter/secrets/test-secret", 155 | "non-secret=hello", 156 | }, 157 | wantErr: true, 158 | mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider { 159 | sp := SecretsProvider{sm: mockSM, ssm: mockSSM} 160 | secretName := "/secrets/test-secret" 161 | withDecryption := true 162 | valueInput := ssm.GetParameterInput{Name: &secretName, WithDecryption: &withDecryption} 163 | mockSSM.On("GetParameter", &valueInput).Return(nil, errors.New("test error")) 164 | return &sp 165 | }, 166 | }, 167 | } 168 | for _, tt := range tests { 169 | t.Run(tt.name, func(t *testing.T) { 170 | mockSM := &mocks.SecretsManagerAPI{} 171 | mockSSM := &mocks.SSMAPI{} 172 | sp := tt.mockServiceProvider(mockSM, mockSSM) 173 | got, err := sp.ResolveSecrets(context.TODO(), tt.vars) 174 | if (err != nil) != tt.wantErr { 175 | t.Errorf("SecretsProvider.ResolveSecrets() error = %v, wantErr %v", err, tt.wantErr) 176 | return 177 | } 178 | if !reflect.DeepEqual(got, tt.want) { 179 | t.Errorf("SecretsProvider.ResolveSecrets() = %v, want %v", got, tt.want) 180 | } 181 | mockSM.AssertExpectations(t) 182 | mockSSM.AssertExpectations(t) 183 | }) 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /pkg/secrets/google/interface.go: -------------------------------------------------------------------------------- 1 | package google 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/googleapis/gax-go/v2" 7 | secretspb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1" 8 | ) 9 | 10 | // SecretsManagerAPI is the interface for the Google Secrets Manager API. 11 | type SecretsManagerAPI interface { 12 | AccessSecretVersion(ctx context.Context, req *secretspb.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretspb.AccessSecretVersionResponse, error) //nolint:lll 13 | } 14 | -------------------------------------------------------------------------------- /pkg/secrets/google/secrets.go: -------------------------------------------------------------------------------- 1 | package google 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "regexp" 7 | "strings" 8 | "sync" 9 | 10 | "secrets-init/pkg/secrets" //nolint:gci 11 | 12 | "cloud.google.com/go/compute/metadata" 13 | secretmanager "cloud.google.com/go/secretmanager/apiv1" 14 | "github.com/pkg/errors" 15 | log "github.com/sirupsen/logrus" 16 | secretspb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1" //nolint:gci 17 | ) 18 | 19 | var fullSecretRe = regexp.MustCompile(`projects/[^/]+/secrets/[^/+](/version/[^/+])?`) 20 | 21 | type result struct { 22 | Env string 23 | Err error 24 | } 25 | 26 | // SecretsProvider Google Cloud secrets provider 27 | type SecretsProvider struct { 28 | sm SecretsManagerAPI 29 | projectID string 30 | } 31 | 32 | // NewGoogleSecretsProvider init Google Secrets Provider 33 | func NewGoogleSecretsProvider(ctx context.Context, projectID string) (secrets.Provider, error) { 34 | sp := SecretsProvider{} 35 | var err error 36 | 37 | if projectID != "" { 38 | sp.projectID = projectID 39 | } else { 40 | sp.projectID, err = metadata.ProjectID() 41 | if err != nil { 42 | log.WithError(err).Infoln("The Google project cannot be detected, you won't be able to use the short secret version") 43 | } 44 | } 45 | 46 | sp.sm, err = secretmanager.NewClient(ctx) 47 | if err != nil { 48 | return nil, errors.Wrap(err, "failed to initialize Google Cloud SDK") 49 | } 50 | return &sp, nil 51 | } 52 | 53 | // ResolveSecrets replaces all passed variables values prefixed with 'gcp:secretmanager' 54 | // by corresponding secrets from Google Secret Manager 55 | // The secret name should be in the format (optionally with version) 56 | // 57 | // `gcp:secretmanager:projects/{PROJECT_ID}/secrets/{SECRET_NAME}` 58 | // `gcp:secretmanager:projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/{VERSION|latest}` 59 | // `gcp:secretmanager:{SECRET_NAME} 60 | // `gcp:secretmanager:{SECRET_NAME}/versions/{VERSION|latest}` 61 | func (sp SecretsProvider) ResolveSecrets(ctx context.Context, vars []string) ([]string, error) { 62 | envs := make([]string, 0, len(vars)) 63 | 64 | // Create a channel to collect the results 65 | results := make(chan result, len(vars)) 66 | 67 | // Start a goroutine for each secret 68 | var wg sync.WaitGroup 69 | for _, env := range vars { 70 | wg.Add(1) 71 | go func(env string) { 72 | defer wg.Done() 73 | select { 74 | case <-ctx.Done(): 75 | results <- result{Err: ctx.Err()} 76 | return 77 | default: 78 | val, err := sp.processEnvironmentVariable(ctx, env) 79 | if err != nil { 80 | results <- result{Err: err} 81 | return 82 | } 83 | results <- result{Env: val} 84 | } 85 | }(env) 86 | } 87 | 88 | // Start another goroutine to close the results channel when all fetch goroutines are done 89 | go func() { 90 | wg.Wait() 91 | close(results) 92 | }() 93 | 94 | // Collect the results 95 | for res := range results { 96 | if res.Err != nil { 97 | return vars, res.Err 98 | } 99 | envs = append(envs, res.Env) 100 | } 101 | 102 | return envs, nil 103 | } 104 | 105 | // processEnvironmentVariable processes the environment variable and replaces the value with the secret value 106 | func (sp SecretsProvider) processEnvironmentVariable(ctx context.Context, env string) (string, error) { 107 | kv := strings.Split(env, "=") 108 | key, value := kv[0], kv[1] 109 | if !strings.HasPrefix(value, "gcp:secretmanager:") { 110 | return env, nil 111 | } 112 | 113 | // construct valid secret name 114 | name := strings.TrimPrefix(value, "gcp:secretmanager:") 115 | 116 | isLong := fullSecretRe.MatchString(name) 117 | 118 | if !isLong { 119 | if sp.projectID == "" { 120 | return "", errors.Errorf("failed to get secret \"%s\" from Google Secret Manager (unknown project)", name) 121 | } 122 | name = fmt.Sprintf("projects/%s/secrets/%s", sp.projectID, name) 123 | } 124 | 125 | // if no version specified add latest 126 | if !strings.Contains(name, "/versions/") { 127 | name += "/versions/latest" 128 | } 129 | 130 | // get secret value 131 | req := &secretspb.AccessSecretVersionRequest{ 132 | Name: name, 133 | } 134 | secret, err := sp.sm.AccessSecretVersion(ctx, req) 135 | if err != nil { 136 | return "", fmt.Errorf("failed to get secret from Google Secret Manager: %w", err) 137 | } 138 | return key + "=" + string(secret.Payload.GetData()), nil 139 | } 140 | -------------------------------------------------------------------------------- /pkg/secrets/google/secrets_test.go: -------------------------------------------------------------------------------- 1 | // nolint 2 | package google 3 | 4 | import ( 5 | "context" 6 | "errors" 7 | "testing" 8 | 9 | "secrets-init/mocks" 10 | "secrets-init/pkg/secrets" 11 | 12 | "github.com/stretchr/testify/assert" 13 | secretspb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1" 14 | ) 15 | 16 | func TestSecretsProvider_ResolveSecrets(t *testing.T) { 17 | type fields struct { 18 | sm SecretsManagerAPI 19 | } 20 | type args struct { 21 | ctx context.Context 22 | vars []string 23 | } 24 | tests := []struct { 25 | name string 26 | fields fields 27 | args args 28 | mockServiceProvider func(context.Context, *mocks.GoogleSecretsManagerAPI) secrets.Provider 29 | want []string 30 | wantErr bool 31 | }{ 32 | { 33 | name: "get implicit (latest) version single secret from Secrets Manager", 34 | args: args{ 35 | ctx: context.TODO(), 36 | vars: []string{ 37 | "test-secret=gcp:secretmanager:projects/test-project-id/secrets/test-secret", 38 | }, 39 | }, 40 | want: []string{ 41 | "test-secret=test-secret-value", 42 | }, 43 | mockServiceProvider: func(ctx context.Context, mockSM *mocks.GoogleSecretsManagerAPI) secrets.Provider { 44 | sp := SecretsProvider{sm: mockSM} 45 | req := secretspb.AccessSecretVersionRequest{ 46 | Name: "projects/test-project-id/secrets/test-secret/versions/latest", 47 | } 48 | res := secretspb.AccessSecretVersionResponse{Payload: &secretspb.SecretPayload{ 49 | Data: []byte("test-secret-value"), 50 | }} 51 | mockSM.On("AccessSecretVersion", ctx, &req).Return(&res, nil) 52 | return &sp 53 | }, 54 | }, 55 | { 56 | name: "get implicit (latest) version single secret from Secrets Manager with the shorthand syntax", 57 | args: args{ 58 | ctx: context.TODO(), 59 | vars: []string{ 60 | "test-secret=gcp:secretmanager:test-secret", 61 | }, 62 | }, 63 | want: []string{ 64 | "test-secret=test-secret-value", 65 | }, 66 | mockServiceProvider: func(ctx context.Context, mockSM *mocks.GoogleSecretsManagerAPI) secrets.Provider { 67 | sp := SecretsProvider{sm: mockSM, projectID: "test-project-id"} 68 | req := secretspb.AccessSecretVersionRequest{ 69 | Name: "projects/test-project-id/secrets/test-secret/versions/latest", 70 | } 71 | res := secretspb.AccessSecretVersionResponse{Payload: &secretspb.SecretPayload{ 72 | Data: []byte("test-secret-value"), 73 | }} 74 | mockSM.On("AccessSecretVersion", ctx, &req).Return(&res, nil) 75 | return &sp 76 | }, 77 | }, 78 | { 79 | name: "get explicit single secret version from Secrets Manager", 80 | args: args{ 81 | ctx: context.TODO(), 82 | vars: []string{ 83 | "test-secret=gcp:secretmanager:projects/test-project-id/secrets/test-secret/versions/5", 84 | }, 85 | }, 86 | want: []string{ 87 | "test-secret=test-secret-value", 88 | }, 89 | mockServiceProvider: func(ctx context.Context, mockSM *mocks.GoogleSecretsManagerAPI) secrets.Provider { 90 | sp := SecretsProvider{sm: mockSM} 91 | req := secretspb.AccessSecretVersionRequest{ 92 | Name: "projects/test-project-id/secrets/test-secret/versions/5", 93 | } 94 | res := secretspb.AccessSecretVersionResponse{Payload: &secretspb.SecretPayload{ 95 | Data: []byte("test-secret-value"), 96 | }} 97 | mockSM.On("AccessSecretVersion", ctx, &req).Return(&res, nil) 98 | return &sp 99 | }, 100 | }, 101 | { 102 | name: "get explicit single secret version from Secrets Manager with the shorthand syntax", 103 | args: args{ 104 | ctx: context.TODO(), 105 | vars: []string{ 106 | "test-secret=gcp:secretmanager:test-secret/versions/5", 107 | }, 108 | }, 109 | want: []string{ 110 | "test-secret=test-secret-value", 111 | }, 112 | mockServiceProvider: func(ctx context.Context, mockSM *mocks.GoogleSecretsManagerAPI) secrets.Provider { 113 | sp := SecretsProvider{sm: mockSM, projectID: "test-project-id"} 114 | req := secretspb.AccessSecretVersionRequest{ 115 | Name: "projects/test-project-id/secrets/test-secret/versions/5", 116 | } 117 | res := secretspb.AccessSecretVersionResponse{Payload: &secretspb.SecretPayload{ 118 | Data: []byte("test-secret-value"), 119 | }} 120 | mockSM.On("AccessSecretVersion", ctx, &req).Return(&res, nil) 121 | return &sp 122 | }, 123 | }, 124 | { 125 | name: "get 2 secrets from Secrets Manager", 126 | args: args{ 127 | ctx: context.TODO(), 128 | vars: []string{ 129 | "test-secret-1=gcp:secretmanager:projects/test-project-id/secrets/test-secret/versions/5", 130 | "non-secret=hello", 131 | "test-secret-2=gcp:secretmanager:projects/test-project-id/secrets/test-secret", 132 | }, 133 | }, 134 | want: []string{ 135 | "test-secret-1=test-secret-value-1", 136 | "non-secret=hello", 137 | "test-secret-2=test-secret-value-2", 138 | }, 139 | mockServiceProvider: func(ctx context.Context, mockSM *mocks.GoogleSecretsManagerAPI) secrets.Provider { 140 | sp := SecretsProvider{sm: mockSM} 141 | vars := map[string]string{ 142 | "projects/test-project-id/secrets/test-secret/versions/5": "test-secret-value-1", 143 | "projects/test-project-id/secrets/test-secret/versions/latest": "test-secret-value-2", 144 | } 145 | for n, v := range vars { 146 | name := n 147 | value := v 148 | req := secretspb.AccessSecretVersionRequest{ 149 | Name: name, 150 | } 151 | res := secretspb.AccessSecretVersionResponse{Payload: &secretspb.SecretPayload{ 152 | Data: []byte(value), 153 | }} 154 | mockSM.On("AccessSecretVersion", ctx, &req).Return(&res, nil) 155 | } 156 | return &sp 157 | }, 158 | }, 159 | { 160 | name: "no secrets", 161 | args: args{ 162 | ctx: context.TODO(), 163 | vars: []string{ 164 | "non-secret-1=hello-1", 165 | "non-secret-2=hello-2", 166 | }, 167 | }, 168 | want: []string{ 169 | "non-secret-1=hello-1", 170 | "non-secret-2=hello-2", 171 | }, 172 | mockServiceProvider: func(ctx context.Context, mockSM *mocks.GoogleSecretsManagerAPI) secrets.Provider { 173 | return &SecretsProvider{sm: mockSM} 174 | }, 175 | }, 176 | { 177 | name: "error getting secret from Secrets Manager", 178 | args: args{ 179 | ctx: context.TODO(), vars: []string{ 180 | "test-secret=gcp:secretmanager:projects/test-project-id/secrets/test-secret", 181 | "non-secret=hello", 182 | }, 183 | }, 184 | want: []string{ 185 | "test-secret=gcp:secretmanager:projects/test-project-id/secrets/test-secret", 186 | "non-secret=hello", 187 | }, 188 | wantErr: true, 189 | mockServiceProvider: func(ctx context.Context, mockSM *mocks.GoogleSecretsManagerAPI) secrets.Provider { 190 | sp := SecretsProvider{sm: mockSM} 191 | req := secretspb.AccessSecretVersionRequest{ 192 | Name: "projects/test-project-id/secrets/test-secret/versions/latest", 193 | } 194 | mockSM.On("AccessSecretVersion", ctx, &req).Return(nil, errors.New("test error")) 195 | return &sp 196 | }, 197 | }, 198 | } 199 | for _, tt := range tests { 200 | t.Run(tt.name, func(t *testing.T) { 201 | mockSM := &mocks.GoogleSecretsManagerAPI{} 202 | sp := tt.mockServiceProvider(tt.args.ctx, mockSM) 203 | got, err := sp.ResolveSecrets(tt.args.ctx, tt.args.vars) 204 | if (err != nil) != tt.wantErr { 205 | t.Errorf("SecretsProvider.ResolveSecrets() error = %v, wantErr %v", err, tt.wantErr) 206 | return 207 | } 208 | if !assert.ElementsMatch(t, got, tt.want) { 209 | t.Errorf("SecretsProvider.ResolveSecrets() = %v, want %v", got, tt.want) 210 | } 211 | mockSM.AssertExpectations(t) 212 | }) 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /pkg/secrets/provider.go: -------------------------------------------------------------------------------- 1 | package secrets 2 | 3 | import "context" 4 | 5 | // Provider secrets provider interface 6 | type Provider interface { 7 | ResolveSecrets(ctx context.Context, envs []string) ([]string, error) 8 | } 9 | --------------------------------------------------------------------------------