1
0
Fork 0
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:
dependabot[bot] 2022-08-19 17:32:06 +02:00 committed by GitHub
parent 2d20b5488e
commit 67fedc840e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 3193 additions and 1508 deletions

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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"`

View file

@ -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"`
}

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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
View 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

File diff suppressed because it is too large Load diff

View file

@ -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=* \

View file

@ -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
View file

@ -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
)

799
go.sum

File diff suppressed because it is too large Load diff

View file

@ -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(),
}

View file

@ -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)

View file

@ -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 {

View file

@ -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)

View file

@ -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 {

View file

@ -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) {

View file

@ -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{},

View file

@ -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)
}

View file

@ -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

View file

@ -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)
}

View file

@ -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,

View 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
}

View file

@ -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 {

View file

@ -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
}

View 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
}

View 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)
}
})
}
}

View file

@ -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)
}

View file

@ -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,
}

View file

@ -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,

View file

@ -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
}

View file

@ -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)
}

View file

@ -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",