mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-14 11:57:59 +00:00
✨ Kubernetes v1.24 upgrade (#1345)
* build(deps): bump sigs.k8s.io/controller-runtime from 0.11.2 to 0.12.3 Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.11.2 to 0.12.3. - [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/master/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.11.2...v0.12.3) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-runtime dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * feat: bump kubernetes 1.24 Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> * fix: backwards-compatible vault implementation Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> * feat: add audiences field to serviceAccountRef This will be used by aws, azure, gcp, kubernetes & vault providers in combination with TokenRequest API: it will _append_ audience claims to provider-specific audiences. Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> * feat: refactor kubernetes client to match provider/client interfaces the kubernetes provider mixed up provider and client interfaces which made it really hard to reason about. This commit separates into two structs, each implements one interface. The client struct fields have been renamed and annotated so their use and scope is clear. Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> * fix: deprecate expirationSeconds expirationSeconds is not needed because we generate a service account token on the fly for a single use. There will be no replacement for this. Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> * fix: rename token fetch audiences field Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> * fix: generate CRDs Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Moritz Johner <beller.moritz@googlemail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Moritz Johner <beller.moritz@googlemail.com>
This commit is contained in:
parent
2d20b5488e
commit
67fedc840e
39 changed files with 3193 additions and 1508 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -12,7 +12,7 @@ env:
|
|||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.42.1'
|
||||
KUBERNETES_VERSION: '1.23.x'
|
||||
KUBERNETES_VERSION: '1.24.x'
|
||||
DOCKER_BUILDX_VERSION: 'v0.4.2'
|
||||
|
||||
# Common users. We can't run a step 'if secrets.GHCR_USERNAME != ""' but we can run
|
||||
|
|
11
.github/workflows/dlc.yml
vendored
11
.github/workflows/dlc.yml
vendored
|
@ -14,17 +14,6 @@ on:
|
|||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.42.1'
|
||||
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
|
||||
# a step 'if env.GHCR_USERNAME' != ""', so we copy these to succinctly test whether
|
||||
# credentials have been provided before trying to run steps that need them.
|
||||
GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }}
|
||||
|
||||
# Sonar
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
|
||||
jobs:
|
||||
license-check:
|
||||
|
|
4
.github/workflows/e2e.yml
vendored
4
.github/workflows/e2e.yml
vendored
|
@ -10,8 +10,8 @@ env:
|
|||
GOLANGCI_VERSION: 'v1.33'
|
||||
GINKGO_VERSION: 'v2.1.4'
|
||||
DOCKER_BUILDX_VERSION: 'v0.4.2'
|
||||
KIND_VERSION: 'v0.11.1'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.2'
|
||||
|
||||
# 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
|
||||
|
|
|
@ -187,12 +187,14 @@ type VaultKubernetesServiceAccountTokenAuth struct {
|
|||
// Optional audiences field that will be used to request a temporary Kubernetes service
|
||||
// account token for the service account referenced by `serviceAccountRef`.
|
||||
// Defaults to a single audience `vault` it not specified.
|
||||
// Deprecated: use serviceAccountRef.Audiences instead
|
||||
// +optional
|
||||
Audiences *[]string `json:"audiences,omitempty"`
|
||||
|
||||
// Optional expiration time in seconds that will be used to request a temporary
|
||||
// Kubernetes service account token for the service account referenced by
|
||||
// `serviceAccountRef`.
|
||||
// Deprecated: this will be removed in the future.
|
||||
// Defaults to 10 minutes.
|
||||
// +optional
|
||||
ExpirationSeconds *int64 `json:"expirationSeconds,omitempty"`
|
||||
|
|
|
@ -37,4 +37,9 @@ type ServiceAccountSelector struct {
|
|||
// to the namespace of the referent.
|
||||
// +optional
|
||||
Namespace *string `json:"namespace,omitempty"`
|
||||
// Audience specifies the `aud` claim for the service account token
|
||||
// If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity
|
||||
// then this audiences will be appended to the list
|
||||
// +optional
|
||||
Audiences []string `json:"audiences,omitempty"`
|
||||
}
|
||||
|
|
|
@ -49,6 +49,11 @@ func (in *ServiceAccountSelector) DeepCopyInto(out *ServiceAccountSelector) {
|
|||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Audiences != nil {
|
||||
in, out := &in.Audiences, &out.Audiences
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountSelector.
|
||||
|
|
|
@ -229,6 +229,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -375,6 +384,15 @@ spec:
|
|||
description: ServiceAccountRef specified the service account
|
||||
that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the
|
||||
service account token If the service account uses a
|
||||
well-known annotation for e.g. IRSA or GCP Workload
|
||||
Identity then this audiences will be appended to the
|
||||
list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being
|
||||
referred to.
|
||||
|
@ -463,6 +481,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -637,6 +664,15 @@ spec:
|
|||
serviceAccount:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -934,6 +970,15 @@ spec:
|
|||
description: Service account field containing
|
||||
the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud`
|
||||
claim for the service account token If the
|
||||
service account uses a well-known annotation
|
||||
for e.g. IRSA or GCP Workload Identity then
|
||||
this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount
|
||||
resource being referred to.
|
||||
|
@ -1031,6 +1076,15 @@ spec:
|
|||
with Vault. If the service account selector is not
|
||||
supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -1596,6 +1650,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -1755,6 +1818,15 @@ spec:
|
|||
description: ServiceAccountRef specified the service account
|
||||
that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the
|
||||
service account token If the service account uses a
|
||||
well-known annotation for e.g. IRSA or GCP Workload
|
||||
Identity then this audiences will be appended to the
|
||||
list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being
|
||||
referred to.
|
||||
|
@ -1843,6 +1915,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -2030,6 +2111,15 @@ spec:
|
|||
description: points to a service account that should be
|
||||
used for authentication
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for
|
||||
the service account token If the service account
|
||||
uses a well-known annotation for e.g. IRSA or GCP
|
||||
Workload Identity then this audiences will be appended
|
||||
to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -2410,26 +2500,37 @@ spec:
|
|||
a token for with the `TokenRequest` API.
|
||||
properties:
|
||||
audiences:
|
||||
description: Optional audiences field that will
|
||||
description: 'Optional audiences field that will
|
||||
be used to request a temporary Kubernetes service
|
||||
account token for the service account referenced
|
||||
by `serviceAccountRef`. Defaults to a single
|
||||
audience `vault` it not specified.
|
||||
audience `vault` it not specified. Deprecated:
|
||||
use serviceAccountRef.Audiences instead'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
expirationSeconds:
|
||||
description: Optional expiration time in seconds
|
||||
description: 'Optional expiration time in seconds
|
||||
that will be used to request a temporary Kubernetes
|
||||
service account token for the service account
|
||||
referenced by `serviceAccountRef`. Defaults
|
||||
to 10 minutes.
|
||||
referenced by `serviceAccountRef`. Deprecated:
|
||||
this will be removed in the future. Defaults
|
||||
to 10 minutes.'
|
||||
format: int64
|
||||
type: integer
|
||||
serviceAccountRef:
|
||||
description: Service account field containing
|
||||
the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud`
|
||||
claim for the service account token If the
|
||||
service account uses a well-known annotation
|
||||
for e.g. IRSA or GCP Workload Identity then
|
||||
this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount
|
||||
resource being referred to.
|
||||
|
@ -2527,6 +2628,15 @@ spec:
|
|||
with Vault. If the service account selector is not
|
||||
supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
|
|
@ -229,6 +229,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -375,6 +384,15 @@ spec:
|
|||
description: ServiceAccountRef specified the service account
|
||||
that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the
|
||||
service account token If the service account uses a
|
||||
well-known annotation for e.g. IRSA or GCP Workload
|
||||
Identity then this audiences will be appended to the
|
||||
list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being
|
||||
referred to.
|
||||
|
@ -463,6 +481,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -637,6 +664,15 @@ spec:
|
|||
serviceAccount:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -934,6 +970,15 @@ spec:
|
|||
description: Service account field containing
|
||||
the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud`
|
||||
claim for the service account token If the
|
||||
service account uses a well-known annotation
|
||||
for e.g. IRSA or GCP Workload Identity then
|
||||
this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount
|
||||
resource being referred to.
|
||||
|
@ -1031,6 +1076,15 @@ spec:
|
|||
with Vault. If the service account selector is not
|
||||
supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -1596,6 +1650,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -1755,6 +1818,15 @@ spec:
|
|||
description: ServiceAccountRef specified the service account
|
||||
that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the
|
||||
service account token If the service account uses a
|
||||
well-known annotation for e.g. IRSA or GCP Workload
|
||||
Identity then this audiences will be appended to the
|
||||
list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being
|
||||
referred to.
|
||||
|
@ -1843,6 +1915,15 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -2030,6 +2111,15 @@ spec:
|
|||
description: points to a service account that should be
|
||||
used for authentication
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for
|
||||
the service account token If the service account
|
||||
uses a well-known annotation for e.g. IRSA or GCP
|
||||
Workload Identity then this audiences will be appended
|
||||
to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
@ -2410,26 +2500,37 @@ spec:
|
|||
a token for with the `TokenRequest` API.
|
||||
properties:
|
||||
audiences:
|
||||
description: Optional audiences field that will
|
||||
description: 'Optional audiences field that will
|
||||
be used to request a temporary Kubernetes service
|
||||
account token for the service account referenced
|
||||
by `serviceAccountRef`. Defaults to a single
|
||||
audience `vault` it not specified.
|
||||
audience `vault` it not specified. Deprecated:
|
||||
use serviceAccountRef.Audiences instead'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
expirationSeconds:
|
||||
description: Optional expiration time in seconds
|
||||
description: 'Optional expiration time in seconds
|
||||
that will be used to request a temporary Kubernetes
|
||||
service account token for the service account
|
||||
referenced by `serviceAccountRef`. Defaults
|
||||
to 10 minutes.
|
||||
referenced by `serviceAccountRef`. Deprecated:
|
||||
this will be removed in the future. Defaults
|
||||
to 10 minutes.'
|
||||
format: int64
|
||||
type: integer
|
||||
serviceAccountRef:
|
||||
description: Service account field containing
|
||||
the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud`
|
||||
claim for the service account token If the
|
||||
service account uses a well-known annotation
|
||||
for e.g. IRSA or GCP Workload Identity then
|
||||
this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount
|
||||
resource being referred to.
|
||||
|
@ -2527,6 +2628,15 @@ spec:
|
|||
with Vault. If the service account selector is not
|
||||
supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim
|
||||
for the service account token If the service
|
||||
account uses a well-known annotation for e.g.
|
||||
IRSA or GCP Workload Identity then this audiences
|
||||
will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource
|
||||
being referred to.
|
||||
|
|
|
@ -550,6 +550,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -654,6 +659,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -728,6 +738,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -856,6 +871,11 @@ spec:
|
|||
serviceAccount:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -1067,6 +1087,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: Service account field containing the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -1128,6 +1153,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -1556,6 +1586,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -1669,6 +1704,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -1743,6 +1783,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -1882,6 +1927,11 @@ spec:
|
|||
serviceAccount:
|
||||
description: points to a service account that should be used for authentication
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -2162,17 +2212,22 @@ spec:
|
|||
description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API.
|
||||
properties:
|
||||
audiences:
|
||||
description: Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified.
|
||||
description: 'Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. Deprecated: use serviceAccountRef.Audiences instead'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
expirationSeconds:
|
||||
description: Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to 10 minutes.
|
||||
description: 'Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Deprecated: this will be removed in the future. Defaults to 10 minutes.'
|
||||
format: int64
|
||||
type: integer
|
||||
serviceAccountRef:
|
||||
description: Service account field containing the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -2234,6 +2289,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -3279,6 +3339,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -3383,6 +3448,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -3457,6 +3527,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -3585,6 +3660,11 @@ spec:
|
|||
serviceAccount:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -3796,6 +3876,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: Service account field containing the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -3857,6 +3942,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -4285,6 +4375,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -4398,6 +4493,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -4472,6 +4572,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: A reference to a ServiceAccount resource.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -4611,6 +4716,11 @@ spec:
|
|||
serviceAccount:
|
||||
description: points to a service account that should be used for authentication
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -4891,17 +5001,22 @@ spec:
|
|||
description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API.
|
||||
properties:
|
||||
audiences:
|
||||
description: Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified.
|
||||
description: 'Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. Deprecated: use serviceAccountRef.Audiences instead'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
expirationSeconds:
|
||||
description: Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to 10 minutes.
|
||||
description: 'Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Deprecated: this will be removed in the future. Defaults to 10 minutes.'
|
||||
format: int64
|
||||
type: integer
|
||||
serviceAccountRef:
|
||||
description: Service account field containing the name of a kubernetes ServiceAccount.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
@ -4963,6 +5078,11 @@ spec:
|
|||
serviceAccountRef:
|
||||
description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead.
|
||||
properties:
|
||||
audiences:
|
||||
description: Audience specifies the `aud` claim for the service account token If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity then this audiences will be appended to the list
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: The name of the ServiceAccount resource being referred to.
|
||||
type: string
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
ARG GO_VERSION=1.17
|
||||
FROM golang:$GO_VERSION-buster as builder
|
||||
|
||||
ENV KUBECTL_VERSION="v1.23.6"
|
||||
ENV KUBECTL_VERSION="v1.24.3"
|
||||
ENV HELM_VERSION="v3.7.1"
|
||||
|
||||
RUN go get -u github.com/onsi/ginkgo/v2/ginkgo
|
||||
|
|
|
@ -2,7 +2,7 @@ MAKEFLAGS += --warn-undefined-variables
|
|||
SHELL := /bin/bash
|
||||
.SHELLFLAGS := -euo pipefail -c
|
||||
|
||||
KIND_IMG = "kindest/node:v1.23.3@sha256:0df8215895129c0d3221cda19847d1296c4f29ec93487339149333bd9d899e5a"
|
||||
KIND_IMG = "kindest/node:v1.24.2@sha256:1f0cee2282f43150b52dc7933183ed96abdcfc8d293f30ec07082495874876f1"
|
||||
BUILD_ARGS ?=
|
||||
|
||||
export E2E_IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets-e2e
|
||||
|
|
249
e2e/go.mod
Normal file
249
e2e/go.mod
Normal file
|
@ -0,0 +1,249 @@
|
|||
module github.com/external-secrets/external-secrets-e2e
|
||||
|
||||
go 1.17
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.23.0
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.0
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.23.0
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.23.0
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.23.0
|
||||
k8s.io/client-go => k8s.io/client-go v0.23.0
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.23.0
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.23.0
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.23.0
|
||||
k8s.io/component-base => k8s.io/component-base v0.23.0
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.23.0
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.23.0
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.23.0
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.23.0
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.23.0
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.23.0
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.23.0
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.23.0
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.23.0
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.23.0
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.0
|
||||
k8s.io/metrics => k8s.io/metrics v0.23.0
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.23.0
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.0
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.0
|
||||
sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.11.2
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/secretmanager v1.5.0
|
||||
github.com/Azure/azure-sdk-for-go v66.0.0+incompatible
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11
|
||||
github.com/akeylesslabs/akeyless-go-cloud-id v0.3.4
|
||||
github.com/akeylesslabs/akeyless-go/v2 v2.16.12
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704
|
||||
github.com/argoproj/argo-cd/v2 v2.4.8
|
||||
github.com/aws/aws-sdk-go v1.44.66
|
||||
github.com/external-secrets/external-secrets v0.5.8
|
||||
github.com/fluxcd/helm-controller/api v0.22.2
|
||||
github.com/fluxcd/pkg/apis/meta v0.14.2
|
||||
github.com/fluxcd/source-controller/api v0.25.11
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
||||
github.com/hashicorp/vault/api v1.7.2
|
||||
github.com/onsi/ginkgo/v2 v2.1.4
|
||||
github.com/onsi/gomega v1.20.0
|
||||
github.com/oracle/oci-go-sdk/v56 v56.1.0
|
||||
github.com/xanzy/go-gitlab v0.69.0
|
||||
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c
|
||||
google.golang.org/api v0.90.0
|
||||
google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9
|
||||
k8s.io/api v0.24.2
|
||||
k8s.io/apiextensions-apiserver v0.24.2
|
||||
k8s.io/apimachinery v0.24.2
|
||||
k8s.io/client-go v0.24.2
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
|
||||
sigs.k8s.io/controller-runtime v0.12.3
|
||||
software.sslmate.com/src/go-pkcs12 v0.2.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.102.0 // indirect
|
||||
cloud.google.com/go/compute v1.7.0 // indirect
|
||||
cloud.google.com/go/iam v0.3.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||
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/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
|
||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.17 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/argoproj/gitops-engine v0.7.0 // indirect
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bombsimon/logrusr/v2 v2.0.1 // indirect
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.0.4 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fatih/camelcase v1.0.0 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.4.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||
github.com/go-git/go-git/v5 v5.4.2 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/go-redis/cache/v8 v8.4.2 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.3 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
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/btree v1.0.1 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/google/go-github/v41 v41.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/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.1.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.3 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hashicorp/go-version v1.4.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.1-vault-3 // indirect
|
||||
github.com/hashicorp/vault/sdk v0.5.1 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.12.2 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/robfig/cron v1.2.0 // indirect
|
||||
github.com/russross/blackfriday v1.5.2 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b // indirect
|
||||
github.com/spf13/cobra v1.4.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/testify v1.8.0 // indirect
|
||||
github.com/tidwall/gjson v1.14.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/vmihailenco/go-tinylfu v0.2.1 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||
golang.org/x/exp v0.0.0-20210901193431-a062eea981d2 // indirect
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
||||
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/grpc v1.48.0 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 // indirect
|
||||
k8s.io/apiserver v0.23.1 // indirect
|
||||
k8s.io/cli-runtime v0.23.1 // indirect
|
||||
k8s.io/component-base v0.24.2 // indirect
|
||||
k8s.io/component-helpers v0.23.1 // indirect
|
||||
k8s.io/klog/v2 v2.60.1 // indirect
|
||||
k8s.io/kube-aggregator v0.23.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220310132336-3f90b8c54bbb // indirect
|
||||
k8s.io/kubectl v0.23.1 // indirect
|
||||
k8s.io/kubernetes v1.23.1 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.10.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
1829
e2e/go.sum
Normal file
1829
e2e/go.sum
Normal file
File diff suppressed because it is too large
Load diff
|
@ -91,7 +91,8 @@ vault write auth/myjwtk8s/role/external-secrets-operator \
|
|||
vault auth enable -path=mykubernetes kubernetes
|
||||
vault write auth/mykubernetes/config \
|
||||
kubernetes_host=https://kubernetes.default.svc.cluster.local \
|
||||
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
|
||||
issuer=https://kubernetes.default.svc.cluster.local
|
||||
|
||||
vault write auth/mykubernetes/role/external-secrets-operator \
|
||||
bound_service_account_names=* \
|
||||
|
|
|
@ -39,12 +39,6 @@ kubectl create clusterrolebinding service-account-issuer-discovery-binding \
|
|||
--clusterrole=system:service-account-issuer-discovery \
|
||||
--group=system:unauthenticated || true
|
||||
|
||||
echo -e "Waiting service account..."; \
|
||||
until kubectl get secret | grep -q -e ^external-secrets-e2e-token; do \
|
||||
echo -e "waiting for api token"; \
|
||||
sleep 3; \
|
||||
done
|
||||
|
||||
echo -e "Starting the e2e test pod ${E2E_IMAGE_REGISTRY}:${VERSION}"
|
||||
kubectl run --rm \
|
||||
--attach \
|
||||
|
|
141
go.mod
141
go.mod
|
@ -5,31 +5,31 @@ go 1.17
|
|||
replace (
|
||||
github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127
|
||||
github.com/go-test/deep => github.com/go-test/deep v1.0.4
|
||||
k8s.io/api => k8s.io/api v0.23.0
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.0
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.23.0
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.23.0
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.23.0
|
||||
k8s.io/client-go => k8s.io/client-go v0.23.0
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.23.0
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.23.0
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.23.0
|
||||
k8s.io/component-base => k8s.io/component-base v0.23.0
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.23.0
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.23.0
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.23.0
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.23.0
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.23.0
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.23.0
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.23.0
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.23.0
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.23.0
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.23.0
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.0
|
||||
k8s.io/metrics => k8s.io/metrics v0.23.0
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.23.0
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.0
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.0
|
||||
k8s.io/api => k8s.io/api v0.24.2
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.24.2
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.24.2
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.24.2
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.24.2
|
||||
k8s.io/client-go => k8s.io/client-go v0.24.2
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.24.2
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.24.2
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.24.2
|
||||
k8s.io/component-base => k8s.io/component-base v0.24.2
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.24.2
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.24.2
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.24.2
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.24.2
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.24.2
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.24.2
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.24.2
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.24.2
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.24.2
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.24.2
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.24.2
|
||||
k8s.io/metrics => k8s.io/metrics v0.24.2
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.24.2
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.24.2
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.24.2
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -54,7 +54,7 @@ require (
|
|||
github.com/crossplane/crossplane-runtime v0.17.0
|
||||
github.com/go-logr/logr v1.2.3
|
||||
github.com/go-test/deep v1.0.4 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/googleapis/gax-go/v2 v2.5.1
|
||||
|
@ -84,29 +84,21 @@ require (
|
|||
google.golang.org/grpc v1.48.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919
|
||||
k8s.io/api v0.24.0
|
||||
k8s.io/apiextensions-apiserver v0.24.1
|
||||
k8s.io/apimachinery v0.24.1
|
||||
k8s.io/client-go v0.23.5
|
||||
k8s.io/api v0.24.2
|
||||
k8s.io/apiextensions-apiserver v0.24.2
|
||||
k8s.io/apimachinery v0.24.2
|
||||
k8s.io/client-go v0.24.2
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
|
||||
sigs.k8s.io/controller-runtime v0.11.2
|
||||
sigs.k8s.io/controller-runtime v0.12.3
|
||||
sigs.k8s.io/controller-tools v0.9.2
|
||||
software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78
|
||||
)
|
||||
|
||||
require github.com/1Password/connect-sdk-go v1.5.0
|
||||
|
||||
require (
|
||||
github.com/argoproj/argo-cd/v2 v2.4.6
|
||||
github.com/fluxcd/helm-controller/api v0.22.2
|
||||
github.com/fluxcd/pkg/apis/meta v0.14.2
|
||||
github.com/fluxcd/source-controller/api v0.25.11
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
require sigs.k8s.io/yaml v1.3.0
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.7.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
|
@ -114,45 +106,24 @@ 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/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
|
||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.17 // indirect
|
||||
github.com/PaesslerAG/gval v1.0.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/argoproj/gitops-engine v0.7.0 // indirect
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bombsimon/logrusr/v2 v2.0.1 // indirect
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.0.4 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fatih/camelcase v1.0.0 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.4.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||
github.com/go-git/go-git/v5 v5.4.2 // indirect
|
||||
github.com/go-logr/zapr v1.2.0 // indirect
|
||||
github.com/go-openapi/errors v0.19.8 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
|
@ -161,27 +132,20 @@ require (
|
|||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-redis/cache/v8 v8.4.2 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.3 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/gobuffalo/flect v0.2.5 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/goccy/go-json v0.9.7 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
|
||||
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/btree v1.0.1 // indirect
|
||||
github.com/google/go-github/v41 v41.0.0 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // 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/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.1.0 // indirect
|
||||
|
@ -202,14 +166,9 @@ require (
|
|||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
|
||||
|
@ -217,7 +176,6 @@ require (
|
|||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.1 // indirect
|
||||
github.com/lestrrat-go/option v1.0.0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
|
@ -225,32 +183,22 @@ require (
|
|||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/robfig/cron v1.2.0 // indirect
|
||||
github.com/russross/blackfriday v1.5.2 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
|
@ -258,20 +206,12 @@ require (
|
|||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
|
||||
github.com/vmihailenco/go-tinylfu v0.2.1 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
|
||||
go.mongodb.org/mongo-driver v1.7.5 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20210901193431-a062eea981d2 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48 // indirect
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
|
@ -285,21 +225,12 @@ require (
|
|||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/apiserver v0.23.1 // indirect
|
||||
k8s.io/cli-runtime v0.23.1 // indirect
|
||||
k8s.io/component-base v0.23.5 // indirect
|
||||
k8s.io/component-helpers v0.23.1 // indirect
|
||||
k8s.io/component-base v0.24.2 // indirect
|
||||
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect
|
||||
k8s.io/klog v0.3.0 // indirect
|
||||
k8s.io/klog/v2 v2.60.1 // indirect
|
||||
k8s.io/kube-aggregator v0.23.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
|
||||
k8s.io/kubectl v0.23.1 // indirect
|
||||
k8s.io/kubernetes v1.23.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.10.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
)
|
||||
|
|
|
@ -194,7 +194,12 @@ func sessionFromServiceAccount(ctx context.Context, prov *esv1beta1.AWSProvider,
|
|||
if tokenAud == "" {
|
||||
tokenAud = defaultTokenAudience
|
||||
}
|
||||
jwtProv, err := jwtProvider(name, namespace, roleArn, tokenAud, prov.Region)
|
||||
audiences := []string{tokenAud}
|
||||
if len(prov.Auth.JWTAuth.ServiceAccountRef.Audiences) > 0 {
|
||||
audiences = append(audiences, prov.Auth.JWTAuth.ServiceAccountRef.Audiences...)
|
||||
}
|
||||
|
||||
jwtProv, err := jwtProvider(name, namespace, roleArn, audiences, prov.Region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -203,12 +208,12 @@ func sessionFromServiceAccount(ctx context.Context, prov *esv1beta1.AWSProvider,
|
|||
return credentials.NewCredentials(jwtProv), nil
|
||||
}
|
||||
|
||||
type jwtProviderFactory func(name, namespace, roleArn, aud, region string) (credentials.Provider, error)
|
||||
type jwtProviderFactory func(name, namespace, roleArn string, aud []string, region string) (credentials.Provider, error)
|
||||
|
||||
// DefaultJWTProvider returns a credentials.Provider that calls the AssumeRoleWithWebidentity
|
||||
// controller-runtime/client does not support TokenRequest or other subresource APIs
|
||||
// so we need to construct our own client and use it to fetch tokens.
|
||||
func DefaultJWTProvider(name, namespace, roleArn, aud, region string) (credentials.Provider, error) {
|
||||
func DefaultJWTProvider(name, namespace, roleArn string, aud []string, region string) (credentials.Provider, error) {
|
||||
cfg, err := ctrlcfg.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -233,7 +238,7 @@ func DefaultJWTProvider(name, namespace, roleArn, aud, region string) (credentia
|
|||
}
|
||||
tokenFetcher := &authTokenFetcher{
|
||||
Namespace: namespace,
|
||||
Audience: aud,
|
||||
Audiences: aud,
|
||||
ServiceAccount: name,
|
||||
k8sClient: clientset.CoreV1(),
|
||||
}
|
||||
|
|
|
@ -352,7 +352,7 @@ func TestNewSession(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
jwtProvider: func(name, namespace, roleArn, aud, region string) (credentials.Provider, error) {
|
||||
jwtProvider: func(name, namespace, roleArn string, aud []string, region string) (credentials.Provider, error) {
|
||||
assert.Equal(t, myServiceAccountKey, name)
|
||||
assert.Equal(t, otherNsName, namespace)
|
||||
assert.Equal(t, "my-sa-role", roleArn)
|
||||
|
|
|
@ -30,7 +30,7 @@ type authTokenFetcher struct {
|
|||
// Audience is the token aud claim
|
||||
// which is verified by the aws oidc provider
|
||||
// see: https://github.com/external-secrets/external-secrets/issues/1251#issuecomment-1161745849
|
||||
Audience string
|
||||
Audiences []string
|
||||
ServiceAccount string
|
||||
k8sClient corev1.CoreV1Interface
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func (p authTokenFetcher) FetchToken(ctx credentials.Context) ([]byte, error) {
|
|||
log.V(1).Info("fetching token", "ns", p.Namespace, "sa", p.ServiceAccount)
|
||||
tokRsp, err := p.k8sClient.ServiceAccounts(p.Namespace).CreateToken(ctx, p.ServiceAccount, &authv1.TokenRequest{
|
||||
Spec: authv1.TokenRequestSpec{
|
||||
Audiences: []string{p.Audience},
|
||||
Audiences: p.Audiences,
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -19,14 +19,14 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/aws/auth/fake"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/util/fake"
|
||||
)
|
||||
|
||||
func TestTokenFetcher(t *testing.T) {
|
||||
tf := &authTokenFetcher{
|
||||
ServiceAccount: "foobar",
|
||||
Namespace: "example",
|
||||
k8sClient: fake.NewCreateTokenMock("FAKETOKEN"),
|
||||
k8sClient: fake.NewCreateTokenMock().WithToken("FAKETOKEN"),
|
||||
}
|
||||
token, err := tf.FetchToken(context.Background())
|
||||
assert.Nil(t, err)
|
||||
|
|
|
@ -465,7 +465,11 @@ func (a *Azure) authorizerForWorkloadIdentity(ctx context.Context, tokenProvider
|
|||
if !ok {
|
||||
return nil, fmt.Errorf(errMissingSAAnnotation, annotationTenantID)
|
||||
}
|
||||
token, err := fetchSAToken(ctx, ns, a.provider.ServiceAccountRef.Name, a.kubeClient)
|
||||
audiences := []string{azureDefaultAudience}
|
||||
if len(a.provider.ServiceAccountRef.Audiences) > 0 {
|
||||
audiences = append(audiences, a.provider.ServiceAccountRef.Audiences...)
|
||||
}
|
||||
token, err := fetchSAToken(ctx, ns, a.provider.ServiceAccountRef.Name, audiences, a.kubeClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -476,10 +480,10 @@ func (a *Azure) authorizerForWorkloadIdentity(ctx context.Context, tokenProvider
|
|||
return autorest.NewBearerAuthorizer(tp), nil
|
||||
}
|
||||
|
||||
func fetchSAToken(ctx context.Context, ns, name string, kubeClient kcorev1.CoreV1Interface) (string, error) {
|
||||
func fetchSAToken(ctx context.Context, ns, name string, audiences []string, kubeClient kcorev1.CoreV1Interface) (string, error) {
|
||||
token, err := kubeClient.ServiceAccounts(ns).CreateToken(ctx, name, &authv1.TokenRequest{
|
||||
Spec: authv1.TokenRequestSpec{
|
||||
Audiences: []string{azureDefaultAudience},
|
||||
Audiences: audiences,
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -32,7 +32,7 @@ import (
|
|||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
awsauthfake "github.com/external-secrets/external-secrets/pkg/provider/aws/auth/fake"
|
||||
utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake"
|
||||
)
|
||||
|
||||
var vaultURL = "https://local.vault.url"
|
||||
|
@ -190,7 +190,7 @@ func TestGetAuthorizorForWorkloadIdentity(t *testing.T) {
|
|||
store: &store,
|
||||
namespace: namespace,
|
||||
crClient: k8sClient,
|
||||
kubeClient: awsauthfake.NewCreateTokenMock(saToken),
|
||||
kubeClient: utilfake.NewCreateTokenMock().WithToken(saToken),
|
||||
provider: store.Spec.Provider.AzureKV,
|
||||
}
|
||||
tokenProvider := func(ctx context.Context, token, clientID, tenantID, aadEndpoint, kvResource string) (adal.OAuthTokenProvider, error) {
|
||||
|
|
|
@ -73,7 +73,7 @@ type idBindTokenGenerator interface {
|
|||
|
||||
// interface to kubernetes serviceaccount token request API.
|
||||
type saTokenGenerator interface {
|
||||
Generate(context.Context, string, string, string) (*authenticationv1.TokenRequest, error)
|
||||
Generate(context.Context, []string, string, string) (*authenticationv1.TokenRequest, error)
|
||||
}
|
||||
|
||||
func newWorkloadIdentity(ctx context.Context) (*workloadIdentity, error) {
|
||||
|
@ -130,9 +130,13 @@ func (w *workloadIdentity) TokenSource(ctx context.Context, store esv1beta1.Gene
|
|||
wi.ClusterLocation,
|
||||
wi.ClusterName)
|
||||
idPool := fmt.Sprintf("%s.svc.id.goog", clusterProjectID)
|
||||
audiences := []string{idPool}
|
||||
if len(wi.ServiceAccountRef.Audiences) > 0 {
|
||||
audiences = append(audiences, wi.ServiceAccountRef.Audiences...)
|
||||
}
|
||||
gcpSA := sa.Annotations[gcpSAAnnotation]
|
||||
|
||||
resp, err := w.saTokenGenerator.Generate(ctx, idPool, saKey.Name, saKey.Namespace)
|
||||
resp, err := w.saTokenGenerator.Generate(ctx, audiences, saKey.Name, saKey.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(errFetchPodToken, err)
|
||||
}
|
||||
|
@ -182,7 +186,7 @@ type k8sSATokenGenerator struct {
|
|||
corev1 clientcorev1.CoreV1Interface
|
||||
}
|
||||
|
||||
func (g *k8sSATokenGenerator) Generate(ctx context.Context, idPool, name, namespace string) (*authenticationv1.TokenRequest, error) {
|
||||
func (g *k8sSATokenGenerator) Generate(ctx context.Context, audiences []string, name, namespace string) (*authenticationv1.TokenRequest, error) {
|
||||
// Request a serviceaccount token for the pod
|
||||
ttl := int64((15 * time.Minute).Seconds())
|
||||
return g.corev1.
|
||||
|
@ -191,7 +195,7 @@ func (g *k8sSATokenGenerator) Generate(ctx context.Context, idPool, name, namesp
|
|||
&authenticationv1.TokenRequest{
|
||||
Spec: authenticationv1.TokenRequestSpec{
|
||||
ExpirationSeconds: &ttl,
|
||||
Audiences: []string{idPool},
|
||||
Audiences: audiences,
|
||||
},
|
||||
},
|
||||
metav1.CreateOptions{},
|
||||
|
|
|
@ -43,7 +43,7 @@ type workloadIdentityTest struct {
|
|||
expErr string
|
||||
genAccessToken func(context.Context, *credentialspb.GenerateAccessTokenRequest, ...gax.CallOption) (*credentialspb.GenerateAccessTokenResponse, error)
|
||||
genIDBindToken func(ctx context.Context, client *http.Client, k8sToken, idPool, idProvider string) (*oauth2.Token, error)
|
||||
genSAToken func(c context.Context, s1, s2, s3 string) (*authv1.TokenRequest, error)
|
||||
genSAToken func(c context.Context, s1 []string, s2, s3 string) (*authv1.TokenRequest, error)
|
||||
store esv1beta1.GenericStore
|
||||
kubeObjects []client.Object
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ func TestSATokenGen(t *testing.T) {
|
|||
g := &k8sSATokenGenerator{
|
||||
corev1: corev1,
|
||||
}
|
||||
token, err := g.Generate(context.Background(), "my-fake-audience", "bar", "default")
|
||||
token, err := g.Generate(context.Background(), []string{"my-fake-audience"}, "bar", "default")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, token.Status.Token, defaultSAToken)
|
||||
assert.Equal(t, token.Spec.Audiences[0], "my-fake-audience")
|
||||
|
@ -270,7 +270,7 @@ func defaultTestCase(name string) *workloadIdentityTest {
|
|||
AccessToken: defaultIDBindToken,
|
||||
}, nil
|
||||
},
|
||||
genSAToken: func(c context.Context, s1, s2, s3 string) (*authv1.TokenRequest, error) {
|
||||
genSAToken: func(c context.Context, s1 []string, s2, s3 string) (*authv1.TokenRequest, error) {
|
||||
return &authv1.TokenRequest{
|
||||
Status: authv1.TokenRequestStatus{
|
||||
Token: defaultSAToken,
|
||||
|
@ -402,10 +402,10 @@ func (f *fakeIAMClient) Close() error {
|
|||
|
||||
// fake SA Token Generator.
|
||||
type fakeSATokenGen struct {
|
||||
GenerateFunc func(context.Context, string, string, string) (*authv1.TokenRequest, error)
|
||||
GenerateFunc func(context.Context, []string, string, string) (*authv1.TokenRequest, error)
|
||||
}
|
||||
|
||||
func (f *fakeSATokenGen) Generate(ctx context.Context, idPool, namespace, name string) (*authv1.TokenRequest, error) {
|
||||
func (f *fakeSATokenGen) Generate(ctx context.Context, idPool []string, namespace, name string) (*authv1.TokenRequest, error) {
|
||||
return f.GenerateFunc(ctx, idPool, namespace, name)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import (
|
|||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/log"
|
||||
"github.com/external-secrets/external-secrets/pkg/utils"
|
||||
)
|
||||
|
||||
|
@ -146,7 +145,7 @@ func (g *Gitlab) NewClient(ctx context.Context, store esv1beta1.GenericStore, ku
|
|||
// Create a new Gitlab client using credentials and options
|
||||
gitlabClient, err := gitlab.NewClient(string(cliStore.credentials), opts...)
|
||||
if err != nil {
|
||||
log.Logf("Failed to create client: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g.client = gitlabClient.ProjectVariables
|
||||
|
|
|
@ -18,7 +18,9 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
|
@ -30,130 +32,116 @@ const (
|
|||
errFetchCredentials = "could not fetch credentials: %w"
|
||||
errMissingCredentials = "missing credentials: \"%s\""
|
||||
errEmptyKey = "key %s found but empty"
|
||||
errGetKubeSA = "cannot get Kubernetes service account %q: %w"
|
||||
errGetKubeSASecrets = "cannot find secrets bound to service account: %q"
|
||||
errGetKubeSANoToken = "cannot find token in secrets bound to service account: %q"
|
||||
errUnableCreateToken = "cannot create service account token: %q"
|
||||
)
|
||||
|
||||
func (k *BaseClient) setAuth(ctx context.Context) error {
|
||||
err := k.setCA(ctx)
|
||||
func (c *Client) setAuth(ctx context.Context) error {
|
||||
err := c.setCA(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if k.store.Auth.Token != nil {
|
||||
k.BearerToken, err = k.fetchSecretKey(ctx, k.store.Auth.Token.BearerToken)
|
||||
if c.store.Auth.Token != nil {
|
||||
c.BearerToken, err = c.fetchSecretKey(ctx, c.store.Auth.Token.BearerToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fetch Auth.Token.BearerToken: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if k.store.Auth.ServiceAccount != nil {
|
||||
k.BearerToken, err = k.secretKeyRefForServiceAccount(ctx, k.store.Auth.ServiceAccount)
|
||||
if c.store.Auth.ServiceAccount != nil {
|
||||
c.BearerToken, err = c.serviceAccountToken(ctx, c.store.Auth.ServiceAccount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fetch Auth.ServiceAccount: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if k.store.Auth.Cert != nil {
|
||||
return k.setClientCert(ctx)
|
||||
if c.store.Auth.Cert != nil {
|
||||
return c.setClientCert(ctx)
|
||||
}
|
||||
return fmt.Errorf("no credentials provided")
|
||||
}
|
||||
|
||||
func (k *BaseClient) setCA(ctx context.Context) error {
|
||||
if k.store.Server.CABundle != nil {
|
||||
k.CA = k.store.Server.CABundle
|
||||
func (c *Client) setCA(ctx context.Context) error {
|
||||
if c.store.Server.CABundle != nil {
|
||||
c.CA = c.store.Server.CABundle
|
||||
return nil
|
||||
}
|
||||
if k.store.Server.CAProvider != nil {
|
||||
if c.store.Server.CAProvider != nil {
|
||||
var ca []byte
|
||||
var err error
|
||||
switch k.store.Server.CAProvider.Type {
|
||||
switch c.store.Server.CAProvider.Type {
|
||||
case esv1beta1.CAProviderTypeConfigMap:
|
||||
keySelector := esmeta.SecretKeySelector{
|
||||
Name: k.store.Server.CAProvider.Name,
|
||||
Namespace: k.store.Server.CAProvider.Namespace,
|
||||
Key: k.store.Server.CAProvider.Key,
|
||||
Name: c.store.Server.CAProvider.Name,
|
||||
Namespace: c.store.Server.CAProvider.Namespace,
|
||||
Key: c.store.Server.CAProvider.Key,
|
||||
}
|
||||
ca, err = k.fetchConfigMapKey(ctx, keySelector)
|
||||
ca, err = c.fetchConfigMapKey(ctx, keySelector)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to fetch Server.CAProvider ConfigMap: %w", err)
|
||||
}
|
||||
case esv1beta1.CAProviderTypeSecret:
|
||||
keySelector := esmeta.SecretKeySelector{
|
||||
Name: k.store.Server.CAProvider.Name,
|
||||
Namespace: k.store.Server.CAProvider.Namespace,
|
||||
Key: k.store.Server.CAProvider.Key,
|
||||
Name: c.store.Server.CAProvider.Name,
|
||||
Namespace: c.store.Server.CAProvider.Namespace,
|
||||
Key: c.store.Server.CAProvider.Key,
|
||||
}
|
||||
ca, err = k.fetchSecretKey(ctx, keySelector)
|
||||
ca, err = c.fetchSecretKey(ctx, keySelector)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to fetch Server.CAProvider Secret: %w", err)
|
||||
}
|
||||
}
|
||||
k.CA = ca
|
||||
c.CA = ca
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("no Certificate Authority provided")
|
||||
}
|
||||
|
||||
func (k *BaseClient) setClientCert(ctx context.Context) error {
|
||||
func (c *Client) setClientCert(ctx context.Context) error {
|
||||
var err error
|
||||
k.Certificate, err = k.fetchSecretKey(ctx, k.store.Auth.Cert.ClientCert)
|
||||
c.Certificate, err = c.fetchSecretKey(ctx, c.store.Auth.Cert.ClientCert)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to fetch client certificate: %w", err)
|
||||
}
|
||||
k.Key, err = k.fetchSecretKey(ctx, k.store.Auth.Cert.ClientKey)
|
||||
c.Key, err = c.fetchSecretKey(ctx, c.store.Auth.Cert.ClientKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to fetch client key: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *BaseClient) secretKeyRefForServiceAccount(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) ([]byte, error) {
|
||||
serviceAccount := &corev1.ServiceAccount{}
|
||||
ref := types.NamespacedName{
|
||||
Namespace: k.namespace,
|
||||
Name: serviceAccountRef.Name,
|
||||
}
|
||||
if (k.storeKind == esv1beta1.ClusterSecretStoreKind) &&
|
||||
func (c *Client) serviceAccountToken(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) ([]byte, error) {
|
||||
namespace := c.namespace
|
||||
if (c.storeKind == esv1beta1.ClusterSecretStoreKind) &&
|
||||
(serviceAccountRef.Namespace != nil) {
|
||||
ref.Namespace = *serviceAccountRef.Namespace
|
||||
namespace = *serviceAccountRef.Namespace
|
||||
}
|
||||
err := k.kube.Get(ctx, ref, serviceAccount)
|
||||
expirationSeconds := int64(3600)
|
||||
tr, err := c.ctrlClientset.ServiceAccounts(namespace).CreateToken(ctx, serviceAccountRef.Name, &authenticationv1.TokenRequest{
|
||||
Spec: authenticationv1.TokenRequestSpec{
|
||||
Audiences: serviceAccountRef.Audiences,
|
||||
ExpirationSeconds: &expirationSeconds,
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(errGetKubeSA, ref.Name, err)
|
||||
return nil, fmt.Errorf(errUnableCreateToken, err)
|
||||
}
|
||||
if len(serviceAccount.Secrets) == 0 {
|
||||
return nil, fmt.Errorf(errGetKubeSASecrets, ref.Name)
|
||||
}
|
||||
for _, tokenRef := range serviceAccount.Secrets {
|
||||
retval, err := k.fetchSecretKey(ctx, esmeta.SecretKeySelector{
|
||||
Name: tokenRef.Name,
|
||||
Namespace: &ref.Namespace,
|
||||
Key: "token",
|
||||
})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return retval, nil
|
||||
}
|
||||
return nil, fmt.Errorf(errGetKubeSANoToken, ref.Name)
|
||||
return []byte(tr.Status.Token), nil
|
||||
}
|
||||
|
||||
func (k *BaseClient) fetchSecretKey(ctx context.Context, key esmeta.SecretKeySelector) ([]byte, error) {
|
||||
func (c *Client) fetchSecretKey(ctx context.Context, key esmeta.SecretKeySelector) ([]byte, error) {
|
||||
keySecret := &corev1.Secret{}
|
||||
objectKey := types.NamespacedName{
|
||||
Name: key.Name,
|
||||
Namespace: k.namespace,
|
||||
Namespace: c.namespace,
|
||||
}
|
||||
// only ClusterStore is allowed to set namespace (and then it's required)
|
||||
if k.storeKind == esv1beta1.ClusterSecretStoreKind {
|
||||
if c.storeKind == esv1beta1.ClusterSecretStoreKind {
|
||||
if key.Namespace == nil {
|
||||
return nil, fmt.Errorf(errInvalidClusterStoreMissingNamespace)
|
||||
}
|
||||
objectKey.Namespace = *key.Namespace
|
||||
}
|
||||
err := k.kube.Get(ctx, objectKey, keySecret)
|
||||
err := c.ctrlClient.Get(ctx, objectKey, keySecret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(errFetchCredentials, err)
|
||||
}
|
||||
|
@ -167,20 +155,20 @@ func (k *BaseClient) fetchSecretKey(ctx context.Context, key esmeta.SecretKeySel
|
|||
return val, nil
|
||||
}
|
||||
|
||||
func (k *BaseClient) fetchConfigMapKey(ctx context.Context, key esmeta.SecretKeySelector) ([]byte, error) {
|
||||
func (c *Client) fetchConfigMapKey(ctx context.Context, key esmeta.SecretKeySelector) ([]byte, error) {
|
||||
configMap := &corev1.ConfigMap{}
|
||||
objectKey := types.NamespacedName{
|
||||
Name: key.Name,
|
||||
Namespace: k.namespace,
|
||||
Namespace: c.namespace,
|
||||
}
|
||||
// only ClusterStore is allowed to set namespace (and then it's required)
|
||||
if k.storeKind == esv1beta1.ClusterSecretStoreKind {
|
||||
if c.storeKind == esv1beta1.ClusterSecretStoreKind {
|
||||
if key.Namespace == nil {
|
||||
return nil, fmt.Errorf(errInvalidClusterStoreMissingNamespace)
|
||||
}
|
||||
objectKey.Namespace = *key.Namespace
|
||||
}
|
||||
err := k.kube.Get(ctx, objectKey, configMap)
|
||||
err := c.ctrlClient.Get(ctx, objectKey, configMap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(errFetchCredentials, err)
|
||||
}
|
||||
|
|
|
@ -20,17 +20,20 @@ import (
|
|||
"github.com/google/go-cmp/cmp"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
fclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake"
|
||||
)
|
||||
|
||||
func TestSetAuth(t *testing.T) {
|
||||
type fields struct {
|
||||
kube kclient.Client
|
||||
kubeclientset typedcorev1.CoreV1Interface
|
||||
store *esv1beta1.KubernetesProvider
|
||||
namespace string
|
||||
storeKind string
|
||||
|
@ -209,18 +212,8 @@ func TestSetAuth(t *testing.T) {
|
|||
Name: "my-sa",
|
||||
Namespace: "default",
|
||||
},
|
||||
Secrets: []corev1.ObjectReference{
|
||||
{Name: "sa-token", Namespace: "default"},
|
||||
},
|
||||
}, &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "sa-token",
|
||||
Namespace: "default",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"token": []byte("my-sa-token"),
|
||||
},
|
||||
}).Build(),
|
||||
kubeclientset: utilfake.NewCreateTokenMock().WithToken("my-sa-token"),
|
||||
store: &esv1beta1.KubernetesProvider{
|
||||
Server: esv1beta1.KubernetesServer{
|
||||
CABundle: []byte("1234"),
|
||||
|
@ -242,8 +235,9 @@ func TestSetAuth(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
k := &BaseClient{
|
||||
kube: tt.fields.kube,
|
||||
k := &Client{
|
||||
ctrlClientset: tt.fields.kubeclientset,
|
||||
ctrlClient: tt.fields.kube,
|
||||
store: tt.fields.store,
|
||||
namespace: tt.fields.namespace,
|
||||
storeKind: tt.fields.storeKind,
|
||||
|
|
124
pkg/provider/kubernetes/client.go
Normal file
124
pkg/provider/kubernetes/client.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
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 kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
"github.com/external-secrets/external-secrets/pkg/find"
|
||||
"github.com/external-secrets/external-secrets/pkg/utils"
|
||||
)
|
||||
|
||||
func (c *Client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
secretMap, err := c.GetSecretMap(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ref.Property != "" {
|
||||
val, ok := secretMap[ref.Property]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("property %s does not exist in key %s", ref.Property, ref.Key)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
strMap := make(map[string]string)
|
||||
for k, v := range secretMap {
|
||||
strMap[k] = string(v)
|
||||
}
|
||||
jsonStr, err := json.Marshal(strMap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unabled to marshal json: %w", err)
|
||||
}
|
||||
return jsonStr, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
secret, err := c.userSecretClient.Get(ctx, ref.Key, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return secret.Data, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
|
||||
if ref.Tags != nil {
|
||||
return c.findByTags(ctx, ref)
|
||||
}
|
||||
if ref.Name != nil {
|
||||
return c.findByName(ctx, ref)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected find operator: %#v", ref)
|
||||
}
|
||||
|
||||
func (c *Client) findByTags(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
|
||||
// empty/nil tags = everything
|
||||
sel, err := labels.ValidatedSelectorFromSet(ref.Tags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to validate selector tags: %w", err)
|
||||
}
|
||||
secrets, err := c.userSecretClient.List(ctx, metav1.ListOptions{LabelSelector: sel.String()})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to list secrets: %w", err)
|
||||
}
|
||||
data := make(map[string][]byte)
|
||||
for _, secret := range secrets.Items {
|
||||
jsonStr, err := json.Marshal(convertMap(secret.Data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data[secret.Name] = jsonStr
|
||||
}
|
||||
return utils.ConvertKeys(ref.ConversionStrategy, data)
|
||||
}
|
||||
|
||||
func (c *Client) findByName(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
|
||||
secrets, err := c.userSecretClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to list secrets: %w", err)
|
||||
}
|
||||
matcher, err := find.New(*ref.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := make(map[string][]byte)
|
||||
for _, secret := range secrets.Items {
|
||||
if !matcher.MatchName(secret.Name) {
|
||||
continue
|
||||
}
|
||||
jsonStr, err := json.Marshal(convertMap(secret.Data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data[secret.Name] = jsonStr
|
||||
}
|
||||
return utils.ConvertKeys(ref.ConversionStrategy, data)
|
||||
}
|
||||
|
||||
func (c Client) Close(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertMap(in map[string][]byte) map[string]string {
|
||||
out := make(map[string]string)
|
||||
for k, v := range in {
|
||||
out[k] = string(v)
|
||||
}
|
||||
return out
|
||||
}
|
|
@ -22,35 +22,12 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
fclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
errSomethingWentWrong = "Something went wrong"
|
||||
testCertificate = `-----BEGIN CERTIFICATE-----
|
||||
MIIDHTCCAgWgAwIBAgIRAKC4yxy9QGocND+6avTf7BgwDQYJKoZIhvcNAQELBQAw
|
||||
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0yMTAzMjAyMDA4MDhaFw0yMTAzMjAyMDM4
|
||||
MDhaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQC3o6/JdZEqNbqNRkopHhJtJG5c4qS5d0tQ/kZYpfD/v/izAYum4Nzj
|
||||
aG15owr92/11W0pxPUliRLti3y6iScTs+ofm2D7p4UXj/Fnho/2xoWSOoWAodgvW
|
||||
Y8jh8A0LQALZiV/9QsrJdXZdS47DYZLsQ3z9yFC/CdXkg1l7AQ3fIVGKdrQBr9kE
|
||||
1gEDqnKfRxXI8DEQKXr+CKPUwCAytegmy0SHp53zNAvY+kopHytzmJpXLoEhxq4e
|
||||
ugHe52vXHdh/HJ9VjNp0xOH1waAgAGxHlltCW0PVd5AJ0SXROBS/a3V9sZCbCrJa
|
||||
YOOonQSEswveSv6PcG9AHvpNPot2Xs6hAgMBAAGjbjBsMA4GA1UdDwEB/wQEAwIC
|
||||
pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
|
||||
BBR00805mrpoonp95RmC3B6oLl+cGTAVBgNVHREEDjAMggpnb29ibGUuY29tMA0G
|
||||
CSqGSIb3DQEBCwUAA4IBAQAipc1b6JrEDayPjpz5GM5krcI8dCWVd8re0a9bGjjN
|
||||
ioWGlu/eTr5El0ffwCNZ2WLmL9rewfHf/bMvYz3ioFZJ2OTxfazqYXNggQz6cMfa
|
||||
lbedDCdt5XLVX2TyerGvFram+9Uyvk3l0uM7rZnwAmdirG4Tv94QRaD3q4xTj/c0
|
||||
mv+AggtK0aRFb9o47z/BypLdk5mhbf3Mmr88C8XBzEnfdYyf4JpTlZrYLBmDCu5d
|
||||
9RLLsjXxhag8xqMtd1uLUM8XOTGzVWacw8iGY+CTtBKqyA+AE6/bDwZvEwVtsKtC
|
||||
QJ85ioEpy00NioqcF0WyMZH80uMsPycfpnl5uF7RkW8u
|
||||
-----END CERTIFICATE-----`
|
||||
)
|
||||
|
||||
type fakeClient struct {
|
||||
|
@ -171,10 +148,10 @@ func TestGetSecret(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &ProviderKubernetes{
|
||||
Client: tt.fields.Client,
|
||||
ReviewClient: tt.fields.ReviewClient,
|
||||
Namespace: tt.fields.Namespace,
|
||||
p := &Client{
|
||||
userSecretClient: tt.fields.Client,
|
||||
userReviewClient: tt.fields.ReviewClient,
|
||||
namespace: tt.fields.Namespace,
|
||||
}
|
||||
got, err := p.GetSecret(context.Background(), tt.ref)
|
||||
if (err != nil) != tt.wantErr {
|
||||
|
@ -188,167 +165,6 @@ func TestGetSecret(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
type fields struct {
|
||||
Client KClient
|
||||
ReviewClient RClient
|
||||
Namespace string
|
||||
}
|
||||
type args struct {
|
||||
store esv1beta1.GenericStore
|
||||
kube kclient.Client
|
||||
namespace string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "invalid store",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{},
|
||||
},
|
||||
},
|
||||
kube: fclient.NewClientBuilder().Build(),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "test referent auth return",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||
Server: esv1beta1.KubernetesServer{
|
||||
CABundle: []byte(testCertificate),
|
||||
},
|
||||
Auth: esv1beta1.KubernetesAuth{
|
||||
Token: &esv1beta1.TokenAuth{
|
||||
BearerToken: v1.SecretKeySelector{
|
||||
Name: "foo",
|
||||
Key: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
namespace: "",
|
||||
kube: fclient.NewClientBuilder().Build(),
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "auth fail results in error",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||
Server: esv1beta1.KubernetesServer{
|
||||
CABundle: []byte(testCertificate),
|
||||
},
|
||||
RemoteNamespace: "remote",
|
||||
Auth: esv1beta1.KubernetesAuth{
|
||||
Token: &esv1beta1.TokenAuth{
|
||||
BearerToken: v1.SecretKeySelector{
|
||||
Name: "foo",
|
||||
Namespace: pointer.String("default"),
|
||||
Key: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
namespace: "foobarothernamespace",
|
||||
kube: fclient.NewClientBuilder().Build(),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "test auth",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||
Server: esv1beta1.KubernetesServer{
|
||||
CABundle: []byte(testCertificate),
|
||||
},
|
||||
RemoteNamespace: "remote",
|
||||
Auth: esv1beta1.KubernetesAuth{
|
||||
Token: &esv1beta1.TokenAuth{
|
||||
BearerToken: v1.SecretKeySelector{
|
||||
Name: "foo",
|
||||
Namespace: pointer.String("default"),
|
||||
Key: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
namespace: "foobarothernamespace",
|
||||
kube: fclient.NewClientBuilder().WithObjects(&corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: "default",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"token": []byte("1234"),
|
||||
},
|
||||
}).Build(),
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &ProviderKubernetes{
|
||||
Client: tt.fields.Client,
|
||||
ReviewClient: tt.fields.ReviewClient,
|
||||
Namespace: tt.fields.Namespace,
|
||||
}
|
||||
got, err := p.NewClient(context.Background(), tt.args.store, tt.args.kube, tt.args.namespace)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ProviderKubernetes.NewClient() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if tt.want {
|
||||
assert.NotNil(t, got)
|
||||
} else {
|
||||
assert.Nil(t, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllSecrets(t *testing.T) {
|
||||
type fields struct {
|
||||
Client KClient
|
||||
|
@ -445,10 +261,10 @@ func TestGetAllSecrets(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &ProviderKubernetes{
|
||||
Client: tt.fields.Client,
|
||||
ReviewClient: tt.fields.ReviewClient,
|
||||
Namespace: tt.fields.Namespace,
|
||||
p := &Client{
|
||||
userSecretClient: tt.fields.Client,
|
||||
userReviewClient: tt.fields.ReviewClient,
|
||||
namespace: tt.fields.Namespace,
|
||||
}
|
||||
got, err := p.GetAllSecrets(tt.args.ctx, tt.args.ref)
|
||||
if (err != nil) != tt.wantErr {
|
|
@ -1,241 +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 kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
authv1 "k8s.io/api/authorization/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
"github.com/external-secrets/external-secrets/pkg/find"
|
||||
"github.com/external-secrets/external-secrets/pkg/utils"
|
||||
)
|
||||
|
||||
// https://github.com/external-secrets/external-secrets/issues/644
|
||||
var _ esv1beta1.SecretsClient = &ProviderKubernetes{}
|
||||
var _ esv1beta1.Provider = &ProviderKubernetes{}
|
||||
|
||||
type KClient interface {
|
||||
Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error)
|
||||
List(ctx context.Context, opts metav1.ListOptions) (*corev1.SecretList, error)
|
||||
}
|
||||
|
||||
type RClient interface {
|
||||
Create(ctx context.Context, selfSubjectRulesReview *authv1.SelfSubjectRulesReview, opts metav1.CreateOptions) (*authv1.SelfSubjectRulesReview, error)
|
||||
}
|
||||
|
||||
// ProviderKubernetes is a provider for Kubernetes.
|
||||
type ProviderKubernetes struct {
|
||||
Client KClient
|
||||
ReviewClient RClient
|
||||
Namespace string
|
||||
store *esv1beta1.KubernetesProvider
|
||||
storeKind string
|
||||
}
|
||||
|
||||
var _ esv1beta1.SecretsClient = &ProviderKubernetes{}
|
||||
|
||||
type BaseClient struct {
|
||||
kube kclient.Client
|
||||
store *esv1beta1.KubernetesProvider
|
||||
storeKind string
|
||||
namespace string
|
||||
Certificate []byte
|
||||
Key []byte
|
||||
CA []byte
|
||||
BearerToken []byte
|
||||
}
|
||||
|
||||
func init() {
|
||||
esv1beta1.Register(&ProviderKubernetes{}, &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{},
|
||||
})
|
||||
}
|
||||
|
||||
// NewClient constructs a Kubernetes Provider.
|
||||
func (p *ProviderKubernetes) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
|
||||
storeSpec := store.GetSpec()
|
||||
if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Kubernetes == nil {
|
||||
return nil, fmt.Errorf("no store type or wrong store type")
|
||||
}
|
||||
storeSpecKubernetes := storeSpec.Provider.Kubernetes
|
||||
|
||||
client := BaseClient{
|
||||
kube: kube,
|
||||
store: storeSpecKubernetes,
|
||||
namespace: namespace,
|
||||
storeKind: store.GetObjectKind().GroupVersionKind().Kind,
|
||||
}
|
||||
p.Namespace = client.store.RemoteNamespace
|
||||
p.store = storeSpecKubernetes
|
||||
p.storeKind = store.GetObjectKind().GroupVersionKind().Kind
|
||||
|
||||
// allow SecretStore controller validation to pass
|
||||
// when using referent namespace.
|
||||
if client.storeKind == esv1beta1.ClusterSecretStoreKind && client.namespace == "" && isReferentSpec(storeSpecKubernetes) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
if err := client.setAuth(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &rest.Config{
|
||||
Host: client.store.Server.URL,
|
||||
BearerToken: string(client.BearerToken),
|
||||
TLSClientConfig: rest.TLSClientConfig{
|
||||
Insecure: false,
|
||||
CertData: client.Certificate,
|
||||
KeyData: client.Key,
|
||||
CAData: client.CA,
|
||||
},
|
||||
}
|
||||
|
||||
kubeClientSet, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error configuring clientset: %w", err)
|
||||
}
|
||||
p.Client = kubeClientSet.CoreV1().Secrets(client.store.RemoteNamespace)
|
||||
p.ReviewClient = kubeClientSet.AuthorizationV1().SelfSubjectRulesReviews()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func isReferentSpec(prov *esv1beta1.KubernetesProvider) bool {
|
||||
if prov.Auth.Cert != nil {
|
||||
if prov.Auth.Cert.ClientCert.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
if prov.Auth.Cert.ClientKey.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if prov.Auth.ServiceAccount != nil {
|
||||
if prov.Auth.ServiceAccount.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if prov.Auth.Token != nil {
|
||||
if prov.Auth.Token.BearerToken.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *ProviderKubernetes) Close(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProviderKubernetes) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
|
||||
secretMap, err := p.GetSecretMap(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ref.Property != "" {
|
||||
val, ok := secretMap[ref.Property]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("property %s does not exist in key %s", ref.Property, ref.Key)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
strMap := make(map[string]string)
|
||||
for k, v := range secretMap {
|
||||
strMap[k] = string(v)
|
||||
}
|
||||
jsonStr, err := json.Marshal(strMap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unabled to marshal json: %w", err)
|
||||
}
|
||||
return jsonStr, nil
|
||||
}
|
||||
|
||||
func (p *ProviderKubernetes) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
secret, err := p.Client.Get(ctx, ref.Key, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return secret.Data, nil
|
||||
}
|
||||
|
||||
func (p *ProviderKubernetes) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
|
||||
if ref.Tags != nil {
|
||||
return p.findByTags(ctx, ref)
|
||||
}
|
||||
if ref.Name != nil {
|
||||
return p.findByName(ctx, ref)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected find operator: %#v", ref)
|
||||
}
|
||||
|
||||
func (p *ProviderKubernetes) findByTags(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
|
||||
// empty/nil tags = everything
|
||||
sel, err := labels.ValidatedSelectorFromSet(ref.Tags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to validate selector tags: %w", err)
|
||||
}
|
||||
secrets, err := p.Client.List(ctx, metav1.ListOptions{LabelSelector: sel.String()})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to list secrets: %w", err)
|
||||
}
|
||||
data := make(map[string][]byte)
|
||||
for _, secret := range secrets.Items {
|
||||
jsonStr, err := json.Marshal(convertMap(secret.Data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data[secret.Name] = jsonStr
|
||||
}
|
||||
return utils.ConvertKeys(ref.ConversionStrategy, data)
|
||||
}
|
||||
|
||||
func (p *ProviderKubernetes) findByName(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
|
||||
secrets, err := p.Client.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to list secrets: %w", err)
|
||||
}
|
||||
matcher, err := find.New(*ref.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := make(map[string][]byte)
|
||||
for _, secret := range secrets.Items {
|
||||
if !matcher.MatchName(secret.Name) {
|
||||
continue
|
||||
}
|
||||
jsonStr, err := json.Marshal(convertMap(secret.Data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data[secret.Name] = jsonStr
|
||||
}
|
||||
return utils.ConvertKeys(ref.ConversionStrategy, data)
|
||||
}
|
||||
|
||||
func convertMap(in map[string][]byte) map[string]string {
|
||||
out := make(map[string]string)
|
||||
for k, v := range in {
|
||||
out[k] = string(v)
|
||||
}
|
||||
return out
|
||||
}
|
167
pkg/provider/kubernetes/provider.go
Normal file
167
pkg/provider/kubernetes/provider.go
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
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 kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
authv1 "k8s.io/api/authorization/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
)
|
||||
|
||||
// https://github.com/external-secrets/external-secrets/issues/644
|
||||
var _ esv1beta1.SecretsClient = &Client{}
|
||||
var _ esv1beta1.Provider = &Provider{}
|
||||
|
||||
type KClient interface {
|
||||
Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error)
|
||||
List(ctx context.Context, opts metav1.ListOptions) (*corev1.SecretList, error)
|
||||
}
|
||||
|
||||
type RClient interface {
|
||||
Create(ctx context.Context, selfSubjectRulesReview *authv1.SelfSubjectRulesReview, opts metav1.CreateOptions) (*authv1.SelfSubjectRulesReview, error)
|
||||
}
|
||||
|
||||
// Provider implements Secret Provider interface
|
||||
// for Kubernetes.
|
||||
type Provider struct{}
|
||||
|
||||
// Client implements Secret Client interface
|
||||
// for Kubernetes.
|
||||
type Client struct {
|
||||
// ctrlClient is a controller-runtime client
|
||||
// with RBAC scope of the controller (privileged!)
|
||||
ctrlClient kclient.Client
|
||||
// ctrlClientset is a client-go CoreV1() client
|
||||
// with RBAC scope of the controller (privileged!)
|
||||
ctrlClientset typedcorev1.CoreV1Interface
|
||||
// userSecretClient is a client-go CoreV1().Secrets() client
|
||||
// with user-defined scope.
|
||||
userSecretClient KClient
|
||||
// userReviewClient is a SelfSubjectAccessReview client with
|
||||
// user-defined scope.
|
||||
userReviewClient RClient
|
||||
|
||||
// store is the Kubernetes Provider spec
|
||||
// which contains the configuration for this provider.
|
||||
store *esv1beta1.KubernetesProvider
|
||||
storeKind string
|
||||
|
||||
// namespace is the namespace of the
|
||||
// ExternalSecret referencing this provider.
|
||||
namespace string
|
||||
Certificate []byte
|
||||
Key []byte
|
||||
CA []byte
|
||||
BearerToken []byte
|
||||
}
|
||||
|
||||
func init() {
|
||||
esv1beta1.Register(&Provider{}, &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{},
|
||||
})
|
||||
}
|
||||
|
||||
// NewClient constructs a Kubernetes Provider.
|
||||
func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
|
||||
restCfg, err := ctrlcfg.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(restCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.newClient(ctx, store, kube, clientset, namespace)
|
||||
}
|
||||
|
||||
func (p *Provider) newClient(ctx context.Context, store esv1beta1.GenericStore, ctrlClient kclient.Client, ctrlClientset kubernetes.Interface, namespace string) (esv1beta1.SecretsClient, error) {
|
||||
storeSpec := store.GetSpec()
|
||||
if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Kubernetes == nil {
|
||||
return nil, fmt.Errorf("no store type or wrong store type")
|
||||
}
|
||||
storeSpecKubernetes := storeSpec.Provider.Kubernetes
|
||||
client := &Client{
|
||||
ctrlClientset: ctrlClientset.CoreV1(),
|
||||
ctrlClient: ctrlClient,
|
||||
store: storeSpecKubernetes,
|
||||
namespace: namespace,
|
||||
storeKind: store.GetObjectKind().GroupVersionKind().Kind,
|
||||
}
|
||||
|
||||
// allow SecretStore controller validation to pass
|
||||
// when using referent namespace.
|
||||
if client.storeKind == esv1beta1.ClusterSecretStoreKind && client.namespace == "" && isReferentSpec(storeSpecKubernetes) {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
if err := client.setAuth(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &rest.Config{
|
||||
Host: client.store.Server.URL,
|
||||
BearerToken: string(client.BearerToken),
|
||||
TLSClientConfig: rest.TLSClientConfig{
|
||||
Insecure: false,
|
||||
CertData: client.Certificate,
|
||||
KeyData: client.Key,
|
||||
CAData: client.CA,
|
||||
},
|
||||
}
|
||||
|
||||
userClientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error configuring clientset: %w", err)
|
||||
}
|
||||
client.userSecretClient = userClientset.CoreV1().Secrets(client.store.RemoteNamespace)
|
||||
client.userReviewClient = userClientset.AuthorizationV1().SelfSubjectRulesReviews()
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func isReferentSpec(prov *esv1beta1.KubernetesProvider) bool {
|
||||
if prov.Auth.Cert != nil {
|
||||
if prov.Auth.Cert.ClientCert.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
if prov.Auth.Cert.ClientKey.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if prov.Auth.ServiceAccount != nil {
|
||||
if prov.Auth.ServiceAccount.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if prov.Auth.Token != nil {
|
||||
if prov.Auth.Token.BearerToken.Namespace == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Provider) Close(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
213
pkg/provider/kubernetes/provider_test.go
Normal file
213
pkg/provider/kubernetes/provider_test.go
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
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 kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
clientgofake "k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/utils/pointer"
|
||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
fclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
testCertificate = `-----BEGIN CERTIFICATE-----
|
||||
MIIDHTCCAgWgAwIBAgIRAKC4yxy9QGocND+6avTf7BgwDQYJKoZIhvcNAQELBQAw
|
||||
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0yMTAzMjAyMDA4MDhaFw0yMTAzMjAyMDM4
|
||||
MDhaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQC3o6/JdZEqNbqNRkopHhJtJG5c4qS5d0tQ/kZYpfD/v/izAYum4Nzj
|
||||
aG15owr92/11W0pxPUliRLti3y6iScTs+ofm2D7p4UXj/Fnho/2xoWSOoWAodgvW
|
||||
Y8jh8A0LQALZiV/9QsrJdXZdS47DYZLsQ3z9yFC/CdXkg1l7AQ3fIVGKdrQBr9kE
|
||||
1gEDqnKfRxXI8DEQKXr+CKPUwCAytegmy0SHp53zNAvY+kopHytzmJpXLoEhxq4e
|
||||
ugHe52vXHdh/HJ9VjNp0xOH1waAgAGxHlltCW0PVd5AJ0SXROBS/a3V9sZCbCrJa
|
||||
YOOonQSEswveSv6PcG9AHvpNPot2Xs6hAgMBAAGjbjBsMA4GA1UdDwEB/wQEAwIC
|
||||
pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
|
||||
BBR00805mrpoonp95RmC3B6oLl+cGTAVBgNVHREEDjAMggpnb29ibGUuY29tMA0G
|
||||
CSqGSIb3DQEBCwUAA4IBAQAipc1b6JrEDayPjpz5GM5krcI8dCWVd8re0a9bGjjN
|
||||
ioWGlu/eTr5El0ffwCNZ2WLmL9rewfHf/bMvYz3ioFZJ2OTxfazqYXNggQz6cMfa
|
||||
lbedDCdt5XLVX2TyerGvFram+9Uyvk3l0uM7rZnwAmdirG4Tv94QRaD3q4xTj/c0
|
||||
mv+AggtK0aRFb9o47z/BypLdk5mhbf3Mmr88C8XBzEnfdYyf4JpTlZrYLBmDCu5d
|
||||
9RLLsjXxhag8xqMtd1uLUM8XOTGzVWacw8iGY+CTtBKqyA+AE6/bDwZvEwVtsKtC
|
||||
QJ85ioEpy00NioqcF0WyMZH80uMsPycfpnl5uF7RkW8u
|
||||
-----END CERTIFICATE-----`
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
type fields struct {
|
||||
Client KClient
|
||||
ReviewClient RClient
|
||||
Namespace string
|
||||
}
|
||||
type args struct {
|
||||
store esv1beta1.GenericStore
|
||||
kube kclient.Client
|
||||
clientset kubernetes.Interface
|
||||
namespace string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "invalid store",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{},
|
||||
},
|
||||
},
|
||||
kube: fclient.NewClientBuilder().Build(),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "test referent auth return",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||
Server: esv1beta1.KubernetesServer{
|
||||
CABundle: []byte(testCertificate),
|
||||
},
|
||||
Auth: esv1beta1.KubernetesAuth{
|
||||
Token: &esv1beta1.TokenAuth{
|
||||
BearerToken: v1.SecretKeySelector{
|
||||
Name: "foo",
|
||||
Key: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
namespace: "",
|
||||
kube: fclient.NewClientBuilder().Build(),
|
||||
clientset: clientgofake.NewSimpleClientset(),
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "auth fail results in error",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||
Server: esv1beta1.KubernetesServer{
|
||||
CABundle: []byte(testCertificate),
|
||||
},
|
||||
RemoteNamespace: "remote",
|
||||
Auth: esv1beta1.KubernetesAuth{
|
||||
Token: &esv1beta1.TokenAuth{
|
||||
BearerToken: v1.SecretKeySelector{
|
||||
Name: "foo",
|
||||
Namespace: pointer.String("default"),
|
||||
Key: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
namespace: "foobarothernamespace",
|
||||
clientset: clientgofake.NewSimpleClientset(),
|
||||
kube: fclient.NewClientBuilder().Build(),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "test auth",
|
||||
fields: fields{},
|
||||
args: args{
|
||||
store: &esv1beta1.ClusterSecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||
},
|
||||
Spec: esv1beta1.SecretStoreSpec{
|
||||
Provider: &esv1beta1.SecretStoreProvider{
|
||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||
Server: esv1beta1.KubernetesServer{
|
||||
CABundle: []byte(testCertificate),
|
||||
},
|
||||
RemoteNamespace: "remote",
|
||||
Auth: esv1beta1.KubernetesAuth{
|
||||
Token: &esv1beta1.TokenAuth{
|
||||
BearerToken: v1.SecretKeySelector{
|
||||
Name: "foo",
|
||||
Namespace: pointer.String("default"),
|
||||
Key: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
namespace: "foobarothernamespace",
|
||||
clientset: clientgofake.NewSimpleClientset(),
|
||||
kube: fclient.NewClientBuilder().WithObjects(&corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: "default",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"token": []byte("1234"),
|
||||
},
|
||||
}).Build(),
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := (&Provider{}).newClient(context.Background(), tt.args.store, tt.args.kube, tt.args.clientset, tt.args.namespace)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ProviderKubernetes.NewClient() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if tt.want {
|
||||
assert.NotNil(t, got)
|
||||
} else {
|
||||
assert.Nil(t, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ import (
|
|||
"github.com/external-secrets/external-secrets/pkg/utils"
|
||||
)
|
||||
|
||||
func (p *ProviderKubernetes) ValidateStore(store esv1beta1.GenericStore) error {
|
||||
func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
|
||||
storeSpec := store.GetSpec()
|
||||
k8sSpec := storeSpec.Provider.Kubernetes
|
||||
if k8sSpec.Server.CABundle == nil && k8sSpec.Server.CAProvider == nil {
|
||||
|
@ -65,20 +65,20 @@ func (p *ProviderKubernetes) ValidateStore(store esv1beta1.GenericStore) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *ProviderKubernetes) Validate() (esv1beta1.ValidationResult, error) {
|
||||
func (c *Client) Validate() (esv1beta1.ValidationResult, error) {
|
||||
// when using referent namespace we can not validate the token
|
||||
// because the namespace is not known yet when Validate() is called
|
||||
// from the SecretStore controller.
|
||||
if p.storeKind == esv1beta1.ClusterSecretStoreKind && isReferentSpec(p.store) {
|
||||
if c.storeKind == esv1beta1.ClusterSecretStoreKind && isReferentSpec(c.store) {
|
||||
return esv1beta1.ValidationResultUnknown, nil
|
||||
}
|
||||
ctx := context.Background()
|
||||
t := authv1.SelfSubjectRulesReview{
|
||||
Spec: authv1.SelfSubjectRulesReviewSpec{
|
||||
Namespace: p.Namespace,
|
||||
Namespace: c.store.RemoteNamespace,
|
||||
},
|
||||
}
|
||||
authReview, err := p.ReviewClient.Create(ctx, &t, metav1.CreateOptions{})
|
||||
authReview, err := c.userReviewClient.Create(ctx, &t, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return esv1beta1.ValidationResultUnknown, fmt.Errorf("could not verify if client is valid: %w", err)
|
||||
}
|
||||
|
|
|
@ -244,11 +244,7 @@ func TestValidateStore(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
k := &ProviderKubernetes{
|
||||
Client: tt.fields.Client,
|
||||
ReviewClient: tt.fields.ReviewClient,
|
||||
Namespace: tt.fields.Namespace,
|
||||
}
|
||||
k := &Provider{}
|
||||
if err := k.ValidateStore(tt.store); (err != nil) != tt.wantErr {
|
||||
t.Errorf("ProviderKubernetes.ValidateStore() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
@ -312,6 +308,7 @@ func TestValidate(t *testing.T) {
|
|||
fields: fields{
|
||||
Namespace: "default",
|
||||
ReviewClient: fakeReviewClient{},
|
||||
store: &esv1beta1.KubernetesProvider{},
|
||||
},
|
||||
want: esv1beta1.ValidationResultUnknown,
|
||||
wantErr: true,
|
||||
|
@ -321,6 +318,7 @@ func TestValidate(t *testing.T) {
|
|||
fields: fields{
|
||||
Namespace: "default",
|
||||
ReviewClient: fakeReviewClient{authReview: &failReview},
|
||||
store: &esv1beta1.KubernetesProvider{},
|
||||
},
|
||||
want: esv1beta1.ValidationResultError,
|
||||
wantErr: true,
|
||||
|
@ -330,6 +328,7 @@ func TestValidate(t *testing.T) {
|
|||
fields: fields{
|
||||
Namespace: "default",
|
||||
ReviewClient: fakeReviewClient{authReview: &successReview},
|
||||
store: &esv1beta1.KubernetesProvider{},
|
||||
},
|
||||
want: esv1beta1.ValidationResultReady,
|
||||
wantErr: false,
|
||||
|
@ -337,10 +336,10 @@ func TestValidate(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
k := &ProviderKubernetes{
|
||||
Client: tt.fields.Client,
|
||||
ReviewClient: tt.fields.ReviewClient,
|
||||
Namespace: tt.fields.Namespace,
|
||||
k := &Client{
|
||||
userSecretClient: tt.fields.Client,
|
||||
userReviewClient: tt.fields.ReviewClient,
|
||||
namespace: tt.fields.Namespace,
|
||||
store: tt.fields.store,
|
||||
storeKind: tt.fields.storeKind,
|
||||
}
|
||||
|
|
|
@ -21,10 +21,8 @@ import (
|
|||
k8sv1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
func NewCreateTokenMock(token string) *MockK8sV1 {
|
||||
return &MockK8sV1{
|
||||
token: token,
|
||||
}
|
||||
func NewCreateTokenMock() *MockK8sV1 {
|
||||
return &MockK8sV1{}
|
||||
}
|
||||
|
||||
// Mock K8s client for creating tokens.
|
||||
|
@ -32,6 +30,17 @@ type MockK8sV1 struct {
|
|||
k8sv1.CoreV1Interface
|
||||
|
||||
token string
|
||||
err error
|
||||
}
|
||||
|
||||
func (m *MockK8sV1) WithToken(token string) *MockK8sV1 {
|
||||
m.token = token
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *MockK8sV1) WithError(err error) *MockK8sV1 {
|
||||
m.err = err
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *MockK8sV1) ServiceAccounts(namespace string) k8sv1.ServiceAccountInterface {
|
||||
|
@ -50,6 +59,9 @@ func (ma *MockK8sV1SA) CreateToken(
|
|||
tokenRequest *authv1.TokenRequest,
|
||||
opts metav1.CreateOptions,
|
||||
) (*authv1.TokenRequest, error) {
|
||||
if ma.v1mock.err != nil {
|
||||
return nil, ma.v1mock.err
|
||||
}
|
||||
return &authv1.TokenRequest{
|
||||
Status: authv1.TokenRequestStatus{
|
||||
Token: ma.v1mock.token,
|
|
@ -970,7 +970,11 @@ func (v *client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySe
|
|||
return valueStr, nil
|
||||
}
|
||||
|
||||
func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esmeta.ServiceAccountSelector, audiences []string, expirationSeconds int64) (string, error) {
|
||||
func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esmeta.ServiceAccountSelector, additionalAud []string, expirationSeconds int64) (string, error) {
|
||||
audiences := serviceAccountRef.Audiences
|
||||
if len(additionalAud) > 0 {
|
||||
audiences = append(audiences, additionalAud...)
|
||||
}
|
||||
tokenRequest := &authenticationv1.TokenRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: v.namespace,
|
||||
|
@ -1046,7 +1050,19 @@ func (v *client) requestTokenWithKubernetesAuth(ctx context.Context, kubernetesA
|
|||
|
||||
func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.VaultKubernetesAuth) (string, error) {
|
||||
if kubernetesAuth.ServiceAccountRef != nil {
|
||||
// Kubernetes <v1.24 fetch token via ServiceAccount.Secrets[]
|
||||
// this behavior was removed in v1.24 and we must use TokenRequest API (see below)
|
||||
jwt, err := v.secretKeyRefForServiceAccount(ctx, kubernetesAuth.ServiceAccountRef)
|
||||
if jwt != "" {
|
||||
return jwt, err
|
||||
}
|
||||
if err != nil {
|
||||
v.log.V(1).Info("unable to fetch jwt from service account secret")
|
||||
}
|
||||
// Kubernetes >=v1.24: fetch token via TokenRequest API
|
||||
// note: this is a massive change from vault perspective: the `iss` claim will very likely change.
|
||||
// Vault 1.9 deprecated issuer validation by default, and authentication with Vault clusters <1.9 will likely fail.
|
||||
jwt, err = v.serviceAccountToken(ctx, *kubernetesAuth.ServiceAccountRef, nil, 600)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -26,11 +26,13 @@ import (
|
|||
vault "github.com/hashicorp/vault/api"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/vault/fake"
|
||||
)
|
||||
|
||||
|
@ -172,6 +174,7 @@ type args struct {
|
|||
newClientFunc func(c *vault.Config) (Client, error)
|
||||
store esv1beta1.GenericStore
|
||||
kube kclient.Client
|
||||
corev1 typedcorev1.CoreV1Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
|
@ -227,13 +230,12 @@ func kubeMockWithSecretTokenAndServiceAcc(obj kclient.Object) error {
|
|||
|
||||
func TestNewVault(t *testing.T) {
|
||||
errBoom := errors.New("boom")
|
||||
secretClientKey := []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEArfZ4HV1obFVlVNiA24tX/UOakqRnEtWXpIvaOsMaPGvvODgGe4XnyJGO32idPv85sIr7vDH9p+OhactVlJV1fu5SZoZ7pg4jTCLqVDCb3IRD++yik2Sw58YayNe3HiaCTsJQWeMXLzfaqOeyk6bEpBCJo09+3QxUWxijgJ7YZCb+Gi8pf3ZWeSZG+rGNNvXHmTs1Yu1H849SYXu+uJOd/R3ZSTw8CxFe4eTLgbCnPf6tgA8Sg2hc+CAZxunPP2JLZWbiJXxjNRoypso6MAJ1FRkx5sTJiLg6UoLvd95/S/lCVOR2PDlM1hg7ox8VEd4QHky7tLx7gji/5hHQKJQSTwIDAQABAoIBAQCYPICQ8hVX+MNcpLrfZenycR7sBYNOMC0silbH5cUn6yzFfgHuRxi3pOnrCJnTb3cE0BvMbdMVAVdYReD2znSsR9NEdZvvjZ/GGSgH1SIQsI7t//+mDQ/jRLJb4KsXb4vJcLLwdpLrd22bMmhMXjzndrF8gSz8NLX9omozPM8RlLxjzPzYOdlX/Zw8V68qQH2Ic04KbtnCwyAUIgAJxYtn/uYB8lzILBkyzQqwhQKkDDZQ0wbZT0hP6z+HgsdifwQvHG1GZAgCuzzyXrL/4TgDaDhYdMVoBA4+HPmzqm5MkBvjH4oqroxjRofUroVix0OGXZJMI1OJ0z/ubzmwCq5BAoGBANqbwzAydUJs0P+GFL94K/Y6tXULKA2c9N0crbxoxheobRpuJvhpW1ZE/9UGpaYX1Rw3nW4x+Jwvt83YkgHAlR4LgEwDvdJPZobybfqifQDiraUO0t62Crn8mSxOsFCugtRIFniwnX67w3uKxiSdCZYbJGs9JEDTpxRG/PSWq3QlAoGBAMu3zOv1PJAhOky7VcxFxWQPEMY+t2PA/sneD01/qgGuhlTwL4QlpywmBqXcI070dcvcBkP0flnWI7y5cnuE1+55twmsrvfaS8s1+AYje0b35DsaF2vtKuJrXC0AGKP+/eiycd9cbvVW2GWOxE7Ui76Mj95MARK8ZNjt0wJagQhjAoGASm9dD80uhhadN1RFPkjB1054OMk6sx/tdFhug8e9I5MSyzwUguME2aQW5EcmIh7dToVVUo8rUqsgz7NdS8FyRM+vuLJRcQneJDbp4bxwCdwlOh2JCZI8psVutlp4yJATNgrxs9iXV+7BChDflNnvyK+nP+iKrpQiwNHHEdU3vg0CgYEAvEpwD4+loJn1psJn9NxwK6F5IaMKIhtZ4/9pKXpcCh3jb1JouL2MnFOxRVAJGor87aW57Mlol2RDt8W4OM56PqMlOL3xIokUEQka66GT6e5pdu8QwuJ9BrWwhq9WFw4yZQe6FHb836qbbJLegvYVC9QjjZW2UDjtBUwcAkrghH0CgYBUMmMOCwIfMEtMaWxZRGdxRabazLhn7TXhBpVTuv7WouPaXYd7ZGjCTMKAuVa/E4afBlxgemnqBuX90gHpK/dDmn9l+lp8GZey0grJ7G0x5HEMiKziaX5PrgAcKbQ70m9ZNZ1deYhsC05X8rHNexZB6ns7Yms9L7qnlAy51ZH2zw==
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
secretClientKey := []byte(`-----BEGIN PRIVATE KEY-----
|
||||
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCi4cG2CxHejOXaWW0Xri4PbWyuainurCZuULPLC0jJsJF0zkq778O7JleWzh7QhqVBKKIhW6LNUVS9tmGHfHC7ufaHr9YtadzVkiDzQKtA0Cgcco98CfX7bzn5pZn/yfnbRN/aTyxT5335DFhHc0/FCJn2Q/5H9UtX6LR3H3zbT9Io32T0B6OAUKKB/3uzxAECFwwSK8UqGUee8JKGBrU10XRAMGxOc1BOWYpCHWZRH2FRGIgS+bwYHOXUjPv6FH7qx+wCMzlxqd9LGvic2CpFE0BiEsOLIiY/qEqozvd2aOLVhBPjT/9LTXvRZwX/qA7h4YIsnq5N8lN4ytryb13N9fdRVgymVykGkaAmh5zA4DIg48ULWzOfdPwRQ1kVq2TRmj3IlcJsNn6MgHJTbRqvCdJMyA59FUZC9+QHfC307sV2aWPoVTwuUyD3pOFu4K0LV+OKIVQ8OTOqApbnL9dOLVx4wFVYE32lTC4tRdxUU8MKiPEoT19A+bLMPrZHnqXCIRzLwwfewICgTNYNuDHV93OmqJK4IXcF8UG00v+pRw+umqXNxNkk0x3grfX5w0sBGZbyuojYHnQQx6wZfUl3mEzJ2zlmCB1/2GKtXn6tIDmRxzeJ2bgaKTjG/uCv9OGtp1VLmn3b/3qC+he4fv/lGh/zd/i5JMVgMXM9MPRlWQIDAQABAoICAAec04fllo03Oprs6QtdSavQ6m5wactM4nLvdKe9vEYo6XNzHM0R1K0PirJyqcAHOvwDoSg79yzvay1+s6o4Z7BubZZD4pe2xep5bO7Ri+94ixdhR1F9ybBZr3T6h2sMDpBv9KJoZuL5A8s7B3k3a3gDAecfoGfOkBnot16F6zj4zxK39ijtnnelzSKURTzOoVluqFLFFu7zxYQpLD/1WkzMoElLuhQkkZFH4A1dAGY0OEEpC1sPrvnVh+xaNoCmqpPgiihEKqAkV1pURWBXPgqCbtTmmZsMGouJGwwuuCQhnNBr3t4V5BGp6mqMDRy4xxFJj+Lz+6OK+tm/aWJBUDn38JK1rQLCA5W3BxMoit4745VWxJc9PX068w6YwBRpqhfg94qZBZHxDe+nQBBEguQ5kBhoBpx60Wscrkjvr4ggb4fzuU6JxLDIDuE2HMIO+EZXl9HEwOB4ImmJhFxcxC8QTU7MnMJ05SuafZDGM2YdmvP2D/BfZf3DlWvVGOnbGh0vUSVLeS5qBBSNAoeG2UR4T3MCXLSaa9+GqIqzti+euPXXAUSYAC+y1qkqkE9rsPezMmKOJmybBIBf40hVLge8fIZPZuvMSW7Sykuex/EjIDfjohAj7GAkrzXOTKlnz7vZAv6Y3EUsoEiVKh5vot+p9xn/XEYH8+JMsVqAABH9AoIBAQDY8VwccTRzYjMoKxhWXdXKvCAAFumo8uUowpJnbbkZfTbf8+75zwi/XXHn9nm9ON/7tUrWAzwuUvtKz4AiHmwHt/IiicEC8Vlyl7N0X40pW/wtcFZJarFQAmVoRiZAzyszqggv3cwCcf8o1ugaBh1Q83RoT8Fz72yI+J70ldiGsu86aZY4V7ApzPH2OHdNbLUDTKkiMUrS6io5DzIeDx4x4riu+GAqm33nhnYdk1nwx/EATixPqwTN62n6XKhE5QysrKlO2pUEr0YXypN6ynRYiCBPsh8OvnB+2ibkgBNQRicSkOBoSMl/1BI35rwmARl/qUoypqJEUO4pgBsCBLBTAoIBAQDANMp+6rluPLGYXLf4vqT7Zlr1EgHIl0aBWzcqQlpVr6UrgHaFnw+q9T/wg+oFM7zMD02oPjGnsKyL8zaIveUCKSYQFjlznvLnFWeLMTbnrjkMrsN3aLriQ+7w6TXZVuGpA1W+DdChKl0z4BDJiMuHcZjiX4F9jFEB4xhvbH54e947Vk16GZVflSCqcBOAhH8DtGC/fQK76g1ndIHZjmUP8f2yQA7NaLhNbnZp0N2AvXOLBu+pDOaAKheENUOMRkDA+pNkEP0Krr0eW+P5o1iIuqK09ILytyECmUGd+VV6ePPsNAc/rKt0lF7Adg4Ay16hgPHHLbM7j+vsZd7KLU4jAoIBAE33SBRMtv30v8/i1QdNB+WpgJKnqWf3i1X/v1/+dfRsJMmNwEf1GP61VZd45D2V8CFlATUyynEXj4pOUo1wg4Cuog25li05kdz2Gh9rq66+iT3HTqtp9bl8cvdrppnKGouhwvl467XBRGNoANhBdE3AgQhwCWViGY6MU4wxQjT+n61NfxhWo1ASgK7tkiq4M8GwzmQkdPCiCXSiOm/FHSPuiFMRnnYRlckccNymNT+si7eBYLltC/f5cAfzPuIrs0dnch2NvtqFJ1qrih8qHXAn0/zwVesVlBZyzmF2ifpii+5HNO8loY0YKUf/24SJBqHztF/JtS16LG2rxYkPKFMCggEAT7yW1RgjXSwosQCmAbd1UiYgTdLuknzPbxKcTBfCyhFYADgG82ANa+raX7kZ+JaCGFWw7b7/coXEzzpSwV+mBcN0WvAdXW3vbxZeIkyEbpDEchJ+XKdCAGQWWDMnd8anTypnA7VPe8zLZZ3q2PC7HrFtr1vXqHHxmUrQ9EiaHvmkNBGVirXaVhDTwGFGdeaBmtPV3xrJa5Opg+W9iLeeDYNir/QLMAPlkZnl3fgcLDBsIpz6B7OmXD0aDGrcXvE2I9jQFI9HqorbQiD07rdpHy/uGAvn1zFJrH5Pzm2FnI1ZBACBkVTcvDxhIo7XOFUmKPIJW4wF8wu94BBS4KTy6QKCAQEAiG8TYUEAcCTpPzRC6oMc3uD0ukxJIYm94MbGts7j9cb+kULoxHN9BjPTeNMcq2dHFZoobLt33YmqcRbH4bRenBGAu1iGCGJsVDnwsnGrThuWwhlQQSVetGaIT7ODjuR2KA9ms/U0jpuYmcXFnQtAs9jhZ2Hx2GkWyQkcTEyQalwqAl3kCv05VYlRGOaYZA31xNyUnsjL0AMLzOAs0+t+IPM12l4FCEXV83m10J5DTFxpb12jWHRwGNmDlsk/Mknlj4uQEvmr9iopnpZnFOgi+jvRmx1CBmARXoMz5D/Hh/EVuCwJS1vIytYsHsml0x2yRxDYxD0V44p//HS/dG4SsQ==
|
||||
-----END PRIVATE KEY-----`)
|
||||
clientCrt := []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIICsTCCAZkCFEJJ4daz5sxkFlzq9n1djLEuG7bmMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHZhdWx0LWNhMB4XDTIxMDcyMDA4MTQxM1oXDTIyMDcyMDA4MTQxM1owFzEVMBMGA1UEAwwMdmF1bHQtY2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArfZ4HV1obFVlVNiA24tX/UOakqRnEtWXpIvaOsMaPGvvODgGe4XnyJGO32idPv85sIr7vDH9p+OhactVlJV1fu5SZoZ7pg4jTCLqVDCb3IRD++yik2Sw58YayNe3HiaCTsJQWeMXLzfaqOeyk6bEpBCJo09+3QxUWxijgJ7YZCb+Gi8pf3ZWeSZG+rGNNvXHmTs1Yu1H849SYXu+uJOd/R3ZSTw8CxFe4eTLgbCnPf6tgA8Sg2hc+CAZxunPP2JLZWbiJXxjNRoypso6MAJ1FRkx5sTJiLg6UoLvd95/S/lCVOR2PDlM1hg7ox8VEd4QHky7tLx7gji/5hHQKJQSTwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAsDYKtzScIA7bqIOmqF8rr+oLSjRhPt5OfT+KGNdXk8G3VAy1ED2tyCHaRNC7dPLq4EvcxbIXQnXPy1iZMofriGbFPAcQ2fyWUesAD6bYSpI+bYxwz6Ebb93hU5nc/FyXg8yh0kgiGbY3MrACPjxqP2+z5kcOC3u3hx3SZylgW7TeOXDTdqSbNfH1b+1rR/bVNgQQshjhU9d+c4Yv/t0u07uykBhHLWZDSnYiAeOZ8+mWuOSDkcZHE1zznx74fWgtN0zRDtr0L0w9evT9R2CnNSZGxXcEQxAlQ7SL/Jyw82TFCGEw0L4jj7jjvx0N5J8KX/DulUDE9vuVyQEJ88Epe
|
||||
-----END CERTIFICATE-----
|
||||
`)
|
||||
MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDERMA8GA1UEAwwIdmF1bHQtY2EwHhcNMjIwNzI5MjEyMjE4WhcNMzkwMTAxMjEyMjE4WjBYMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMREwDwYDVQQDDAh2YXVsdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKLhwbYLEd6M5dpZbReuLg9tbK5qKe6sJm5Qs8sLSMmwkXTOSrvvw7smV5bOHtCGpUEooiFbos1RVL22YYd8cLu59oev1i1p3NWSIPNAq0DQKBxyj3wJ9ftvOfmlmf/J+dtE39pPLFPnffkMWEdzT8UImfZD/kf1S1fotHcffNtP0ijfZPQHo4BQooH/e7PEAQIXDBIrxSoZR57wkoYGtTXRdEAwbE5zUE5ZikIdZlEfYVEYiBL5vBgc5dSM+/oUfurH7AIzOXGp30sa+JzYKkUTQGISw4siJj+oSqjO93Zo4tWEE+NP/0tNe9FnBf+oDuHhgiyerk3yU3jK2vJvXc3191FWDKZXKQaRoCaHnMDgMiDjxQtbM590/BFDWRWrZNGaPciVwmw2foyAclNtGq8J0kzIDn0VRkL35Ad8LfTuxXZpY+hVPC5TIPek4W7grQtX44ohVDw5M6oClucv104tXHjAVVgTfaVMLi1F3FRTwwqI8ShPX0D5ssw+tkeepcIhHMvDB97AgKBM1g24MdX3c6aokrghdwXxQbTS/6lHD66apc3E2STTHeCt9fnDSwEZlvK6iNgedBDHrBl9SXeYTMnbOWYIHX/YYq1efq0gOZHHN4nZuBopOMb+4K/04a2nVUuafdv/eoL6F7h+/+UaH/N3+LkkxWAxcz0w9GVZAgMBAAGjUzBRMB0GA1UdDgQWBBQuIVwmjMZvkq+jf6ViTelH5KDBVDAfBgNVHSMEGDAWgBQuIVwmjMZvkq+jf6ViTelH5KDBVDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAk4kNyFzmiKnREmi5PPj7xGAtv2aJIdMEfcZJ9e+H0Nb2aCvMvZsDodduXu6G5+1opd45v0AeTjLBkXDO6/8vnyM32VZEEKCAwMCLcOLD1z0+r+gaurDYMOGU5qr8hQadHKFsxEDYnR/9KdHhBg6A8qE2cOQa1ryu34DnWQ3m0CBApClf1YBRp/4T8BmHumfH6odD96H30HVzINrd9WM2hR9GRE3xqQyfwlvqmGn9S6snSVa+mcJ6w2wNE2LPGx0kOtBeOIUdfSsEgvSRjbowSHz9lohFZ0LxJYyizCA5vnMmYyhhkfJqm7YtjHkGWgXmqpH9BFt0D3gfORlIh787nuWfxtZ+554rDyQmPjYQG/qF4+Awehr4RxiGWTox1C67G/RzA6TOXX09xuFY+3U1ich90/KffvhoHvRVfhzxx+HUUY2qSU3HqQDzgieQQBaMuOhd1i6pua+/kPSXkuXqnIs8daao/goR5iU/lPLs7M8Dy7xZ9adzbIPuNuzHir2UuvtPlW+x/sSvOnVL9r/7TrAuWhdScglQ70EInPDVX7BgDWKrZUh86N4d7fu2f/T+6VoUSGEjq8obCj3BQ61mNEoftKVECUO4MMUdat6pY/4Xh6Dwc+FnbvR2+sX7IzI7FtgOrfO6abT+LCAR0R+UXyvnqZcjK2zkHz4DfXFbCQg==
|
||||
-----END CERTIFICATE-----`)
|
||||
secretData := []byte(secretDataString)
|
||||
|
||||
cases := map[string]testCase{
|
||||
|
@ -271,13 +273,15 @@ MIICsTCCAZkCFEJJ4daz5sxkFlzq9n1djLEuG7bmMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHZh
|
|||
"GetKubeServiceAccountError": {
|
||||
reason: "Should return error if fetching kubernetes secret fails.",
|
||||
args: args{
|
||||
store: makeSecretStore(),
|
||||
newClientFunc: clientWithLoginMock,
|
||||
kube: &test.MockClient{
|
||||
MockGet: test.NewMockGetFn(errBoom),
|
||||
},
|
||||
store: makeSecretStore(),
|
||||
corev1: utilfake.NewCreateTokenMock().WithError(errBoom),
|
||||
},
|
||||
want: want{
|
||||
err: fmt.Errorf(errGetKubeSA, "example-sa", errBoom),
|
||||
err: fmt.Errorf(errGetKubeSATokenRequest, "example-sa", errBoom),
|
||||
},
|
||||
},
|
||||
"GetKubeSecretError": {
|
||||
|
@ -333,18 +337,10 @@ MIICsTCCAZkCFEJJ4daz5sxkFlzq9n1djLEuG7bmMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHZh
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if o, ok := obj.(*corev1.ServiceAccount); ok {
|
||||
o.Secrets = []corev1.ObjectReference{
|
||||
{
|
||||
Name: tokenSecretName,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
corev1: utilfake.NewCreateTokenMock().WithToken("ok"),
|
||||
newClientFunc: clientWithLoginMock,
|
||||
},
|
||||
want: want{
|
||||
|
@ -389,25 +385,10 @@ MIICsTCCAZkCFEJJ4daz5sxkFlzq9n1djLEuG7bmMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHZh
|
|||
return nil
|
||||
}
|
||||
|
||||
if o, ok := obj.(*corev1.ServiceAccount); ok {
|
||||
o.Secrets = []corev1.ObjectReference{
|
||||
{
|
||||
Name: tokenSecretName,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if o, ok := obj.(*corev1.Secret); ok {
|
||||
o.Data = map[string][]byte{
|
||||
"token": secretData,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
corev1: utilfake.NewCreateTokenMock().WithToken("ok"),
|
||||
newClientFunc: clientWithLoginMock,
|
||||
},
|
||||
want: want{
|
||||
|
@ -505,7 +486,7 @@ func vaultTest(t *testing.T, name string, tc testCase) {
|
|||
if tc.args.newClientFunc == nil {
|
||||
conn.newVaultClient = newVaultClient
|
||||
}
|
||||
_, err := conn.newClient(context.Background(), tc.args.store, tc.args.kube, nil, tc.args.ns)
|
||||
_, err := conn.newClient(context.Background(), tc.args.store, tc.args.kube, tc.args.corev1, tc.args.ns)
|
||||
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("\n%s\nvault.New(...): -want error, +got error:\n%s", tc.reason, diff)
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ func TestObjectHash(t *testing.T) {
|
|||
input: v1.Secret{Data: map[string][]byte{
|
||||
"xx": []byte("yyy"),
|
||||
}},
|
||||
want: "a9fe13fd43b20829b45f0a93372413dd",
|
||||
want: "7b6fb27a17a8e4a4be8fda6cb499f3d5",
|
||||
},
|
||||
{
|
||||
name: "map also works",
|
||||
|
|
Loading…
Reference in a new issue