mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-14 11:57:59 +00:00
Merge branch 'main' into feature/docs-versioning
This commit is contained in:
commit
47a7425a2a
47 changed files with 1956 additions and 338 deletions
5
.github/codecov.yml
vendored
5
.github/codecov.yml
vendored
|
@ -1,5 +0,0 @@
|
|||
ignore:
|
||||
- pkg/provider/**/fake
|
||||
coverage:
|
||||
round: down
|
||||
precision: 2
|
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
|
@ -12,9 +12,7 @@ env:
|
|||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.42.1'
|
||||
# list of available versions: https://storage.googleapis.com/kubebuilder-tools
|
||||
# TODO: 1.21.2 does not shut down properly with controller-runtime 0.9.2
|
||||
KUBEBUILDER_TOOLS_VERSION: '1.20.2'
|
||||
KUBERNETES_VERSION: '1.23.x'
|
||||
DOCKER_BUILDX_VERSION: 'v0.4.2'
|
||||
|
||||
# Common users. We can't run a step 'if secrets.GHCR_USERNAME != ""' but we can run
|
||||
|
@ -164,22 +162,22 @@ jobs:
|
|||
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-pkg-
|
||||
|
||||
- name: Add envtest binaries
|
||||
- name: Add setup-envtest
|
||||
run: |
|
||||
curl -sSLo envtest-bins.tar.gz "https://storage.googleapis.com/kubebuilder-tools/kubebuilder-tools-${{env.KUBEBUILDER_TOOLS_VERSION}}-linux-amd64.tar.gz"
|
||||
sudo mkdir -p /usr/local/kubebuilder
|
||||
sudo tar -C /usr/local/kubebuilder --strip-components=1 -zvxf envtest-bins.tar.gz
|
||||
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
|
||||
setup-envtest use ${{env.KUBERNETES_VERSION}} -p env --os $(go env GOOS) --arch $(go env GOARCH)
|
||||
|
||||
- name: Cache envtest binaries
|
||||
uses: actions/cache@v2.1.7
|
||||
with:
|
||||
path: /usr/local/kubebuilder
|
||||
key: ${{ runner.os }}-kubebuilder-${{env.KUBEBUILDER_TOOLS_VERSION}}
|
||||
path: /home/runner/.local/share/kubebuilder-envtest/
|
||||
key: ${{ runner.os }}-kubebuilder-${{env.KUBERNETES_VERSION}}
|
||||
restore-keys: ${{ runner.os }}-kubebuilder-
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
export KUBEBUILDER_ATTACH_CONTROL_PLANE_OUTPUT=true
|
||||
source <(setup-envtest use ${{env.KUBERNETES_VERSION}} -p env --os $(go env GOOS) --arch $(go env GOARCH))
|
||||
make test
|
||||
|
||||
|
||||
|
|
47
.github/workflows/e2e-managed.yml
vendored
47
.github/workflows/e2e-managed.yml
vendored
|
@ -1,6 +1,5 @@
|
|||
# Run secret-dependent e2e tests only after /ok-to-test-managed approval
|
||||
on:
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [ok-to-test-managed-command]
|
||||
|
||||
|
@ -49,6 +48,48 @@ jobs:
|
|||
|
||||
steps:
|
||||
|
||||
# create new status check for this specific provider
|
||||
- uses: actions/github-script@v1
|
||||
if: ${{ always() }}
|
||||
env:
|
||||
number: ${{ github.event.client_payload.pull_request.number }}
|
||||
provider: ${{ github.event.client_payload.slash_command.args.named.provider }}
|
||||
job: ${{ github.job }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { data: pull } = await github.pulls.get({
|
||||
...context.repo,
|
||||
pull_number: process.env.number
|
||||
});
|
||||
const ref = pull.head.sha;
|
||||
console.log("\n\nPR sha: " + ref)
|
||||
const { data: checks } = await github.checks.listForRef({
|
||||
...context.repo,
|
||||
ref
|
||||
});
|
||||
const job_name = process.env.job + "-" + process.env.provider
|
||||
console.log("\n\nPR CHECKS: " + checks)
|
||||
const check = checks.check_runs.filter(c => c.name === job_name);
|
||||
console.log("\n\nPR Filtered CHECK: " + check)
|
||||
console.log(check)
|
||||
if(check && check.length > 0){
|
||||
const { data: result } = await github.checks.update({
|
||||
...context.repo,
|
||||
check_run_id: check[0].id,
|
||||
status: 'in_progress',
|
||||
});
|
||||
return result;
|
||||
}
|
||||
const { data: result } = await github.checks.create({
|
||||
...context.repo,
|
||||
name: job_name,
|
||||
head_sha: pull.head.sha,
|
||||
status: 'in_progress',
|
||||
});
|
||||
return result;
|
||||
|
||||
|
||||
# Check out merge commit
|
||||
- name: Fork based /ok-to-test-managed checkout
|
||||
uses: actions/checkout@v2
|
||||
|
@ -164,6 +205,7 @@ jobs:
|
|||
if: ${{ always() }}
|
||||
env:
|
||||
number: ${{ github.event.client_payload.pull_request.number }}
|
||||
provider: ${{ github.event.client_payload.slash_command.args.named.provider }}
|
||||
job: ${{ github.job }}
|
||||
# Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run
|
||||
conclusion: ${{ job.status }}
|
||||
|
@ -180,8 +222,9 @@ jobs:
|
|||
...context.repo,
|
||||
ref
|
||||
});
|
||||
const job_name = process.env.job + "-" + process.env.provider
|
||||
console.log("\n\nPR CHECKS: " + checks)
|
||||
const check = checks.check_runs.filter(c => c.name === process.env.job);
|
||||
const check = checks.check_runs.filter(c => c.name === job_name);
|
||||
console.log("\n\nPR Filtered CHECK: " + check)
|
||||
console.log(check)
|
||||
const { data: result } = await github.checks.update({
|
||||
|
|
10
.github/workflows/e2e.yml
vendored
10
.github/workflows/e2e.yml
vendored
|
@ -9,6 +9,8 @@ env:
|
|||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.33'
|
||||
DOCKER_BUILDX_VERSION: 'v0.4.2'
|
||||
KIND_VERSION: 'v0.11.1'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
|
||||
# Common users. We can't run a step 'if secrets.GHCR_USERNAME != ""' but we can run
|
||||
# a step 'if env.GHCR_USERNAME' != ""', so we copy these to succinctly test whether
|
||||
|
@ -71,9 +73,9 @@ jobs:
|
|||
- name: Setup kind
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
version: "v0.11.1"
|
||||
version: ${{env.KIND_VERSION}}
|
||||
wait: 10m
|
||||
node_image: kindest/node:v1.20.7
|
||||
node_image: ${{env.KIND_IMAGE}}
|
||||
name: external-secrets
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
|
@ -134,9 +136,9 @@ jobs:
|
|||
- name: Setup kind
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
version: "v0.11.1"
|
||||
version: ${{env.KIND_VERSION}}
|
||||
wait: 10m
|
||||
node_image: kindest/node:v1.20.7
|
||||
node_image: ${{env.KIND_IMAGE}}
|
||||
name: external-secrets
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
|
|
4
.github/workflows/helm.yml
vendored
4
.github/workflows/helm.yml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
|||
make helm.generate
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v1.1
|
||||
uses: azure/setup-helm@v2.0
|
||||
with:
|
||||
version: v3.4.2
|
||||
|
||||
|
@ -62,7 +62,7 @@ jobs:
|
|||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v1.1
|
||||
uses: azure/setup-helm@v2.0
|
||||
with:
|
||||
version: v3.4.2
|
||||
|
||||
|
|
27
apis/externalsecrets/v1alpha1/secretstore_fake_types.go
Normal file
27
apis/externalsecrets/v1alpha1/secretstore_fake_types.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// FakeProvider configures a fake provider that returns static values.
|
||||
type FakeProvider struct {
|
||||
Data []FakeProviderData `json:"data"`
|
||||
}
|
||||
|
||||
type FakeProviderData struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value,omitempty"`
|
||||
ValueMap map[string]string `json:"valueMap,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
|
@ -81,6 +81,10 @@ type SecretStoreProvider struct {
|
|||
// Webhook configures this store to sync secrets using a generic templated webhook
|
||||
// +optional
|
||||
Webhook *WebhookProvider `json:"webhook,omitempty"`
|
||||
|
||||
// Fake configures a store with static key/value pairs
|
||||
// +optional
|
||||
Fake *FakeProvider `json:"fake,omitempty"`
|
||||
}
|
||||
|
||||
type SecretStoreRetrySettings struct {
|
||||
|
|
|
@ -599,6 +599,50 @@ func (in *ExternalSecretTemplateMetadata) DeepCopy() *ExternalSecretTemplateMeta
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FakeProvider) DeepCopyInto(out *FakeProvider) {
|
||||
*out = *in
|
||||
if in.Data != nil {
|
||||
in, out := &in.Data, &out.Data
|
||||
*out = make([]FakeProviderData, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FakeProvider.
|
||||
func (in *FakeProvider) DeepCopy() *FakeProvider {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FakeProvider)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FakeProviderData) DeepCopyInto(out *FakeProviderData) {
|
||||
*out = *in
|
||||
if in.ValueMap != nil {
|
||||
in, out := &in.ValueMap, &out.ValueMap
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FakeProviderData.
|
||||
func (in *FakeProviderData) DeepCopy() *FakeProviderData {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FakeProviderData)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GCPSMAuth) DeepCopyInto(out *GCPSMAuth) {
|
||||
*out = *in
|
||||
|
@ -939,6 +983,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) {
|
|||
*out = new(WebhookProvider)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Fake != nil {
|
||||
in, out := &in.Fake, &out.Fake
|
||||
*out = new(FakeProvider)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreProvider.
|
||||
|
|
|
@ -380,6 +380,29 @@ spec:
|
|||
required:
|
||||
- vaultUrl
|
||||
type: object
|
||||
fake:
|
||||
description: Fake configures a store with static key/value pairs
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
valueMap:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
version:
|
||||
type: string
|
||||
required:
|
||||
- key
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- data
|
||||
type: object
|
||||
gcpsm:
|
||||
description: GCPSM configures this store to sync secrets using
|
||||
Google Cloud Platform Secret Manager provider
|
||||
|
|
|
@ -380,6 +380,29 @@ spec:
|
|||
required:
|
||||
- vaultUrl
|
||||
type: object
|
||||
fake:
|
||||
description: Fake configures a store with static key/value pairs
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
valueMap:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
version:
|
||||
type: string
|
||||
required:
|
||||
- key
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- data
|
||||
type: object
|
||||
gcpsm:
|
||||
description: GCPSM configures this store to sync secrets using
|
||||
Google Cloud Platform Secret Manager provider
|
||||
|
|
|
@ -31,6 +31,82 @@ for the lifecycle of the PR: review, merging, ping on inactivity, close.
|
|||
We close pull requests or issues if there is no response from the author for
|
||||
a period of time. Feel free to reopen if you want to get back on it.
|
||||
|
||||
### Triggering e2e tests
|
||||
|
||||
We have an extensive set of e2e tests that test the integration with *real* cloud provider APIs.
|
||||
Maintainers must trigger these kind of tests manually for PRs that come from forked repositories. These tests run inside a `kind` cluster in the GitHub Actions runner:
|
||||
|
||||
```
|
||||
/ok-to-test sha=xxxxxx
|
||||
```
|
||||
|
||||
#### Executing e2e tests locally
|
||||
|
||||
You have to prepare your shell environment with the necessary variables so the e2e test
|
||||
runner knows what credentials to use. See `e2e/run.sh` for the variables that are passed in.
|
||||
If you e.g. want to test AWS integration make sure set all `AWS_*` variables mentioned
|
||||
in that file.
|
||||
|
||||
Use [ginkgo labels](https://onsi.github.io/ginkgo/#spec-labels) to select the tests
|
||||
you want to execute. You have to specify `!managed` to ensure that you do not
|
||||
run managed tests.
|
||||
|
||||
```
|
||||
make test.e2e GINKGO_LABELS='gcp&&!managed'
|
||||
```
|
||||
|
||||
#### Managed Kubernetes e2e tests
|
||||
|
||||
There's another suite of e2e tests that integrate with managed Kuberentes offerings.
|
||||
They create real infrastructure at a cloud provider and deploy the controller
|
||||
into that environment.
|
||||
This is necessary to test the authentication integration
|
||||
([GCP Worklaod Identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity),
|
||||
[EKS IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)...).
|
||||
|
||||
These tests are time intensive (~20-45min) and must be triggered manually by
|
||||
a maintainer when a particular provider or authentication mechanism was changed:
|
||||
|
||||
```
|
||||
/ok-to-test-managed sha=xxxxxx provider=aws
|
||||
# or
|
||||
/ok-to-test-managed sha=xxxxxx provider=gcp
|
||||
```
|
||||
|
||||
Both tests can run in parallel. Once started they add a dynamic GitHub check `integration-managed-(gcp|aws)` to the PR that triggered the test.
|
||||
|
||||
|
||||
### Executing Managed Kubernetes e2e tests locally
|
||||
|
||||
You have to prepare your shell environment with the necessary variables so the e2e
|
||||
test runner knows what credentials to use. See `.github/workflows/e2e-managed.yml`
|
||||
for the variables that are passed in. If you e.g. want to test AWS integration make
|
||||
sure set all variables containing `AWS_*` and `TF_VAR_AWS_*` mentioned in that file.
|
||||
|
||||
Then execute `tf.apply.aws` or `tf.apply.gcp` to create the infrastructure.
|
||||
|
||||
```
|
||||
make tf.apply.aws
|
||||
```
|
||||
|
||||
Then run the `managed` testsuite. You will need push permissions to the external-secrets ghcr repository. You can set `IMAGE_REGISTRY` to control which image registry is used to store the controller and e2e test images in.
|
||||
|
||||
You also have to setup a proper Kubeconfig so the e2e test pod gets deployed into the managed cluster.
|
||||
|
||||
```
|
||||
aws eks update-kubeconfig --name ${AWS_CLUSTER_NAME}
|
||||
or
|
||||
gcloud container clusters get-credentials ${GCP_GKE_CLUSTER} --region europe-west1-b
|
||||
```
|
||||
|
||||
Use [ginkgo labels](https://onsi.github.io/ginkgo/#spec-labels) to select the tests
|
||||
you want to execute.
|
||||
|
||||
```
|
||||
# you may have to set IMAGE_REGISTRY=docker.io/your-user/external-secrets
|
||||
make test.e2e.managed GINKGO_LABELS='gcp'
|
||||
```
|
||||
|
||||
## Proposal Process
|
||||
Before we introduce significant changes to the project we want to gather feedback
|
||||
from the community to ensure that we progress in the right direction before we
|
||||
|
|
26
docs/provider-fake.md
Normal file
26
docs/provider-fake.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
We provide a `fake` implementation to help with testing. This provider returns static key/value pairs and nothing else.
|
||||
To use the `fake` provider simply create a `SecretStore` or `ClusterSecretStore` and configure it like in the following example:
|
||||
|
||||
!!! note inline end
|
||||
The provider returns static data configured in `value` or `valueMap`. You can define a `version`, too. If set the `remoteRef` from an ExternalSecret must match otherwise no value is returned.
|
||||
|
||||
```yaml
|
||||
{% include 'fake-provider-store.yaml' %}
|
||||
```
|
||||
|
||||
Please note that `value` is intended for exclusive use with `data` and `valueMap` for `dataFrom`.
|
||||
Here is an example `ExternalSecret` that displays this behavior:
|
||||
|
||||
!!! warning inline end
|
||||
This provider supports specifying different `data[].version` configurations. However, `data[].property` is ignored.
|
||||
|
||||
```yaml
|
||||
{% include 'fake-provider-es.yaml' %}
|
||||
```
|
||||
|
||||
This results in the following secret:
|
||||
|
||||
|
||||
```yaml
|
||||
{% include 'fake-provider-secret.yaml' %}
|
||||
```
|
18
docs/snippets/fake-provider-es.yaml
Normal file
18
docs/snippets/fake-provider-es.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
apiVersion: external-secrets.io/v1alpha1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
name: fake
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: secret-to-be-created
|
||||
data:
|
||||
- secretKey: foo_bar
|
||||
remoteRef:
|
||||
key: /foo/bar
|
||||
version: v1
|
||||
dataFrom:
|
||||
- key: /foo/baz
|
9
docs/snippets/fake-provider-secret.yaml
Normal file
9
docs/snippets/fake-provider-secret.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-to-be-created
|
||||
namespace: default
|
||||
data:
|
||||
foo_bar: SEVMTE8x # HELLO1 (via data)
|
||||
foo: ZXhhbXBsZQ== # example (via dataFrom)
|
||||
other: dGhpbmc= # thing (via dataFrom)
|
20
docs/snippets/fake-provider-store.yaml
Normal file
20
docs/snippets/fake-provider-store.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
apiVersion: external-secrets.io/v1alpha1
|
||||
kind: ClusterSecretStore
|
||||
metadata:
|
||||
name: fake
|
||||
spec:
|
||||
provider:
|
||||
fake:
|
||||
data:
|
||||
- key: "/foo/bar"
|
||||
value: "HELLO1"
|
||||
version: "v1"
|
||||
- key: "/foo/bar"
|
||||
value: "HELLO2"
|
||||
version: "v2"
|
||||
- key: "/foo/baz"
|
||||
valueMap:
|
||||
foo: example
|
||||
other: thing
|
||||
|
||||
|
336
docs/spec.md
336
docs/spec.md
|
@ -714,6 +714,237 @@ string
|
|||
<td></td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.ClusterExternalSecret">ClusterExternalSecret
|
||||
</h3>
|
||||
<p>
|
||||
<p>ClusterExternalSecret is the Schema for the clusterexternalsecrets API.</p>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>metadata</code></br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta">
|
||||
Kubernetes meta/v1.ObjectMeta
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
Refer to the Kubernetes API documentation for the fields of the
|
||||
<code>metadata</code> field.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>spec</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecretSpec">
|
||||
ClusterExternalSecretSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<br/>
|
||||
<br/>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<code>externalSecretSpec</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.ExternalSecretSpec">
|
||||
ExternalSecretSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>The spec for the ExternalSecrets to be created</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>externalSecretName</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>The name of the external secrets to be created defaults to the name of the ClusterExternalSecret</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>namespaceSelector</code></br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#labelselector-v1-meta">
|
||||
Kubernetes meta/v1.LabelSelector
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>The labels to select by to find the Namespaces to create the ExternalSecrets in.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>status</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecretStatus">
|
||||
ClusterExternalSecretStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.ClusterExternalSecretConditionType">ClusterExternalSecretConditionType
|
||||
(<code>string</code> alias)</p></h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecretStatus">ClusterExternalSecretStatus</a>)
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr><td><p>"NotReady"</p></td>
|
||||
<td></td>
|
||||
</tr><tr><td><p>"PartiallyReady"</p></td>
|
||||
<td></td>
|
||||
</tr><tr><td><p>"Ready"</p></td>
|
||||
<td></td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.ClusterExternalSecretSpec">ClusterExternalSecretSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecret">ClusterExternalSecret</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret.</p>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>externalSecretSpec</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.ExternalSecretSpec">
|
||||
ExternalSecretSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>The spec for the ExternalSecrets to be created</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>externalSecretName</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>The name of the external secrets to be created defaults to the name of the ClusterExternalSecret</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>namespaceSelector</code></br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#labelselector-v1-meta">
|
||||
Kubernetes meta/v1.LabelSelector
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>The labels to select by to find the Namespaces to create the ExternalSecrets in.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.ClusterExternalSecretStatus">ClusterExternalSecretStatus
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecret">ClusterExternalSecret</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret.</p>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>type</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecretConditionType">
|
||||
ClusterExternalSecretConditionType
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>status</code></br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#conditionstatus-v1-core">
|
||||
Kubernetes core/v1.ConditionStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>externalSecretStatuses</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.ExternalSecretStatus">
|
||||
[]ExternalSecretStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.ClusterSecretStore">ClusterSecretStore
|
||||
</h3>
|
||||
<p>
|
||||
|
@ -1084,6 +1315,7 @@ string
|
|||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecretSpec">ClusterExternalSecretSpec</a>,
|
||||
<a href="#external-secrets.io/v1alpha1.ExternalSecret">ExternalSecret</a>)
|
||||
</p>
|
||||
<p>
|
||||
|
@ -1171,6 +1403,7 @@ If multiple entries are specified, the Secret keys are merged in the specified o
|
|||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#external-secrets.io/v1alpha1.ClusterExternalSecretStatus">ClusterExternalSecretStatus</a>,
|
||||
<a href="#external-secrets.io/v1alpha1.ExternalSecret">ExternalSecret</a>)
|
||||
</p>
|
||||
<p>
|
||||
|
@ -1486,6 +1719,95 @@ map[string]string
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.FakeProvider">FakeProvider
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#external-secrets.io/v1alpha1.SecretStoreProvider">SecretStoreProvider</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>FakeProvider configures a fake provider that returns static values</p>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>data</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.FakeProviderData">
|
||||
[]FakeProviderData
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.FakeProviderData">FakeProviderData
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#external-secrets.io/v1alpha1.FakeProvider">FakeProvider</a>)
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>key</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>value</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>valueMap</code></br>
|
||||
<em>
|
||||
map[string]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>version</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.GCPSMAuth">GCPSMAuth
|
||||
</h3>
|
||||
<p>
|
||||
|
@ -2310,6 +2632,20 @@ WebhookProvider
|
|||
<p>Webhook configures this store to sync secrets using a generic templated webhook</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>fake</code></br>
|
||||
<em>
|
||||
<a href="#external-secrets.io/v1alpha1.FakeProvider">
|
||||
FakeProvider
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Fake configures a store with static key/value pairs</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="external-secrets.io/v1alpha1.SecretStoreRef">SecretStoreRef
|
||||
|
|
|
@ -2,7 +2,7 @@ MAKEFLAGS += --warn-undefined-variables
|
|||
SHELL := /bin/bash
|
||||
.SHELLFLAGS := -euo pipefail -c
|
||||
|
||||
KIND_IMG = "kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6"
|
||||
KIND_IMG = "kindest/node:v1.23.3@sha256:0df8215895129c0d3221cda19847d1296c4f29ec93487339149333bd9d899e5a"
|
||||
BUILD_ARGS ?=
|
||||
|
||||
export E2E_IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets-e2e
|
||||
|
|
97
e2e/suite/aws/common.go
Normal file
97
e2e/suite/aws/common.go
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
)
|
||||
|
||||
const (
|
||||
WithReferencedIRSA = "with referenced IRSA"
|
||||
WithMountedIRSA = "with mounted IRSA"
|
||||
StaticCredentialsSecretName = "provider-secret"
|
||||
)
|
||||
|
||||
func ReferencedIRSAStoreName(f *framework.Framework) string {
|
||||
return "irsa-ref-" + f.Namespace.Name
|
||||
}
|
||||
|
||||
func MountedIRSAStoreName(f *framework.Framework) string {
|
||||
return "irsa-mounted-" + f.Namespace.Name
|
||||
}
|
||||
|
||||
func UseClusterSecretStore(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.ClusterSecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = ReferencedIRSAStoreName(tc.Framework)
|
||||
}
|
||||
|
||||
func UseMountedIRSAStore(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.SecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = MountedIRSAStoreName(tc.Framework)
|
||||
}
|
||||
|
||||
// StaticStore is namespaced and references
|
||||
// static credentials from a secret.
|
||||
func SetupStaticStore(f *framework.Framework, kid, sak, region string, serviceType esv1alpha1.AWSServiceType) {
|
||||
awsCreds := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: StaticCredentialsSecretName,
|
||||
Namespace: f.Namespace.Name,
|
||||
},
|
||||
StringData: map[string]string{
|
||||
"kid": kid,
|
||||
"sak": sak,
|
||||
},
|
||||
}
|
||||
err := f.CRClient.Create(context.Background(), awsCreds)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
secretStore := &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: f.Namespace.Name,
|
||||
Namespace: f.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: serviceType,
|
||||
Region: region,
|
||||
Auth: esv1alpha1.AWSAuth{
|
||||
SecretRef: &esv1alpha1.AWSAuthSecretRef{
|
||||
AccessKeyID: esmetav1.SecretKeySelector{
|
||||
Name: StaticCredentialsSecretName,
|
||||
Key: "kid",
|
||||
},
|
||||
SecretAccessKey: esmetav1.SecretKeySelector{
|
||||
Name: StaticCredentialsSecretName,
|
||||
Key: "sak",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = f.CRClient.Create(context.Background(), secretStore)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
45
e2e/suite/aws/parameterstore/parameterstore.go
Normal file
45
e2e/suite/aws/parameterstore/parameterstore.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[aws] ", Label("aws", "parameterstore"), func() {
|
||||
f := framework.New("eso-aws-ps")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
Entry(common.NestedJSONWithGJSON(f)),
|
||||
Entry(common.JSONDataFromSync(f)),
|
||||
Entry(common.JSONDataWithProperty(f)),
|
||||
Entry(common.JSONDataWithTemplate(f)),
|
||||
Entry(common.DockerJSONConfig(f)),
|
||||
Entry(common.DataPropertyDockerconfigJSON(f)),
|
||||
Entry(common.SSHKeySync(f)),
|
||||
Entry(common.SSHKeySyncDataProperty(f)),
|
||||
Entry(common.SyncWithoutTargetName(f)),
|
||||
Entry(common.JSONDataWithoutTargetName(f)),
|
||||
)
|
||||
})
|
85
e2e/suite/aws/parameterstore/parameterstore_managed.go
Normal file
85
e2e/suite/aws/parameterstore/parameterstore_managed.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/addon"
|
||||
awscommon "github.com/external-secrets/external-secrets/e2e/suite/aws"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
// here we use the global eso instance
|
||||
// that uses the service account in the default namespace
|
||||
// which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] IRSA via referenced service account", Label("aws", "parameterstore", "managed"), func() {
|
||||
f := framework.New("eso-aws-ps-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
// nolint
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SimpleDataSync, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataFromSync, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithProperty, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithTemplate, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.DockerJSONConfig, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySync, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SyncWithoutTargetName, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseClusterSecretStore),
|
||||
)
|
||||
})
|
||||
|
||||
// here we create a central eso instance in the default namespace
|
||||
// that mounts the service account which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] with mounted IRSA", Label("aws", "parameterstore", "managed"), func() {
|
||||
f := framework.New("eso-aws-ps-irsa-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
// each test case gets its own ESO instance
|
||||
BeforeEach(func() {
|
||||
f.Install(addon.NewESO(
|
||||
addon.WithControllerClass(f.BaseName),
|
||||
addon.WithServiceAccount(prov.ServiceAccountName),
|
||||
addon.WithReleaseName(f.Namespace.Name),
|
||||
addon.WithNamespace("default"),
|
||||
))
|
||||
})
|
||||
|
||||
// nolint
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SimpleDataSync, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataFromSync, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithProperty, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithTemplate, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.DockerJSONConfig, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySync, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SyncWithoutTargetName, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseMountedIRSAStore),
|
||||
)
|
||||
})
|
165
e2e/suite/aws/parameterstore/provider.go
Normal file
165
e2e/suite/aws/parameterstore/provider.go
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/log"
|
||||
common "github.com/external-secrets/external-secrets/e2e/suite/aws"
|
||||
)
|
||||
|
||||
type Provider struct {
|
||||
ServiceAccountName string
|
||||
ServiceAccountNamespace string
|
||||
|
||||
region string
|
||||
client *ssm.SSM
|
||||
framework *framework.Framework
|
||||
}
|
||||
|
||||
func NewProvider(f *framework.Framework, kid, sak, region, saName, saNamespace string) *Provider {
|
||||
sess, err := session.NewSessionWithOptions(session.Options{
|
||||
Config: aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials(kid, sak, ""),
|
||||
Region: aws.String(region),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
Fail(err.Error())
|
||||
}
|
||||
sm := ssm.New(sess)
|
||||
prov := &Provider{
|
||||
ServiceAccountName: saName,
|
||||
ServiceAccountNamespace: saNamespace,
|
||||
region: region,
|
||||
client: sm,
|
||||
framework: f,
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
common.SetupStaticStore(f, kid, sak, region, esv1alpha1.AWSServiceParameterStore)
|
||||
prov.SetupReferencedIRSAStore()
|
||||
prov.SetupMountedIRSAStore()
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
// Cleanup ClusterSecretStore
|
||||
err := prov.framework.CRClient.Delete(context.Background(), &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ReferencedIRSAStoreName(f),
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
return prov
|
||||
}
|
||||
|
||||
func NewFromEnv(f *framework.Framework) *Provider {
|
||||
kid := os.Getenv("AWS_ACCESS_KEY_ID")
|
||||
sak := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||
region := "eu-west-1"
|
||||
saName := os.Getenv("AWS_SA_NAME")
|
||||
saNamespace := os.Getenv("AWS_SA_NAMESPACE")
|
||||
return NewProvider(f, kid, sak, region, saName, saNamespace)
|
||||
}
|
||||
|
||||
// CreateSecret creates a secret at the provider.
|
||||
func (s *Provider) CreateSecret(key, val string) {
|
||||
_, err := s.client.PutParameter(&ssm.PutParameterInput{
|
||||
Name: aws.String(key),
|
||||
Value: aws.String(val),
|
||||
DataType: aws.String("text"),
|
||||
Type: aws.String("String"),
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
// DeleteSecret deletes a secret at the provider.
|
||||
func (s *Provider) DeleteSecret(key string) {
|
||||
_, err := s.client.DeleteParameter(&ssm.DeleteParameterInput{
|
||||
Name: aws.String(key),
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
// MountedIRSAStore is a SecretStore without auth config
|
||||
// ESO relies on the pod-mounted ServiceAccount when using this store.
|
||||
func (s *Provider) SetupMountedIRSAStore() {
|
||||
secretStore := &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.MountedIRSAStoreName(s.framework),
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: esv1alpha1.AWSServiceParameterStore,
|
||||
Region: s.region,
|
||||
Auth: esv1alpha1.AWSAuth{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err := s.framework.CRClient.Create(context.Background(), secretStore)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
// ReferncedIRSAStore is a ClusterStore
|
||||
// that references a (IRSA-) ServiceAccount in the default namespace.
|
||||
func (s *Provider) SetupReferencedIRSAStore() {
|
||||
log.Logf("creating IRSA ClusterSecretStore %s", s.framework.Namespace.Name)
|
||||
secretStore := &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ReferencedIRSAStoreName(s.framework),
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(context.Background(), s.framework.CRClient, secretStore, func() error {
|
||||
secretStore.Spec.Provider = &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: esv1alpha1.AWSServiceParameterStore,
|
||||
Region: s.region,
|
||||
Auth: esv1alpha1.AWSAuth{
|
||||
JWTAuth: &esv1alpha1.AWSJWTAuth{
|
||||
ServiceAccountRef: &esmetav1.ServiceAccountSelector{
|
||||
Name: s.ServiceAccountName,
|
||||
Namespace: &s.ServiceAccountNamespace,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
|
@ -29,7 +29,6 @@ import (
|
|||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
|
@ -37,24 +36,19 @@ import (
|
|||
esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/log"
|
||||
common "github.com/external-secrets/external-secrets/e2e/suite/aws"
|
||||
)
|
||||
|
||||
type SMProvider struct {
|
||||
type Provider struct {
|
||||
ServiceAccountName string
|
||||
ServiceAccountNamespace string
|
||||
|
||||
kid string
|
||||
sak string
|
||||
region string
|
||||
client *secretsmanager.SecretsManager
|
||||
framework *framework.Framework
|
||||
}
|
||||
|
||||
const (
|
||||
staticCredentialsSecretName = "provider-secret"
|
||||
)
|
||||
|
||||
func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace string) *SMProvider {
|
||||
func NewProvider(f *framework.Framework, kid, sak, region, saName, saNamespace string) *Provider {
|
||||
sess, err := session.NewSessionWithOptions(session.Options{
|
||||
Config: aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials(kid, sak, ""),
|
||||
|
@ -65,18 +59,16 @@ func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace
|
|||
Fail(err.Error())
|
||||
}
|
||||
sm := secretsmanager.New(sess)
|
||||
prov := &SMProvider{
|
||||
prov := &Provider{
|
||||
ServiceAccountName: saName,
|
||||
ServiceAccountNamespace: saNamespace,
|
||||
kid: kid,
|
||||
sak: sak,
|
||||
region: region,
|
||||
client: sm,
|
||||
framework: f,
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
prov.SetupStaticStore()
|
||||
common.SetupStaticStore(f, kid, sak, region, esv1alpha1.AWSServiceSecretsManager)
|
||||
prov.SetupReferencedIRSAStore()
|
||||
prov.SetupMountedIRSAStore()
|
||||
})
|
||||
|
@ -85,7 +77,7 @@ func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace
|
|||
// Cleanup ClusterSecretStore
|
||||
err := prov.framework.CRClient.Delete(context.Background(), &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: prov.ReferencedIRSAStoreName(),
|
||||
Name: common.ReferencedIRSAStoreName(f),
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
@ -94,17 +86,17 @@ func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace
|
|||
return prov
|
||||
}
|
||||
|
||||
func NewFromEnv(f *framework.Framework) *SMProvider {
|
||||
func NewFromEnv(f *framework.Framework) *Provider {
|
||||
kid := os.Getenv("AWS_ACCESS_KEY_ID")
|
||||
sak := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||
region := "eu-west-1"
|
||||
saName := os.Getenv("AWS_SA_NAME")
|
||||
saNamespace := os.Getenv("AWS_SA_NAMESPACE")
|
||||
return NewSMProvider(f, kid, sak, region, saName, saNamespace)
|
||||
return NewProvider(f, kid, sak, region, saName, saNamespace)
|
||||
}
|
||||
|
||||
// CreateSecret creates a secret at the provider.
|
||||
func (s *SMProvider) CreateSecret(key, val string) {
|
||||
func (s *Provider) CreateSecret(key, val string) {
|
||||
// we re-use some secret names throughout our test suite
|
||||
// due to the fact that there is a short delay before the secret is actually deleted
|
||||
// we have to retry creating the secret
|
||||
|
@ -129,7 +121,7 @@ func (s *SMProvider) CreateSecret(key, val string) {
|
|||
// DeleteSecret deletes a secret at the provider.
|
||||
// There may be a short delay between calling this function
|
||||
// and the removal of the secret on the provider side.
|
||||
func (s *SMProvider) DeleteSecret(key string) {
|
||||
func (s *Provider) DeleteSecret(key string) {
|
||||
log.Logf("deleting secret %s", key)
|
||||
_, err := s.client.DeleteSecret(&secretsmanager.DeleteSecretInput{
|
||||
SecretId: aws.String(key),
|
||||
|
@ -140,10 +132,10 @@ func (s *SMProvider) DeleteSecret(key string) {
|
|||
|
||||
// MountedIRSAStore is a SecretStore without auth config
|
||||
// ESO relies on the pod-mounted ServiceAccount when using this store.
|
||||
func (s *SMProvider) SetupMountedIRSAStore() {
|
||||
func (s *Provider) SetupMountedIRSAStore() {
|
||||
secretStore := &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.MountedIRSAStoreName(),
|
||||
Name: common.MountedIRSAStoreName(s.framework),
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
|
@ -160,17 +152,13 @@ func (s *SMProvider) SetupMountedIRSAStore() {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *SMProvider) MountedIRSAStoreName() string {
|
||||
return "irsa-mounted-" + s.framework.Namespace.Name
|
||||
}
|
||||
|
||||
// ReferncedIRSAStore is a ClusterStore
|
||||
// that references a (IRSA-) ServiceAccount in the default namespace.
|
||||
func (s *SMProvider) SetupReferencedIRSAStore() {
|
||||
func (s *Provider) SetupReferencedIRSAStore() {
|
||||
log.Logf("creating IRSA ClusterSecretStore %s", s.framework.Namespace.Name)
|
||||
secretStore := &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.ReferencedIRSAStoreName(),
|
||||
Name: common.ReferencedIRSAStoreName(s.framework),
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(context.Background(), s.framework.CRClient, secretStore, func() error {
|
||||
|
@ -192,53 +180,3 @@ func (s *SMProvider) SetupReferencedIRSAStore() {
|
|||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *SMProvider) ReferencedIRSAStoreName() string {
|
||||
return "irsa-ref-" + s.framework.Namespace.Name
|
||||
}
|
||||
|
||||
// StaticStore is namespaced and references
|
||||
// static credentials from a secret.
|
||||
func (s *SMProvider) SetupStaticStore() {
|
||||
awsCreds := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: staticCredentialsSecretName,
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
StringData: map[string]string{
|
||||
"kid": s.kid,
|
||||
"sak": s.sak,
|
||||
},
|
||||
}
|
||||
err := s.framework.CRClient.Create(context.Background(), awsCreds)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
secretStore := &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.framework.Namespace.Name,
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: esv1alpha1.AWSServiceSecretsManager,
|
||||
Region: s.region,
|
||||
Auth: esv1alpha1.AWSAuth{
|
||||
SecretRef: &esv1alpha1.AWSAuthSecretRef{
|
||||
AccessKeyID: esmetav1.SecretKeySelector{
|
||||
Name: staticCredentialsSecretName,
|
||||
Key: "kid",
|
||||
},
|
||||
SecretAccessKey: esmetav1.SecretKeySelector{
|
||||
Name: staticCredentialsSecretName,
|
||||
Key: "sak",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = s.framework.CRClient.Create(context.Background(), secretStore)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
85
e2e/suite/aws/secretsmanager/secretsmanager_managed.go
Normal file
85
e2e/suite/aws/secretsmanager/secretsmanager_managed.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/addon"
|
||||
awscommon "github.com/external-secrets/external-secrets/e2e/suite/aws"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
// here we use the global eso instance
|
||||
// that uses the service account in the default namespace
|
||||
// which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] IRSA via referenced service account", Label("aws", "secretsmanager", "managed"), func() {
|
||||
f := framework.New("eso-aws-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
// nolint
|
||||
DescribeTable("sync secretsmanager secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SimpleDataSync, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataFromSync, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithProperty, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithTemplate, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.DockerJSONConfig, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySync, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.SyncWithoutTargetName, awscommon.UseClusterSecretStore),
|
||||
framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseClusterSecretStore),
|
||||
)
|
||||
})
|
||||
|
||||
// here we create a central eso instance in the default namespace
|
||||
// that mounts the service account which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] with mounted IRSA", Label("aws", "secretsmanager", "managed"), func() {
|
||||
f := framework.New("eso-aws-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
// each test case gets its own ESO instance
|
||||
BeforeEach(func() {
|
||||
f.Install(addon.NewESO(
|
||||
addon.WithControllerClass(f.BaseName),
|
||||
addon.WithServiceAccount(prov.ServiceAccountName),
|
||||
addon.WithReleaseName(f.Namespace.Name),
|
||||
addon.WithNamespace("default"),
|
||||
))
|
||||
})
|
||||
|
||||
// nolint
|
||||
DescribeTable("sync secretsmanager secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SimpleDataSync, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataFromSync, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithProperty, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithTemplate, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.DockerJSONConfig, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySync, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.SyncWithoutTargetName, awscommon.UseMountedIRSAStore),
|
||||
framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseMountedIRSAStore),
|
||||
)
|
||||
})
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/addon"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
const (
|
||||
withReferencedIRSA = "with referenced IRSA"
|
||||
withMountedIRSA = "with mounted IRSA"
|
||||
)
|
||||
|
||||
// here we use the global eso instance
|
||||
// that uses the service account in the default namespace
|
||||
// which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] IRSA via referenced service account", Label("aws", "secretsmanager", "managed"), func() {
|
||||
f := framework.New("eso-aws-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(withReferencedIRSA, f, common.SimpleDataSync, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.NestedJSONWithGJSON, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataFromSync, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataWithProperty, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataWithTemplate, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.DockerJSONConfig, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.DataPropertyDockerconfigJSON, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.SSHKeySync, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.SSHKeySyncDataProperty, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.SyncWithoutTargetName, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataWithoutTargetName, useClusterSecretStore(prov)),
|
||||
)
|
||||
})
|
||||
|
||||
// here we create a central eso instance in the default namespace
|
||||
// that mounts the service account which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] with mounted IRSA", Label("aws", "secretsmanager", "managed"), func() {
|
||||
f := framework.New("eso-aws-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
// each test case gets its own ESO instance
|
||||
BeforeEach(func() {
|
||||
f.Install(addon.NewESO(
|
||||
addon.WithControllerClass(f.BaseName),
|
||||
addon.WithServiceAccount(prov.ServiceAccountName),
|
||||
addon.WithReleaseName(f.Namespace.Name),
|
||||
addon.WithNamespace("default"),
|
||||
))
|
||||
})
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(withMountedIRSA, f, common.SimpleDataSync, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.NestedJSONWithGJSON, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataFromSync, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataWithProperty, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataWithTemplate, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.DockerJSONConfig, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.DataPropertyDockerconfigJSON, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.SSHKeySync, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.SSHKeySyncDataProperty, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.SyncWithoutTargetName, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataWithoutTargetName, useMountedIRSAStore(prov)),
|
||||
)
|
||||
})
|
||||
|
||||
func useClusterSecretStore(prov *SMProvider) func(*framework.TestCase) {
|
||||
return func(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.ClusterSecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = prov.ReferencedIRSAStoreName()
|
||||
}
|
||||
}
|
||||
|
||||
func useMountedIRSAStore(prov *SMProvider) func(*framework.TestCase) {
|
||||
return func(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.SecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = prov.MountedIRSAStoreName()
|
||||
}
|
||||
}
|
66
e2e/suite/azure/azure_cert.go
Normal file
66
e2e/suite/azure/azure_cert.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
limitations under the License.
|
||||
*/
|
||||
package azure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
||||
// nolint
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
)
|
||||
|
||||
// azure keyvault type=cert should get a certificate from the api.
|
||||
var _ = Describe("[azure]", Label("azure", "keyvault", "cert"), func() {
|
||||
f := framework.New("eso-azure-certtype")
|
||||
prov := newFromEnv(f)
|
||||
var certBytes []byte
|
||||
var certName string
|
||||
|
||||
BeforeEach(func() {
|
||||
certName = fmt.Sprintf("%s-%s", f.Namespace.Name, "certtest")
|
||||
prov.CreateCertificate(certName)
|
||||
certBytes = prov.GetCertificate(certName)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
prov.DeleteCertificate(certName)
|
||||
})
|
||||
|
||||
ff := framework.TableFunc(f, prov)
|
||||
It("should sync keyvault objects with type=cert", func() {
|
||||
ff(func(tc *framework.TestCase) {
|
||||
secretKey := "azkv-cert"
|
||||
|
||||
tc.ExpectedSecret = &v1.Secret{
|
||||
Type: v1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
secretKey: certBytes,
|
||||
},
|
||||
}
|
||||
tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
|
||||
{
|
||||
SecretKey: secretKey,
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: "cert/" + certName,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
})
|
69
e2e/suite/azure/azure_key.go
Normal file
69
e2e/suite/azure/azure_key.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
limitations under the License.
|
||||
*/
|
||||
package azure
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/keyvault/keyvault"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
)
|
||||
|
||||
// azure keyvault type=key should retrieve a jwk from the api.
|
||||
var _ = Describe("[azure]", Label("azure", "keyvault", "key"), func() {
|
||||
f := framework.New("eso-azure-keytype")
|
||||
prov := newFromEnv(f)
|
||||
var jwk *keyvault.JSONWebKey
|
||||
var keyName string
|
||||
|
||||
BeforeEach(func() {
|
||||
keyName = fmt.Sprintf("%s-%s", f.Namespace.Name, "keytest")
|
||||
jwk = prov.CreateKey(keyName)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
prov.DeleteKey(keyName)
|
||||
})
|
||||
|
||||
ff := framework.TableFunc(f, prov)
|
||||
|
||||
It("should sync keyvault objects with type=key", func() {
|
||||
ff(func(tc *framework.TestCase) {
|
||||
secretKey := "azkv-key"
|
||||
keyBytes, _ := json.Marshal(jwk)
|
||||
|
||||
tc.ExpectedSecret = &v1.Secret{
|
||||
Type: v1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
secretKey: keyBytes,
|
||||
},
|
||||
}
|
||||
tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
|
||||
{
|
||||
SecretKey: secretKey,
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: "key/" + keyName,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
})
|
|
@ -21,7 +21,8 @@ import (
|
|||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[azure]", Label("azure", "keyvault"), func() {
|
||||
// keyvault type=secret should behave just like any other secret store.
|
||||
var _ = Describe("[azure]", Label("azure", "keyvault", "secret"), func() {
|
||||
f := framework.New("eso-azure")
|
||||
prov := newFromEnv(f)
|
||||
|
|
@ -15,16 +15,15 @@ package azure
|
|||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/keyvault/keyvault"
|
||||
kvauth "github.com/Azure/go-autorest/autorest/azure/auth"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
|
@ -100,6 +99,83 @@ func (s *azureProvider) DeleteSecret(key string) {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *azureProvider) CreateKey(key string) *keyvault.JSONWebKey {
|
||||
out, err := s.client.CreateKey(
|
||||
context.Background(),
|
||||
s.vaultURL,
|
||||
key,
|
||||
keyvault.KeyCreateParameters{
|
||||
Kty: keyvault.RSA,
|
||||
KeyAttributes: &keyvault.KeyAttributes{
|
||||
RecoveryLevel: keyvault.Purgeable,
|
||||
Enabled: utilpointer.BoolPtr(true),
|
||||
},
|
||||
},
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return out.Key
|
||||
}
|
||||
|
||||
func (s *azureProvider) DeleteKey(key string) {
|
||||
_, err := s.client.DeleteKey(context.Background(), s.vaultURL, key)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *azureProvider) CreateCertificate(key string) {
|
||||
_, err := s.client.CreateCertificate(
|
||||
context.Background(),
|
||||
s.vaultURL,
|
||||
key,
|
||||
keyvault.CertificateCreateParameters{
|
||||
CertificatePolicy: &keyvault.CertificatePolicy{
|
||||
X509CertificateProperties: &keyvault.X509CertificateProperties{
|
||||
Subject: utilpointer.String("CN=e2e.test"),
|
||||
ValidityInMonths: utilpointer.Int32(42),
|
||||
},
|
||||
IssuerParameters: &keyvault.IssuerParameters{
|
||||
Name: utilpointer.String("Self"),
|
||||
},
|
||||
Attributes: &keyvault.CertificateAttributes{
|
||||
RecoveryLevel: keyvault.Purgeable,
|
||||
Enabled: utilpointer.BoolPtr(true),
|
||||
},
|
||||
},
|
||||
CertificateAttributes: &keyvault.CertificateAttributes{
|
||||
RecoveryLevel: keyvault.Purgeable,
|
||||
Enabled: utilpointer.BoolPtr(true),
|
||||
},
|
||||
},
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *azureProvider) GetCertificate(key string) []byte {
|
||||
attempts := 20
|
||||
for {
|
||||
out, err := s.client.GetCertificate(
|
||||
context.Background(),
|
||||
s.vaultURL,
|
||||
key,
|
||||
"",
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
if out.Cer != nil {
|
||||
return *out.Cer
|
||||
}
|
||||
|
||||
attempts--
|
||||
if attempts <= 0 {
|
||||
Fail("failed fetching azkv certificate")
|
||||
}
|
||||
<-time.After(time.Second * 5)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *azureProvider) DeleteCertificate(key string) {
|
||||
_, err := s.client.DeleteCertificate(context.Background(), s.vaultURL, key)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *azureProvider) CreateSecretStore() {
|
||||
azureCreds := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
|
|
@ -16,7 +16,8 @@ package suite
|
|||
import (
|
||||
|
||||
// import different e2e test suites.
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/aws"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/aws/parameterstore"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/aws/secretsmanager"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/azure"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/gcp"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/vault"
|
||||
|
|
29
go.mod
29
go.mod
|
@ -33,7 +33,7 @@ replace (
|
|||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.99.0
|
||||
cloud.google.com/go v0.100.2 // indirect
|
||||
cloud.google.com/go/secretmanager v1.0.0
|
||||
github.com/Azure/azure-sdk-for-go v61.1.0+incompatible
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.7
|
||||
|
@ -45,33 +45,33 @@ require (
|
|||
github.com/PaesslerAG/jsonpath v0.1.1
|
||||
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0
|
||||
github.com/akeylesslabs/akeyless-go-cloud-id v0.3.2
|
||||
github.com/akeylesslabs/akeyless-go/v2 v2.15.24
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1458
|
||||
github.com/akeylesslabs/akeyless-go/v2 v2.15.25
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1473
|
||||
github.com/aws/aws-sdk-go v1.38.6
|
||||
github.com/crossplane/crossplane-runtime v0.15.1
|
||||
github.com/go-logr/logr v1.2.2
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0
|
||||
github.com/google/go-cmp v0.5.7
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/googleapis/gax-go v1.0.3
|
||||
github.com/googleapis/gax-go/v2 v2.1.1
|
||||
github.com/hashicorp/vault/api v1.3.1
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/lestrrat-go/jwx v1.2.1
|
||||
github.com/onsi/ginkgo/v2 v2.0.0
|
||||
github.com/onsi/ginkgo/v2 v2.1.1
|
||||
github.com/onsi/gomega v1.17.0
|
||||
github.com/oracle/oci-go-sdk/v45 v45.2.0
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tidwall/gjson v1.12.1
|
||||
github.com/xanzy/go-gitlab v0.50.1
|
||||
github.com/xanzy/go-gitlab v0.54.3
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20210809082946-a97da516c588
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20210809100642-c13c40a429fa
|
||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
|
||||
go.uber.org/zap v1.20.0
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
google.golang.org/api v0.61.0
|
||||
google.golang.org/api v0.64.0
|
||||
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5
|
||||
google.golang.org/grpc v1.43.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
|
@ -85,7 +85,10 @@ require (
|
|||
software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78
|
||||
)
|
||||
|
||||
require cloud.google.com/go/iam v0.1.1
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v0.1.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
|
||||
|
@ -95,7 +98,6 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/PaesslerAG/gval v1.0.0 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
|
@ -103,16 +105,11 @@ require (
|
|||
github.com/aws/aws-sdk-go-v2 v0.23.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
||||
|
@ -131,10 +128,9 @@ require (
|
|||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
|
@ -194,8 +190,6 @@ require (
|
|||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||
|
@ -212,7 +206,6 @@ require (
|
|||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
honnef.co/go/tools v0.1.4 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.23.0 // indirect
|
||||
k8s.io/component-base v0.23.0 // indirect
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c // indirect
|
||||
|
|
59
go.sum
59
go.sum
|
@ -25,17 +25,23 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD
|
|||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||
cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY=
|
||||
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||
cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
|
||||
cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
|
||||
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v0.1.0 h1:rSUBvAyVwNJ5uQCKNJFMwPtTvJkfN38b6Pvb9zZoqJ8=
|
||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/iam v0.1.1 h1:4CapQyNFjiksks1/x7jsvsygFPhihslYk5GptIrlX68=
|
||||
cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
|
@ -78,7 +84,6 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
@ -107,15 +112,15 @@ github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 h1:+XfOU14S4bGuwyvCijJwhhBIj
|
|||
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8=
|
||||
github.com/akeylesslabs/akeyless-go-cloud-id v0.3.2 h1:1h4udX3Y5KgSG0m4Th2bHfaYxZB9fbngiij9PrKEp6c=
|
||||
github.com/akeylesslabs/akeyless-go-cloud-id v0.3.2/go.mod h1:ionnWiARf5TYoFGuHS7syh51/7lYosZejpZbnECFJcU=
|
||||
github.com/akeylesslabs/akeyless-go/v2 v2.15.24 h1:q++f8n4l66kSptlo9cxrYq8fGHg25GdjqOsw0vbKUAE=
|
||||
github.com/akeylesslabs/akeyless-go/v2 v2.15.24/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I=
|
||||
github.com/akeylesslabs/akeyless-go/v2 v2.15.25 h1:9iztd2fXVfj4b3LRsyvGNRheFoz8IFs/+K4GaAshZc4=
|
||||
github.com/akeylesslabs/akeyless-go/v2 v2.15.25/go.mod h1:uOdXD49NCCe4rexeSc2aBU5Qv4KZgJE6YlbtYalvb+I=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1458 h1:pMdm+s6k9yeAYJNqgZIpZcDBuh2SNR3Q137G9rpxDZc=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1458/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1473 h1:rUoiu7Duq0hr4mjlQWZMORKaCbNXaYvYN2HFJQt228E=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1473/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
|
@ -152,7 +157,6 @@ github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9cop
|
|||
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
|
||||
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
|
@ -170,12 +174,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
||||
|
@ -222,9 +224,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
|
|||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021 h1:fP+fF0up6oPY49OrjPrhIJ8yQfdIM85NXMLkMg1EXVs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
|
@ -340,7 +340,6 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er
|
|||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
|
@ -391,8 +390,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
|
@ -422,9 +421,6 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
|||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v1.0.3 h1:9dMLqhaibYONnDRcnHdUs9P8Mw64jLlZTYlDe3leBtQ=
|
||||
github.com/googleapis/gax-go v1.0.3/go.mod h1:QyXYajJFdARxGzjwUfbDFIse7Spkw81SJ4LrBJXtlQ8=
|
||||
github.com/googleapis/gax-go/v2 v2.0.2/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
|
@ -682,8 +678,8 @@ github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvw
|
|||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.1.1 h1:LCnPB85AvFNr91s0B2aDzEiiIg6MUwLYbryC1NSlWi8=
|
||||
github.com/onsi/ginkgo/v2 v2.1.1/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
|
@ -814,8 +810,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1
|
|||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/xanzy/go-gitlab v0.50.1 h1:eH1G0/ZV1j81rhGrtbcePjbM5Ern7mPA4Xjt+yE+2PQ=
|
||||
github.com/xanzy/go-gitlab v0.50.1/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
|
||||
github.com/xanzy/go-gitlab v0.54.3 h1:fPfZ3Jcu5dPc3xyIYtAALZsEgoyKNFNuULD+TdJ7Zvk=
|
||||
github.com/xanzy/go-gitlab v0.54.3/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||
|
@ -904,7 +900,6 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y
|
|||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190221220918-438050ddec5e/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
|
@ -914,11 +909,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 h1:FR+oGxGfbQu1d+jglI3rCkjAjUnhRSZcUxr+DqlDLNo=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
@ -930,7 +922,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
|||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
|
@ -1109,6 +1100,8 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
|
@ -1135,7 +1128,6 @@ golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -1243,8 +1235,10 @@ google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6
|
|||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||
google.golang.org/api v0.61.0 h1:TXXKS1slM3b2bZNJwD5DV/Tp6/M2cLzLOLh9PjDhrw8=
|
||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
||||
google.golang.org/api v0.64.0 h1:l3pi8ncrQgB9+ncFw3A716L8lWujnXniBYbxWqqy6tE=
|
||||
google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
@ -1319,10 +1313,13 @@ google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ6
|
|||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5 h1:zzNejm+EgrbLfDZ6lu9Uud2IVvHySPl8vQzf04laR5Q=
|
||||
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
@ -1348,6 +1345,7 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
|
|||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||
google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
|
||||
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
|
@ -1413,7 +1411,6 @@ gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
|||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 h1:tmXTu+dfa+d9Evp8NpJdgOy6+rt8/x4yG7qPBrtNfLY=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@ -1421,8 +1418,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.1.4 h1:SadWOkti5uVN1FAMgxn165+Mw00fuQKyk4Gyn/inxNQ=
|
||||
honnef.co/go/tools v0.1.4/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
k8s.io/api v0.23.0 h1:WrL1gb73VSC8obi8cuYETJGXEoFNEh3LU0Pt+Sokgro=
|
||||
k8s.io/api v0.23.0/go.mod h1:8wmDdLBHBNxtOIytwLstXt5E9PddnZb0GaMcqsvDBpg=
|
||||
k8s.io/apiextensions-apiserver v0.23.0 h1:uii8BYmHYiT2ZTAJxmvc3X8UhNYMxl2A0z0Xq3Pm+WY=
|
||||
|
|
|
@ -61,6 +61,7 @@ nav:
|
|||
- Oracle:
|
||||
- Oracle Vault: provider-oracle-vault.md
|
||||
- Webhook: provider-webhook.md
|
||||
- Fake: provider-fake.md
|
||||
- References:
|
||||
- API specification: spec.md
|
||||
- Contributing:
|
||||
|
|
|
@ -64,9 +64,7 @@ func (r *Reconciler) applyTemplate(ctx context.Context, es *esv1alpha1.ExternalS
|
|||
// if no data was provided by template fallback
|
||||
// to value from the provider
|
||||
if len(es.Spec.Target.Template.Data) == 0 {
|
||||
for k, v := range dataMap {
|
||||
secret.Data[k] = v
|
||||
}
|
||||
secret.Data = dataMap
|
||||
}
|
||||
secret.Annotations[esv1alpha1.AnnotationDataHash] = utils.ObjectHash(secret.Data)
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ import (
|
|||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/fake"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/schema"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/testing/fake"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -654,6 +654,85 @@ var _ = Describe("ExternalSecret controller", func() {
|
|||
}
|
||||
}
|
||||
|
||||
// when a provider secret was deleted it must be deleted from
|
||||
// the secret aswell
|
||||
refreshSecretValueMap := func(tc *testCase) {
|
||||
fakeProvider.WithGetSecretMap(map[string][]byte{
|
||||
"foo": []byte("1111"),
|
||||
"bar": []byte("2222"),
|
||||
}, nil)
|
||||
tc.externalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{}
|
||||
tc.externalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
{
|
||||
Key: remoteKey,
|
||||
},
|
||||
}
|
||||
tc.externalSecret.Spec.RefreshInterval = &metav1.Duration{Duration: time.Second}
|
||||
tc.checkSecret = func(es *esv1alpha1.ExternalSecret, secret *v1.Secret) {
|
||||
// check values
|
||||
Expect(string(secret.Data["foo"])).To(Equal("1111"))
|
||||
Expect(string(secret.Data["bar"])).To(Equal("2222"))
|
||||
|
||||
// update provider secret
|
||||
sec := &v1.Secret{}
|
||||
fakeProvider.WithGetSecretMap(map[string][]byte{
|
||||
"foo": []byte("1111"),
|
||||
}, nil)
|
||||
secretLookupKey := types.NamespacedName{
|
||||
Name: ExternalSecretTargetSecretName,
|
||||
Namespace: ExternalSecretNamespace,
|
||||
}
|
||||
Eventually(func() bool {
|
||||
err := k8sClient.Get(context.Background(), secretLookupKey, sec)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return string(sec.Data["foo"]) == "1111" &&
|
||||
sec.Data["bar"] == nil // must not be defined, it was deleted
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
}
|
||||
}
|
||||
|
||||
// when a provider secret was deleted it must be deleted from
|
||||
// the secret aswell when using a template
|
||||
refreshSecretValueMapTemplate := func(tc *testCase) {
|
||||
fakeProvider.WithGetSecretMap(map[string][]byte{
|
||||
"foo": []byte("1111"),
|
||||
"bar": []byte("2222"),
|
||||
}, nil)
|
||||
tc.externalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{}
|
||||
tc.externalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{}
|
||||
tc.externalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
{
|
||||
Key: remoteKey,
|
||||
},
|
||||
}
|
||||
tc.externalSecret.Spec.RefreshInterval = &metav1.Duration{Duration: time.Second}
|
||||
tc.checkSecret = func(es *esv1alpha1.ExternalSecret, secret *v1.Secret) {
|
||||
// check values
|
||||
Expect(string(secret.Data["foo"])).To(Equal("1111"))
|
||||
Expect(string(secret.Data["bar"])).To(Equal("2222"))
|
||||
|
||||
// update provider secret
|
||||
sec := &v1.Secret{}
|
||||
fakeProvider.WithGetSecretMap(map[string][]byte{
|
||||
"foo": []byte("1111"),
|
||||
}, nil)
|
||||
secretLookupKey := types.NamespacedName{
|
||||
Name: ExternalSecretTargetSecretName,
|
||||
Namespace: ExternalSecretNamespace,
|
||||
}
|
||||
Eventually(func() bool {
|
||||
err := k8sClient.Get(context.Background(), secretLookupKey, sec)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return string(sec.Data["foo"]) == "1111" &&
|
||||
sec.Data["bar"] == nil // must not be defined, it was deleted
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
}
|
||||
}
|
||||
|
||||
refreshintervalZero := func(tc *testCase) {
|
||||
const targetProp = "targetProperty"
|
||||
const secretVal = "someValue"
|
||||
|
@ -971,6 +1050,8 @@ var _ = Describe("ExternalSecret controller", func() {
|
|||
Entry("should refresh secret from template", refreshWithTemplate),
|
||||
Entry("should be able to use only metadata from template", onlyMetadataFromTemplate),
|
||||
Entry("should refresh secret value when provider secret changes", refreshSecretValue),
|
||||
Entry("should refresh secret map when provider secret changes", refreshSecretValueMap),
|
||||
Entry("should refresh secret map when provider secret changes when using a template", refreshSecretValueMapTemplate),
|
||||
Entry("should not refresh secret value when provider secret changes but refreshInterval is zero", refreshintervalZero),
|
||||
Entry("should fetch secret using dataFrom", syncWithDataFrom),
|
||||
Entry("should fetch secret using dataFrom and a template", syncWithDataFromTemplate),
|
||||
|
|
|
@ -16,6 +16,7 @@ package externalsecret
|
|||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/metrics"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
|
@ -50,6 +51,62 @@ var (
|
|||
|
||||
// updateExternalSecretCondition updates the ExternalSecret conditions.
|
||||
func updateExternalSecretCondition(es *esv1alpha1.ExternalSecret, condition *esv1alpha1.ExternalSecretStatusCondition, value float64) {
|
||||
switch condition.Type {
|
||||
case esv1alpha1.ExternalSecretDeleted:
|
||||
// Remove condition=Ready metrics when the object gets deleted.
|
||||
externalSecretCondition.Delete(prometheus.Labels{
|
||||
"name": es.Name,
|
||||
"namespace": es.Namespace,
|
||||
"condition": string(esv1alpha1.ExternalSecretReady),
|
||||
"status": string(v1.ConditionFalse),
|
||||
})
|
||||
externalSecretCondition.Delete(prometheus.Labels{
|
||||
"name": es.Name,
|
||||
"namespace": es.Namespace,
|
||||
"condition": string(esv1alpha1.ExternalSecretReady),
|
||||
"status": string(v1.ConditionTrue),
|
||||
})
|
||||
|
||||
case esv1alpha1.ExternalSecretReady:
|
||||
// Remove condition=Deleted metrics when the object gets ready.
|
||||
externalSecretCondition.Delete(prometheus.Labels{
|
||||
"name": es.Name,
|
||||
"namespace": es.Namespace,
|
||||
"condition": string(esv1alpha1.ExternalSecretDeleted),
|
||||
"status": string(v1.ConditionFalse),
|
||||
})
|
||||
externalSecretCondition.Delete(prometheus.Labels{
|
||||
"name": es.Name,
|
||||
"namespace": es.Namespace,
|
||||
"condition": string(esv1alpha1.ExternalSecretDeleted),
|
||||
"status": string(v1.ConditionTrue),
|
||||
})
|
||||
// Toggle opposite Status to 0
|
||||
switch condition.Status {
|
||||
case v1.ConditionFalse:
|
||||
externalSecretCondition.With(prometheus.Labels{
|
||||
"name": es.Name,
|
||||
"namespace": es.Namespace,
|
||||
"condition": string(esv1alpha1.ExternalSecretReady),
|
||||
"status": string(v1.ConditionTrue),
|
||||
}).Set(0)
|
||||
case v1.ConditionTrue:
|
||||
externalSecretCondition.With(prometheus.Labels{
|
||||
"name": es.Name,
|
||||
"namespace": es.Namespace,
|
||||
"condition": string(esv1alpha1.ExternalSecretReady),
|
||||
"status": string(v1.ConditionFalse),
|
||||
}).Set(0)
|
||||
case v1.ConditionUnknown:
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
externalSecretCondition.With(prometheus.Labels{
|
||||
"name": es.Name,
|
||||
"namespace": es.Namespace,
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
package externalsecret
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -40,6 +41,7 @@ import (
|
|||
var cfg *rest.Config
|
||||
var k8sClient client.Client
|
||||
var testEnv *envtest.Environment
|
||||
var cancel context.CancelFunc
|
||||
|
||||
func TestAPIs(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
|
@ -56,6 +58,9 @@ var _ = BeforeSuite(func() {
|
|||
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "deploy", "crds")},
|
||||
}
|
||||
|
||||
var ctx context.Context
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
|
||||
var err error
|
||||
cfg, err = testEnv.Start()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
@ -87,12 +92,13 @@ var _ = BeforeSuite(func() {
|
|||
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(k8sManager.Start(ctrl.SetupSignalHandler())).ToNot(HaveOccurred())
|
||||
Expect(k8sManager.Start(ctx)).ToNot(HaveOccurred())
|
||||
}()
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
By("tearing down the test environment")
|
||||
cancel() // stop manager
|
||||
err := testEnv.Stop()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
|
|
@ -16,6 +16,7 @@ package fake
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
|
@ -24,80 +25,72 @@ import (
|
|||
"github.com/external-secrets/external-secrets/pkg/provider/schema"
|
||||
)
|
||||
|
||||
var _ provider.Provider = &Client{}
|
||||
var (
|
||||
errNotFound = fmt.Errorf("secret value not found")
|
||||
errMissingStore = fmt.Errorf("missing store provider")
|
||||
errMissingFakeProvider = fmt.Errorf("missing store provider fake")
|
||||
)
|
||||
|
||||
// Client is a fake client for testing.
|
||||
type Client struct {
|
||||
NewFn func(context.Context, esv1alpha1.GenericStore, client.Client,
|
||||
string) (provider.SecretsClient, error)
|
||||
GetSecretFn func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error)
|
||||
GetSecretMapFn func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error)
|
||||
type Provider struct {
|
||||
config *esv1alpha1.FakeProvider
|
||||
}
|
||||
|
||||
// New returns a fake provider/client.
|
||||
func New() *Client {
|
||||
v := &Client{
|
||||
GetSecretFn: func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
return nil, nil
|
||||
},
|
||||
GetSecretMapFn: func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
v.NewFn = func(context.Context, esv1alpha1.GenericStore, client.Client, string) (provider.SecretsClient, error) {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// RegisterAs registers the fake client in the schema.
|
||||
func (v *Client) RegisterAs(provider *esv1alpha1.SecretStoreProvider) {
|
||||
schema.ForceRegister(v, provider)
|
||||
}
|
||||
|
||||
// GetSecret implements the provider.Provider interface.
|
||||
func (v *Client) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
return v.GetSecretFn(ctx, ref)
|
||||
}
|
||||
|
||||
// WithGetSecret wraps secret data returned by this provider.
|
||||
func (v *Client) WithGetSecret(secData []byte, err error) *Client {
|
||||
v.GetSecretFn = func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
return secData, err
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// GetSecretMap imeplements the provider.Provider interface.
|
||||
func (v *Client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
return v.GetSecretMapFn(ctx, ref)
|
||||
}
|
||||
func (v *Client) Close(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithGetSecretMap wraps the secret data map returned by this fake provider.
|
||||
func (v *Client) WithGetSecretMap(secData map[string][]byte, err error) *Client {
|
||||
v.GetSecretMapFn = func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
return secData, err
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// WithNew wraps the fake provider factory function.
|
||||
func (v *Client) WithNew(f func(context.Context, esv1alpha1.GenericStore, client.Client,
|
||||
string) (provider.SecretsClient, error)) *Client {
|
||||
v.NewFn = f
|
||||
return v
|
||||
}
|
||||
|
||||
// NewClient returns a new fake provider.
|
||||
func (v *Client) NewClient(ctx context.Context, store esv1alpha1.GenericStore, kube client.Client, namespace string) (provider.SecretsClient, error) {
|
||||
c, err := v.NewFn(ctx, store, kube, namespace)
|
||||
func (p *Provider) NewClient(ctx context.Context, store esv1alpha1.GenericStore, kube client.Client, namespace string) (provider.SecretsClient, error) {
|
||||
cfg, err := getProvider(store)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
return &Provider{
|
||||
config: cfg,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getProvider(store esv1alpha1.GenericStore) (*esv1alpha1.FakeProvider, error) {
|
||||
if store == nil {
|
||||
return nil, errMissingStore
|
||||
}
|
||||
spc := store.GetSpec()
|
||||
if spc == nil || spc.Provider == nil || spc.Provider.Fake == nil {
|
||||
return nil, errMissingFakeProvider
|
||||
}
|
||||
return spc.Provider.Fake, nil
|
||||
}
|
||||
|
||||
// GetSecret returns a single secret from the provider.
|
||||
func (p *Provider) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
for _, data := range p.config.Data {
|
||||
if data.Key == ref.Key && data.Version == ref.Version {
|
||||
return []byte(data.Value), nil
|
||||
}
|
||||
}
|
||||
return nil, errNotFound
|
||||
}
|
||||
|
||||
// GetSecretMap returns multiple k/v pairs from the provider.
|
||||
func (p *Provider) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
for _, data := range p.config.Data {
|
||||
if data.Key != ref.Key || data.Version != ref.Version || data.ValueMap == nil {
|
||||
continue
|
||||
}
|
||||
return convertMap(data.ValueMap), nil
|
||||
}
|
||||
return nil, errNotFound
|
||||
}
|
||||
|
||||
func convertMap(in map[string]string) map[string][]byte {
|
||||
m := make(map[string][]byte)
|
||||
for k, v := range in {
|
||||
m[k] = []byte(v)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (p *Provider) Close(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
schema.Register(&Provider{}, &esv1alpha1.SecretStoreProvider{
|
||||
Fake: &esv1alpha1.FakeProvider{},
|
||||
})
|
||||
}
|
||||
|
|
194
pkg/provider/fake/fake_test.go
Normal file
194
pkg/provider/fake/fake_test.go
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/onsi/gomega"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
p := &Provider{}
|
||||
gomega.RegisterTestingT(t)
|
||||
|
||||
// nil store
|
||||
_, err := p.NewClient(context.Background(), nil, nil, "")
|
||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
||||
|
||||
// missing provider
|
||||
_, err = p.NewClient(context.Background(), &esv1alpha1.SecretStore{}, nil, "")
|
||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
||||
}
|
||||
|
||||
func TestClose(t *testing.T) {
|
||||
p := &Provider{}
|
||||
gomega.RegisterTestingT(t)
|
||||
err := p.Close(context.TODO())
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
}
|
||||
|
||||
type testCase struct {
|
||||
name string
|
||||
input []esv1alpha1.FakeProviderData
|
||||
request esv1alpha1.ExternalSecretDataRemoteRef
|
||||
expValue string
|
||||
expErr string
|
||||
}
|
||||
|
||||
func TestGetSecret(t *testing.T) {
|
||||
gomega.RegisterTestingT(t)
|
||||
p := &Provider{}
|
||||
tbl := []testCase{
|
||||
{
|
||||
name: "return err when not found",
|
||||
input: []esv1alpha1.FakeProviderData{},
|
||||
request: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: "/foo",
|
||||
Version: "v2",
|
||||
},
|
||||
expErr: "secret value not found",
|
||||
},
|
||||
{
|
||||
name: "get correct value from multiple versions",
|
||||
input: []esv1alpha1.FakeProviderData{
|
||||
{
|
||||
Key: "/foo",
|
||||
Value: "bar2",
|
||||
Version: "v2",
|
||||
},
|
||||
{
|
||||
Key: "junk",
|
||||
Value: "xxxxx",
|
||||
},
|
||||
{
|
||||
Key: "/foo",
|
||||
Value: "bar1",
|
||||
Version: "v1",
|
||||
},
|
||||
},
|
||||
request: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: "/foo",
|
||||
Version: "v2",
|
||||
},
|
||||
expValue: "bar2",
|
||||
},
|
||||
}
|
||||
|
||||
for _, row := range tbl {
|
||||
t.Run(row.name, func(t *testing.T) {
|
||||
cl, err := p.NewClient(context.Background(), &esv1alpha1.SecretStore{
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
Fake: &esv1alpha1.FakeProvider{
|
||||
Data: row.input,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil, "")
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
out, err := cl.GetSecret(context.Background(), row.request)
|
||||
if row.expErr != "" {
|
||||
gomega.Expect(err).To(gomega.MatchError(row.expErr))
|
||||
} else {
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
}
|
||||
gomega.Expect(string(out)).To(gomega.Equal(row.expValue))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type testMapCase struct {
|
||||
name string
|
||||
input []esv1alpha1.FakeProviderData
|
||||
request esv1alpha1.ExternalSecretDataRemoteRef
|
||||
expValue map[string][]byte
|
||||
expErr string
|
||||
}
|
||||
|
||||
func TestGetSecretMap(t *testing.T) {
|
||||
gomega.RegisterTestingT(t)
|
||||
p := &Provider{}
|
||||
tbl := []testMapCase{
|
||||
{
|
||||
name: "return err when not found",
|
||||
input: []esv1alpha1.FakeProviderData{},
|
||||
request: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: "/foo",
|
||||
Version: "v2",
|
||||
},
|
||||
expErr: "secret value not found",
|
||||
},
|
||||
{
|
||||
name: "get correct value from multiple versions",
|
||||
input: []esv1alpha1.FakeProviderData{
|
||||
{
|
||||
Key: "junk",
|
||||
ValueMap: map[string]string{
|
||||
"junk": "ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: "/foo",
|
||||
ValueMap: map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "bang",
|
||||
},
|
||||
Version: "v1",
|
||||
},
|
||||
{
|
||||
Key: "/foo",
|
||||
ValueMap: map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "bang",
|
||||
},
|
||||
Version: "v2",
|
||||
},
|
||||
},
|
||||
request: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: "/foo",
|
||||
Version: "v2",
|
||||
},
|
||||
expValue: map[string][]byte{
|
||||
"foo": []byte("bar"),
|
||||
"baz": []byte("bang"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, row := range tbl {
|
||||
t.Run(row.name, func(t *testing.T) {
|
||||
cl, err := p.NewClient(context.Background(), &esv1alpha1.SecretStore{
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
Fake: &esv1alpha1.FakeProvider{
|
||||
Data: row.input,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil, "")
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
out, err := cl.GetSecretMap(context.Background(), row.request)
|
||||
if row.expErr != "" {
|
||||
gomega.Expect(err).To(gomega.MatchError(row.expErr))
|
||||
} else {
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
}
|
||||
gomega.Expect(out).To(gomega.Equal(row.expValue))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
grpc "github.com/googleapis/gax-go"
|
||||
grpc "github.com/googleapis/gax-go/v2"
|
||||
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
|
||||
)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
secretmanager "cloud.google.com/go/secretmanager/apiv1"
|
||||
"github.com/googleapis/gax-go"
|
||||
"github.com/googleapis/gax-go/v2"
|
||||
"github.com/tidwall/gjson"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
iam "cloud.google.com/go/iam/credentials/apiv1"
|
||||
secretmanager "cloud.google.com/go/secretmanager/apiv1"
|
||||
"github.com/googleapis/gax-go"
|
||||
"github.com/googleapis/gax-go/v2"
|
||||
"golang.org/x/oauth2"
|
||||
"google.golang.org/api/option"
|
||||
credentialspb "google.golang.org/genproto/googleapis/iam/credentials/v1"
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/googleapis/gax-go"
|
||||
"github.com/googleapis/gax-go/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/oauth2"
|
||||
credentialspb "google.golang.org/genproto/googleapis/iam/credentials/v1"
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
_ "github.com/external-secrets/external-secrets/pkg/provider/alibaba"
|
||||
_ "github.com/external-secrets/external-secrets/pkg/provider/aws"
|
||||
_ "github.com/external-secrets/external-secrets/pkg/provider/azure/keyvault"
|
||||
_ "github.com/external-secrets/external-secrets/pkg/provider/fake"
|
||||
_ "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
|
||||
_ "github.com/external-secrets/external-secrets/pkg/provider/gitlab"
|
||||
_ "github.com/external-secrets/external-secrets/pkg/provider/ibm"
|
||||
|
|
103
pkg/provider/testing/fake/fake.go
Normal file
103
pkg/provider/testing/fake/fake.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/schema"
|
||||
)
|
||||
|
||||
var _ provider.Provider = &Client{}
|
||||
|
||||
// Client is a fake client for testing.
|
||||
type Client struct {
|
||||
NewFn func(context.Context, esv1alpha1.GenericStore, client.Client,
|
||||
string) (provider.SecretsClient, error)
|
||||
GetSecretFn func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error)
|
||||
GetSecretMapFn func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error)
|
||||
}
|
||||
|
||||
// New returns a fake provider/client.
|
||||
func New() *Client {
|
||||
v := &Client{
|
||||
GetSecretFn: func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
return nil, nil
|
||||
},
|
||||
GetSecretMapFn: func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
v.NewFn = func(context.Context, esv1alpha1.GenericStore, client.Client, string) (provider.SecretsClient, error) {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// RegisterAs registers the fake client in the schema.
|
||||
func (v *Client) RegisterAs(provider *esv1alpha1.SecretStoreProvider) {
|
||||
schema.ForceRegister(v, provider)
|
||||
}
|
||||
|
||||
// GetSecret implements the provider.Provider interface.
|
||||
func (v *Client) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
return v.GetSecretFn(ctx, ref)
|
||||
}
|
||||
|
||||
// WithGetSecret wraps secret data returned by this provider.
|
||||
func (v *Client) WithGetSecret(secData []byte, err error) *Client {
|
||||
v.GetSecretFn = func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
return secData, err
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// GetSecretMap imeplements the provider.Provider interface.
|
||||
func (v *Client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
return v.GetSecretMapFn(ctx, ref)
|
||||
}
|
||||
func (v *Client) Close(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithGetSecretMap wraps the secret data map returned by this fake provider.
|
||||
func (v *Client) WithGetSecretMap(secData map[string][]byte, err error) *Client {
|
||||
v.GetSecretMapFn = func(context.Context, esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
return secData, err
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// WithNew wraps the fake provider factory function.
|
||||
func (v *Client) WithNew(f func(context.Context, esv1alpha1.GenericStore, client.Client,
|
||||
string) (provider.SecretsClient, error)) *Client {
|
||||
v.NewFn = f
|
||||
return v
|
||||
}
|
||||
|
||||
// NewClient returns a new fake provider.
|
||||
func (v *Client) NewClient(ctx context.Context, store esv1alpha1.GenericStore, kube client.Client, namespace string) (provider.SecretsClient, error) {
|
||||
c, err := v.NewFn(ctx, store, kube, namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
|
@ -298,7 +298,9 @@ func testGetSecret(tc testCase, t *testing.T, client provider.SecretsClient) {
|
|||
Key: tc.Args.Key,
|
||||
Version: tc.Args.Version,
|
||||
}
|
||||
secret, err := client.GetSecret(context.Background(), testRef)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
secret, err := client.GetSecret(ctx, testRef)
|
||||
errStr := ""
|
||||
if err != nil {
|
||||
errStr = err.Error()
|
||||
|
|
|
@ -37,6 +37,25 @@ resource "aws_iam_role" "eso-e2e-irsa" {
|
|||
"arn:aws:iam::aws:policy/SecretsManagerReadWrite"
|
||||
]
|
||||
|
||||
inline_policy {
|
||||
name = "aws_ssm_parameterstore"
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Action = [
|
||||
"ssm:GetParameter",
|
||||
"ssm:PutParameter",
|
||||
]
|
||||
Effect = "Allow"
|
||||
Resource = "*"
|
||||
},
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
resource "null_resource" "apply_sa" {
|
||||
|
|
Loading…
Reference in a new issue