From 4dfa4d2622b52fc23498c302d90b34e959538da5 Mon Sep 17 00:00:00 2001 From: Diego Tejada Date: Tue, 26 Nov 2024 15:54:58 -0500 Subject: [PATCH] feat: Add API key auth support on BeyondTrust provider (#4101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: bump BeyondTrust/go-client-library-passwordsafe version v0.9.1 Signed-off-by: Diego Tejada * feat: add ApiKey attribute to BeyondtrustAuth Signed-off-by: Diego Tejada * chore: update docs with ApiKey reference, add extra help comments Signed-off-by: Diego Tejada * feat: conditionally using API Key or Client Credentials Auth on BeyondTrust provider Signed-off-by: Diego Tejada * test: Add API key tests for BeyondTrust provider Signed-off-by: Diego Tejada * chore: add apiKey to spec.md Signed-off-by: Diego Tejada * chore: make reviewable files Signed-off-by: Diego Tejada * chore: ensured fmt Signed-off-by: Diego Tejada * chore: update APIKey variable case Signed-off-by: Diego Tejada * chore: fix typo Signed-off-by: Diego Tejada * chore: fix typo Signed-off-by: Diego Tejada * chore: fix typo Signed-off-by: Diego Tejada * chore(deps): bump watchdog from 5.0.3 to 6.0.0 in /hack/api-docs (#4067) Bumps [watchdog](https://github.com/gorakhargosh/watchdog) from 5.0.3 to 6.0.0. - [Release notes](https://github.com/gorakhargosh/watchdog/releases) - [Changelog](https://github.com/gorakhargosh/watchdog/blob/master/changelog.rst) - [Commits](https://github.com/gorakhargosh/watchdog/compare/v5.0.3...v6.0.0) --- updated-dependencies: - dependency-name: watchdog dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump pymdown-extensions in /hack/api-docs (#4068) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.11.2 to 10.12. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.11.2...10.12) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump mkdocs-material in /hack/api-docs (#4069) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.5.42 to 9.5.43. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.42...9.5.43) --- updated-dependencies: - dependency-name: mkdocs-material dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump softprops/action-gh-release from 2.0.8 to 2.0.9 (#4070) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.8 to 2.0.9. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/c062e08bd532815e2082a85e87e3ef29c3e6d191...e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore: move inactive maintainers to emeritus (#4073) Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * chore: update dependencies (#4071) * update dependencies Signed-off-by: External Secrets Operator * removed updating sigs.k8s.io/structured-merge-diff/v4 because that broke compilation and fixed two lint issues Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> --------- Signed-off-by: External Secrets Operator Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Co-authored-by: External Secrets Operator Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Update VaultAppRole documentation to show/use roleRef in its examples (#4035) Signed-off-by: Mike Tougeron Co-authored-by: Gustavo Fernandes de Carvalho <17139678+gusfcarvalho@users.noreply.github.com> Signed-off-by: Diego Tejada * feat: add option to configure topic information for GCM (#4055) * feat: add option to configure topic information for GCM Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> * fix the comparison logic for updates to include topics Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> --------- Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * feat: add AWS STS Session token generator (#4041) * feat: add AWS STS Session token generator Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> * version update for the generated CRD Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> --------- Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(helm): Add extra labels to the validating webhooks (#4074) It should add a bunch of app.kubernetes.io labels Signed-off-by: Miguel Sacristán Izcue Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Reduce refreshInterval example for ACR (#4078) The old example used a `refreshInterval` value of 12h for the ACR access token. This change reduces that to 3h instead, since that is the expiration time for Service Principal authentication tokens: https://learn.microsoft.com/en-us/azure/container-registry/container-registry-authentication?tabs=azure-cli#service-principal Service principals are not the only way to authenticate towards ACR. In fact, two other ways (`managedIdentity` and `workloadIdentity`) are also outlined in the docs. I was unable to find any documentation in Azure for the default expiration time for those tokens, so as far as I know it is always 3 hours. Thus I think we should reflect this in our examples. Signed-off-by: Andreas Lindhé <7773090+lindhe@users.noreply.github.com> Signed-off-by: Diego Tejada * Fix PushSecret lookup in keepersecurity provider (#4077) * Fixed Keeper Security custom record type name in docs Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> * Fixed Keeper records lookup in PushSecret Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> * Improved Keeper record lookup to search only for records of the expected type Improved PushSecret and DeleteSecret Fixed "nil pointer dereference" errors Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> * Fixed tests Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> * chore(helm): Add extra labels to the validating webhooks (#4074) It should add a bunch of app.kubernetes.io labels Signed-off-by: Miguel Sacristán Izcue Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> * Added tests for secrets with multiple matches Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> --------- Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> Signed-off-by: Miguel Sacristán Izcue Co-authored-by: Tete17 Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Add ability to use RetrySettings in the VaultDynamicSecret generator (#4076) Signed-off-by: Oleksij Samorukov Signed-off-by: Diego Tejada * chore: make reviewable format Signed-off-by: Diego Tejada * refactor: reduced complexity in NewClient Signed-off-by: Diego Tejada * refactor: reduced function parameters Signed-off-by: Diego Tejada * chore(deps): bump golang from 1.23.2 to 1.23.3 (#4089) Bumps golang from 1.23.2 to 1.23.3. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump packaging from 24.1 to 24.2 in /hack/api-docs (#4090) Bumps [packaging](https://github.com/pypa/packaging) from 24.1 to 24.2. - [Release notes](https://github.com/pypa/packaging/releases) - [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pypa/packaging/compare/24.1...24.2) --- updated-dependencies: - dependency-name: packaging dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump mkdocs-material in /hack/api-docs (#4091) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.5.43 to 9.5.44. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.43...9.5.44) --- updated-dependencies: - dependency-name: mkdocs-material dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * Update docs for ExternalSecrets's refreshInterval (#4097) Fixes #4079 Signed-off-by: Andreas Lindhé <7773090+lindhe@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump zipp from 3.20.2 to 3.21.0 in /hack/api-docs (#4092) Bumps [zipp](https://github.com/jaraco/zipp) from 3.20.2 to 3.21.0. - [Release notes](https://github.com/jaraco/zipp/releases) - [Changelog](https://github.com/jaraco/zipp/blob/main/NEWS.rst) - [Commits](https://github.com/jaraco/zipp/compare/v3.20.2...v3.21.0) --- updated-dependencies: - dependency-name: zipp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump regex from 2024.9.11 to 2024.11.6 in /hack/api-docs (#4093) Bumps [regex](https://github.com/mrabarnett/mrab-regex) from 2024.9.11 to 2024.11.6. - [Changelog](https://github.com/mrabarnett/mrab-regex/blob/hg/changelog.txt) - [Commits](https://github.com/mrabarnett/mrab-regex/compare/2024.9.11...2024.11.6) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump golang from 1.23.2-bookworm to 1.23.3-bookworm in /e2e (#4094) Bumps golang from 1.23.2-bookworm to 1.23.3-bookworm. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * update dependencies (#4096) Signed-off-by: External Secrets Operator Signed-off-by: Moritz Johner Co-authored-by: External Secrets Operator Signed-off-by: Diego Tejada * chore(deps): bump github/codeql-action from 3.27.0 to 3.27.1 (#4088) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.0 to 3.27.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/662472033e021d55d94146f66f6058822b0b39fd...4f3212b61783c3c68e8309a0f18a699764811cda) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * Fix typo in webhook.md (#4100) Signed-off-by: Stas Alekseev <100800+salekseev@users.noreply.github.com> Signed-off-by: Diego Tejada * docs: reformat pushsecrets documentation to be a list (#4102) * reformat pushsecrets documentation to be a list Signed-off-by: twobiers <22715034+twobiers@users.noreply.github.com> * Use sections instead of a list Signed-off-by: twobiers <22715034+twobiers@users.noreply.github.com> --------- Signed-off-by: twobiers <22715034+twobiers@users.noreply.github.com> Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * fix: refresh interval values (#4111) Signed-off-by: Gustavo Signed-off-by: Diego Tejada * Sign helm chart artifact in ghcr.io (#4098) * Install cosign for signing helm charts Signed-off-by: Aruuunn * Fix helm push failing when GITHUB_REPOSITORY_OWNER contains Uppercase alphabets Signed-off-by: Aruuunn * Sign helm chart in oci registry using cosign Signed-off-by: Aruuunn * Add permissions required for cosign signing and provenance attestations Signed-off-by: Aruuunn * Log helm push output Signed-off-by: Aruuunn * Attest build provenance for helm artifact Signed-off-by: Aruuunn * Format: break code block Signed-off-by: Aruuunn * Reformat: Remove temp variable Signed-off-by: Aruuunn * Verify signed helm chart after signing it Signed-off-by: Aruuunn * Remove unnecessary helm action changes for external-secrets repository Signed-off-by: Aruuunn --------- Signed-off-by: Aruuunn Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump distroless/static from `cc226ca` to `f4a57e8` (#4112) Bumps distroless/static from `cc226ca` to `f4a57e8`. --- updated-dependencies: - dependency-name: distroless/static dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump golang from `0974259` to `c694a4d` (#4113) Bumps golang from `0974259` to `c694a4d`. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump alpine from `beefdbd` to `1e42bbe` (#4114) Bumps alpine from `beefdbd` to `1e42bbe`. --- updated-dependencies: - dependency-name: alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump github/codeql-action from 3.27.1 to 3.27.4 (#4115) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.1 to 3.27.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4f3212b61783c3c68e8309a0f18a699764811cda...ea9e4e37992a54ee68a9622e985e60c8e8f12d9f) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump codecov/codecov-action from 4.6.0 to 5.0.2 (#4116) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.6.0 to 5.0.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238...5c47607acb93fed5485fdbf7232e8a31425f672a) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump softprops/action-gh-release from 2.0.9 to 2.1.0 (#4117) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.9 to 2.1.0. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8...01570a1f39cb168c169c802c3bceb9e93fb10974) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump alpine from `beefdbd` to `1e42bbe` in /hack/api-docs (#4118) Bumps alpine from `beefdbd` to `1e42bbe`. --- updated-dependencies: - dependency-name: alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump alpine from `beefdbd` to `1e42bbe` in /e2e (#4119) Bumps alpine from `beefdbd` to `1e42bbe`. --- updated-dependencies: - dependency-name: alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * chore(deps): bump golang from `0e3377d` to `3f3b9da` in /e2e (#4120) Bumps golang from `0e3377d` to `3f3b9da`. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Diego Tejada * fix: re-enable signing helm release (#4109) Signed-off-by: Moritz Johner Signed-off-by: Diego Tejada * update dependencies (#4122) Signed-off-by: External Secrets Operator Co-authored-by: External Secrets Operator Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Update apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Update apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Update apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Update apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * Update pkg/provider/beyondtrust/provider.go Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: Diego Tejada * chore: fix linter errors Signed-off-by: Diego Tejada * refactor: split credentials/certificate reading functionality Signed-off-by: Diego Tejada * style: apply make fmt Signed-off-by: Diego Tejada --------- Signed-off-by: Diego Tejada Signed-off-by: dependabot[bot] Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Signed-off-by: External Secrets Operator Signed-off-by: Mike Tougeron Signed-off-by: Miguel Sacristán Izcue Signed-off-by: Andreas Lindhé <7773090+lindhe@users.noreply.github.com> Signed-off-by: Ivan Dimov <78815270+idimov-keeper@users.noreply.github.com> Signed-off-by: Oleksij Samorukov Signed-off-by: Moritz Johner Signed-off-by: Stas Alekseev <100800+salekseev@users.noreply.github.com> Signed-off-by: twobiers <22715034+twobiers@users.noreply.github.com> Signed-off-by: Gustavo Signed-off-by: Aruuunn Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Co-authored-by: eso-service-account-app[bot] <85832941+eso-service-account-app[bot]@users.noreply.github.com> Co-authored-by: External Secrets Operator Co-authored-by: Mike Tougeron Co-authored-by: Gustavo Fernandes de Carvalho <17139678+gusfcarvalho@users.noreply.github.com> Co-authored-by: Tete17 Co-authored-by: Andreas Lindhé <7773090+lindhe@users.noreply.github.com> Co-authored-by: idimov-keeper <78815270+idimov-keeper@users.noreply.github.com> Co-authored-by: Alex Samorukov Co-authored-by: Stas Alekseev <100800+salekseev@users.noreply.github.com> Co-authored-by: Tobi <22715034+twobiers@users.noreply.github.com> Co-authored-by: Arun Murugan Co-authored-by: Moritz Johner --- .../v1beta1/secretstore_beyondtrust_types.go | 12 +- .../v1beta1/zz_generated.deepcopy.go | 5 + ...ternal-secrets.io_clustersecretstores.yaml | 38 +++- .../external-secrets.io_secretstores.yaml | 38 +++- deploy/crds/bundle.yaml | 62 ++++++- docs/api/spec.md | 17 +- docs/provider/beyondtrust.md | 20 +- docs/snippets/beyondtrust-secret-store.yaml | 4 + pkg/provider/beyondtrust/provider.go | 174 +++++++++++++----- pkg/provider/beyondtrust/provider_test.go | 58 ++++++ 10 files changed, 348 insertions(+), 80 deletions(-) diff --git a/apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go b/apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go index 2d9663e22..9c94b6583 100644 --- a/apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go +++ b/apis/externalsecrets/v1beta1/secretstore_beyondtrust_types.go @@ -29,11 +29,13 @@ type BeyondTrustProviderSecretRef struct { // Configures a store to sync secrets using BeyondTrust Password Safe. type BeyondtrustAuth struct { - // +required - API OAuth Client ID. - ClientID *BeyondTrustProviderSecretRef `json:"clientId"` - // +required - API OAuth Client Secret. - ClientSecret *BeyondTrustProviderSecretRef `json:"clientSecret"` - // Content of the certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. + // APIKey If not provided then ClientID/ClientSecret become required. + APIKey *BeyondTrustProviderSecretRef `json:"apiKey,omitempty"` + // ClientID is the API OAuth Client ID. + ClientID *BeyondTrustProviderSecretRef `json:"clientId,omitempty"` + // ClientSecret is the API OAuth Client Secret. + ClientSecret *BeyondTrustProviderSecretRef `json:"clientSecret,omitempty"` + // Certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. Certificate *BeyondTrustProviderSecretRef `json:"certificate,omitempty"` // Certificate private key (key.pem). For use when authenticating with an OAuth client Id CertificateKey *BeyondTrustProviderSecretRef `json:"certificateKey,omitempty"` diff --git a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go index 06f043190..8208b7f52 100644 --- a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go +++ b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go @@ -414,6 +414,11 @@ func (in *BeyondTrustProviderSecretRef) DeepCopy() *BeyondTrustProviderSecretRef // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BeyondtrustAuth) DeepCopyInto(out *BeyondtrustAuth) { *out = *in + if in.APIKey != nil { + in, out := &in.APIKey, &out.APIKey + *out = new(BeyondTrustProviderSecretRef) + (*in).DeepCopyInto(*out) + } if in.ClientID != nil { in, out := &in.ClientID, &out.ClientID *out = new(BeyondTrustProviderSecretRef) diff --git a/config/crds/bases/external-secrets.io_clustersecretstores.yaml b/config/crds/bases/external-secrets.io_clustersecretstores.yaml index 47d0e9731..33f6d5cc5 100644 --- a/config/crds/bases/external-secrets.io_clustersecretstores.yaml +++ b/config/crds/bases/external-secrets.io_clustersecretstores.yaml @@ -2305,10 +2305,37 @@ spec: description: Auth configures how the operator authenticates with Beyondtrust. properties: + apiKey: + description: APIKey If not provided then ClientID/ClientSecret + become required. + properties: + secretRef: + description: SecretRef references a key in a secret + that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set + a value without using a secret. + type: string + type: object certificate: - description: Content of the certificate (cert.pem) for - use when authenticating with an OAuth client Id using - a Client Certificate. + description: Certificate (cert.pem) for use when authenticating + with an OAuth client Id using a Client Certificate. properties: secretRef: description: SecretRef references a key in a secret @@ -2363,6 +2390,7 @@ spec: type: string type: object clientId: + description: ClientID is the API OAuth Client ID. properties: secretRef: description: SecretRef references a key in a secret @@ -2389,6 +2417,7 @@ spec: type: string type: object clientSecret: + description: ClientSecret is the API OAuth Client Secret. properties: secretRef: description: SecretRef references a key in a secret @@ -2414,9 +2443,6 @@ spec: a value without using a secret. type: string type: object - required: - - clientId - - clientSecret type: object server: description: Auth configures how API server works. diff --git a/config/crds/bases/external-secrets.io_secretstores.yaml b/config/crds/bases/external-secrets.io_secretstores.yaml index 361ad5141..f8576921c 100644 --- a/config/crds/bases/external-secrets.io_secretstores.yaml +++ b/config/crds/bases/external-secrets.io_secretstores.yaml @@ -2305,10 +2305,37 @@ spec: description: Auth configures how the operator authenticates with Beyondtrust. properties: + apiKey: + description: APIKey If not provided then ClientID/ClientSecret + become required. + properties: + secretRef: + description: SecretRef references a key in a secret + that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being + referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set + a value without using a secret. + type: string + type: object certificate: - description: Content of the certificate (cert.pem) for - use when authenticating with an OAuth client Id using - a Client Certificate. + description: Certificate (cert.pem) for use when authenticating + with an OAuth client Id using a Client Certificate. properties: secretRef: description: SecretRef references a key in a secret @@ -2363,6 +2390,7 @@ spec: type: string type: object clientId: + description: ClientID is the API OAuth Client ID. properties: secretRef: description: SecretRef references a key in a secret @@ -2389,6 +2417,7 @@ spec: type: string type: object clientSecret: + description: ClientSecret is the API OAuth Client Secret. properties: secretRef: description: SecretRef references a key in a secret @@ -2414,9 +2443,6 @@ spec: a value without using a secret. type: string type: object - required: - - clientId - - clientSecret type: object server: description: Auth configures how API server works. diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index 0f05f69e9..79e37f529 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -2814,8 +2814,32 @@ spec: auth: description: Auth configures how the operator authenticates with Beyondtrust. properties: + apiKey: + description: APIKey If not provided then ClientID/ClientSecret become required. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object certificate: - description: Content of the certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. + description: Certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. properties: secretRef: description: SecretRef references a key in a secret that will be used as value. @@ -2863,6 +2887,7 @@ spec: type: string type: object clientId: + description: ClientID is the API OAuth Client ID. properties: secretRef: description: SecretRef references a key in a secret that will be used as value. @@ -2886,6 +2911,7 @@ spec: type: string type: object clientSecret: + description: ClientSecret is the API OAuth Client Secret. properties: secretRef: description: SecretRef references a key in a secret that will be used as value. @@ -2908,9 +2934,6 @@ spec: description: Value can be specified directly to set a value without using a secret. type: string type: object - required: - - clientId - - clientSecret type: object server: description: Auth configures how API server works. @@ -8657,8 +8680,32 @@ spec: auth: description: Auth configures how the operator authenticates with Beyondtrust. properties: + apiKey: + description: APIKey If not provided then ClientID/ClientSecret become required. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object certificate: - description: Content of the certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. + description: Certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. properties: secretRef: description: SecretRef references a key in a secret that will be used as value. @@ -8706,6 +8753,7 @@ spec: type: string type: object clientId: + description: ClientID is the API OAuth Client ID. properties: secretRef: description: SecretRef references a key in a secret that will be used as value. @@ -8729,6 +8777,7 @@ spec: type: string type: object clientSecret: + description: ClientSecret is the API OAuth Client Secret. properties: secretRef: description: SecretRef references a key in a secret that will be used as value. @@ -8751,9 +8800,6 @@ spec: description: Value can be specified directly to set a value without using a secret. type: string type: object - required: - - clientId - - clientSecret type: object server: description: Auth configures how API server works. diff --git a/docs/api/spec.md b/docs/api/spec.md index d993fe775..c68aae94f 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -1076,6 +1076,19 @@ External Secrets meta/v1.SecretKeySelector +apiKey
+ + +BeyondTrustProviderSecretRef + + + + +

APIKey If not provided then ClientID/ClientSecret become required.

+ + + + clientId
@@ -1084,6 +1097,7 @@ BeyondTrustProviderSecretRef +

ClientID is the API OAuth Client ID.

@@ -1096,6 +1110,7 @@ BeyondTrustProviderSecretRef +

ClientSecret is the API OAuth Client Secret.

@@ -1108,7 +1123,7 @@ BeyondTrustProviderSecretRef -

Content of the certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate.

+

Certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate.

diff --git a/docs/provider/beyondtrust.md b/docs/provider/beyondtrust.md index 104c4bde8..1f21a4e43 100644 --- a/docs/provider/beyondtrust.md +++ b/docs/provider/beyondtrust.md @@ -22,13 +22,19 @@ BeyondTrust [OAuth Authentication](https://www.beyondtrust.com/docs/beyondinsigh 5. Add the user to the group 6. Add the Secrets Safe Feature to the group -> NOTE: The ClentID and ClientSecret must be stored in a Kubernetes secret in order for the SecretStore to read the configuration. +> NOTE: The ClientID and ClientSecret must be stored in a Kubernetes secret in order for the SecretStore to read the configuration. +If you're using client credentials authentication: ```sh kubectl create secret generic bt-secret --from-literal ClientSecret="" kubectl create secret generic bt-id --from-literal ClientId="" ``` +If you're using API Key authentication: +```sh +kubectl create secret generic bt-apikey --from-literal ApiKey="" +``` + ### Client Certificate If using `retrievalType: MANAGED_ACCOUNT`, you will also need to download the pfx certificate from Secrets Safe, extract that certificate and create two Kubernetes secrets. @@ -70,7 +76,7 @@ spec: beyondtrust: server: apiUrl: https://example.com:443/BeyondTrust/api/public/v3/ - retrievalType: MANAGED_ACCOUNT # or SECRET + retrievalType: MANAGED_ACCOUNT # or SECRET verifyCA: true clientTimeOutSeconds: 45 auth: @@ -82,17 +88,21 @@ spec: secretRef: name: bt-certificatekey key: ClientCertificateKey - clientSecret: + clientSecret: # define this section if using client credentials authentication secretRef: name: bt-secret key: ClientSecret - clientId: + clientId: # define this section if using client credentials authentication secretRef: name: bt-id key: ClientId + apiKey: # define this section if using Api Key authentication + secretRef: + name: bt-apikey + key: ApiKey ``` -### Creating a ExternalSecret +### Creating an ExternalSecret You can follow the below example to create a `ExternalSecret` resource. Secrets can be referenced by path. You can also use a `ClusterExternalSecret` allowing you to reference secrets from all namespaces. diff --git a/docs/snippets/beyondtrust-secret-store.yaml b/docs/snippets/beyondtrust-secret-store.yaml index 9b4deccf4..ea163a3ea 100644 --- a/docs/snippets/beyondtrust-secret-store.yaml +++ b/docs/snippets/beyondtrust-secret-store.yaml @@ -22,6 +22,10 @@ spec: secretRef: name: bt-id key: ClientId + apiKey: + secretRef: + name: bt-apikey + key: ApiKey server: retrievalType: MANAGED_ACCOUNT verifyCA: true diff --git a/pkg/provider/beyondtrust/provider.go b/pkg/provider/beyondtrust/provider.go index c8fe32fd1..a32fed024 100644 --- a/pkg/provider/beyondtrust/provider.go +++ b/pkg/provider/beyondtrust/provider.go @@ -65,6 +65,18 @@ type Provider struct { separator string } +type AuthenticatorInput struct { + Config *esv1beta1.BeyondtrustProvider + HTTPClientObj utils.HttpClientObj + BackoffDefinition *backoff.ExponentialBackOff + APIURL string + ClientID string + ClientSecret string + APIKey string + Logger *logging.LogrLogger + RetryMaxElapsedTimeMinutes int +} + // Capabilities implements v1beta1.Provider. func (*Provider) Capabilities() esv1beta1.SecretStoreCapabilities { return esv1beta1.SecretStoreReadOnly @@ -111,57 +123,30 @@ func (*Provider) SecretExists(_ context.Context, _ esv1beta1.PushSecretRemoteRef func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube client.Client, namespace string) (esv1beta1.SecretsClient, error) { config := store.GetSpec().Provider.Beyondtrust logger := logging.NewLogrLogger(&ESOLogger) - apiURL := config.Server.APIURL - certificate := "" - certificateKey := "" - clientTimeOutInSeconds := 45 - retryMaxElapsedTimeMinutes := 15 - separator := "/" - if config.Server.Separator != "" { - separator = config.Server.Separator - } - - if config.Server.ClientTimeOutSeconds != 0 { - clientTimeOutInSeconds = config.Server.ClientTimeOutSeconds - } - - backoffDefinition := backoff.NewExponentialBackOff() - backoffDefinition.InitialInterval = 1 * time.Second - backoffDefinition.MaxElapsedTime = time.Duration(retryMaxElapsedTimeMinutes) * time.Second - backoffDefinition.RandomizationFactor = 0.5 - - clientID, err := loadConfigSecret(ctx, config.Auth.ClientID, kube, namespace) + clientID, clientSecret, apiKey, err := loadCredentialsFromConfig(ctx, config, kube, namespace) if err != nil { - return nil, fmt.Errorf("error loading clientID: %w", err) + return nil, fmt.Errorf("error loading credentials: %w", err) } - clientSecret, err := loadConfigSecret(ctx, config.Auth.ClientSecret, kube, namespace) + certificate, certificateKey, err := loadCertificateFromConfig(ctx, config, kube, namespace) if err != nil { - return nil, fmt.Errorf("error loading clientSecret: %w", err) + return nil, fmt.Errorf("error loading certificate: %w", err) } - if config.Auth.Certificate != nil && config.Auth.CertificateKey != nil { - loadedCertificate, err := loadConfigSecret(ctx, config.Auth.Certificate, kube, namespace) - if err != nil { - return nil, fmt.Errorf("error loading Certificate: %w", err) - } - - certificate = loadedCertificate - - loadedCertificateKey, err := loadConfigSecret(ctx, config.Auth.CertificateKey, kube, namespace) - if err != nil { - return nil, fmt.Errorf("error loading Certificate Key: %w", err) - } - - certificateKey = loadedCertificateKey + if err != nil { + return nil, fmt.Errorf("error loading secrets: %w", err) } - // Create an instance of ValidationParams + clientTimeOutInSeconds, separator, retryMaxElapsedTimeMinutes := getConfigValues(config) + + backoffDefinition := getBackoffDefinition(retryMaxElapsedTimeMinutes) + params := utils.ValidationParams{ + ApiKey: apiKey, ClientID: clientID, ClientSecret: clientSecret, - ApiUrl: &apiURL, + ApiUrl: &config.Server.APIURL, ClientTimeOutInSeconds: clientTimeOutInSeconds, Separator: &separator, VerifyCa: config.Server.VerifyCA, @@ -172,22 +157,33 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, MaxFileSecretSizeBytes: &maxFileSecretSizeBytes, } - errorsInInputs := utils.ValidateInputs(params) - - if errorsInInputs != nil { - return nil, fmt.Errorf("error in Inputs: %w", errorsInInputs) + if err := validateInputs(params); err != nil { + return nil, fmt.Errorf("error in Inputs: %w", err) } - // creating a http client - httpClientObj, err := utils.GetHttpClient(clientTimeOutInSeconds, config.Server.VerifyCA, certificate, certificateKey, logger) + httpClient, err := utils.GetHttpClient(clientTimeOutInSeconds, config.Server.VerifyCA, certificate, certificateKey, logger) + if err != nil { + return nil, fmt.Errorf("error creating HTTP client: %w", err) + } + + authenticatorInput := AuthenticatorInput{ + Config: config, + HTTPClientObj: *httpClient, + BackoffDefinition: backoffDefinition, + APIURL: config.Server.APIURL, + ClientID: clientID, + ClientSecret: clientSecret, + APIKey: apiKey, + Logger: logger, + RetryMaxElapsedTimeMinutes: retryMaxElapsedTimeMinutes, + } + + authenticate, err := getAuthenticator(authenticatorInput) if err != nil { - return nil, fmt.Errorf("error creating http client: %w", err) + return nil, fmt.Errorf("error authenticating: %w", err) } - // instantiating authenticate obj, injecting httpClient object - authenticate, _ := auth.Authenticate(*httpClientObj, backoffDefinition, apiURL, clientID, clientSecret, logger, retryMaxElapsedTimeMinutes) - return &Provider{ apiURL: config.Server.APIURL, retrievaltype: config.Server.RetrievalType, @@ -197,6 +193,86 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, }, nil } +func loadCredentialsFromConfig(ctx context.Context, config *esv1beta1.BeyondtrustProvider, kube client.Client, namespace string) (string, string, string, error) { + var clientID, clientSecret, apiKey string + var err error + + if config.Auth.APIKey != nil { + apiKey, err = loadConfigSecret(ctx, config.Auth.APIKey, kube, namespace) + if err != nil { + return "", "", "", fmt.Errorf("error loading apiKey: %w", err) + } + } else { + clientID, err = loadConfigSecret(ctx, config.Auth.ClientID, kube, namespace) + if err != nil { + return "", "", "", fmt.Errorf("error loading clientID: %w", err) + } + + clientSecret, err = loadConfigSecret(ctx, config.Auth.ClientSecret, kube, namespace) + if err != nil { + return "", "", "", fmt.Errorf("error loading clientSecret: %w", err) + } + } + + return clientID, clientSecret, apiKey, nil +} + +func loadCertificateFromConfig(ctx context.Context, config *esv1beta1.BeyondtrustProvider, kube client.Client, namespace string) (string, string, error) { + var certificate, certificateKey string + var err error + + if config.Auth.Certificate != nil && config.Auth.CertificateKey != nil { + certificate, err = loadConfigSecret(ctx, config.Auth.Certificate, kube, namespace) + if err != nil { + return "", "", fmt.Errorf("error loading Certificate: %w", err) + } + + certificateKey, err = loadConfigSecret(ctx, config.Auth.CertificateKey, kube, namespace) + if err != nil { + return "", "", fmt.Errorf("error loading Certificate Key: %w", err) + } + } + + return certificate, certificateKey, nil +} + +func getConfigValues(config *esv1beta1.BeyondtrustProvider) (int, string, int) { + clientTimeOutInSeconds := 45 + separator := "/" + retryMaxElapsedTimeMinutes := 15 + + if config.Server.ClientTimeOutSeconds != 0 { + clientTimeOutInSeconds = config.Server.ClientTimeOutSeconds + } + + if config.Server.Separator != "" { + separator = config.Server.Separator + } + + return clientTimeOutInSeconds, separator, retryMaxElapsedTimeMinutes +} + +func getBackoffDefinition(retryMaxElapsedTimeMinutes int) *backoff.ExponentialBackOff { + backoffDefinition := backoff.NewExponentialBackOff() + backoffDefinition.InitialInterval = 1 * time.Second + backoffDefinition.MaxElapsedTime = time.Duration(retryMaxElapsedTimeMinutes) * time.Minute + backoffDefinition.RandomizationFactor = 0.5 + + return backoffDefinition +} + +func validateInputs(params utils.ValidationParams) error { + return utils.ValidateInputs(params) +} + +func getAuthenticator(input AuthenticatorInput) (*auth.AuthenticationObj, error) { + if input.Config.Auth.APIKey != nil { + return auth.AuthenticateUsingApiKey(input.HTTPClientObj, input.BackoffDefinition, input.APIURL, input.Logger, input.RetryMaxElapsedTimeMinutes, input.APIKey) + } + + return auth.Authenticate(input.HTTPClientObj, input.BackoffDefinition, input.APIURL, input.ClientID, input.ClientSecret, input.Logger, input.RetryMaxElapsedTimeMinutes) +} + func loadConfigSecret(ctx context.Context, ref *esv1beta1.BeyondTrustProviderSecretRef, kube client.Client, defaultNamespace string) (string, error) { if ref.SecretRef == nil { return ref.Value, nil diff --git a/pkg/provider/beyondtrust/provider_test.go b/pkg/provider/beyondtrust/provider_test.go index 37bb6a4af..5ec5bda16 100644 --- a/pkg/provider/beyondtrust/provider_test.go +++ b/pkg/provider/beyondtrust/provider_test.go @@ -29,6 +29,7 @@ import ( const ( errTestCase = "Test case Failed" fakeAPIURL = "https://example.com:443/BeyondTrust/api/public/v3/" + apiKey = "fakeapikey00fakeapikeydd0000000000065b010f20fakeapikey0000000008700000a93fb5d74fddc0000000000000000000000000000000000000;runas=test_user" clientID = "12345678-25fg-4b05-9ced-35e7dd5093ae" clientSecret = "12345678-25fg-4b05-9ced-35e7dd5093ae" ) @@ -268,6 +269,63 @@ func TestNewClient(t *testing.T) { validateErrorText: true, expectedErrorText: "error in Inputs: Key: 'UserInputValidaton.ClientTimeOutinSeconds' Error:Field validation for 'ClientTimeOutinSeconds' failed on the 'lte' tag", }, + { + name: "ApiKey ok", + nameSpace: "test", + args: args{ + store: esv1beta1.SecretStore{ + Spec: esv1beta1.SecretStoreSpec{ + Provider: &esv1beta1.SecretStoreProvider{ + Beyondtrust: &esv1beta1.BeyondtrustProvider{ + Server: &esv1beta1.BeyondtrustServer{ + APIURL: fakeAPIURL, + RetrievalType: "SECRET", + }, + + Auth: &esv1beta1.BeyondtrustAuth{ + APIKey: &esv1beta1.BeyondTrustProviderSecretRef{ + Value: apiKey, + }, + }, + }, + }, + }, + }, + kube: createMockPasswordSafeClient(t), + provider: &Provider{}, + }, + validateErrorNil: true, + validateErrorText: false, + }, + { + name: "Bad ApiKey", + nameSpace: "test", + args: args{ + store: esv1beta1.SecretStore{ + Spec: esv1beta1.SecretStoreSpec{ + Provider: &esv1beta1.SecretStoreProvider{ + Beyondtrust: &esv1beta1.BeyondtrustProvider{ + Server: &esv1beta1.BeyondtrustServer{ + APIURL: fakeAPIURL, + RetrievalType: "SECRET", + }, + + Auth: &esv1beta1.BeyondtrustAuth{ + APIKey: &esv1beta1.BeyondTrustProviderSecretRef{ + Value: "bad_api_key", + }, + }, + }, + }, + }, + }, + kube: createMockPasswordSafeClient(t), + provider: &Provider{}, + }, + validateErrorNil: false, + validateErrorText: true, + expectedErrorText: "error in Inputs: Key: 'UserInputValidaton.ApiKey' Error:Field validation for 'ApiKey' failed on the 'min' tag", + }, } for _, tt := range tests {