mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-15 17:51:01 +00:00
* add AuthRef to kubernetes provider fixes #3627 Signed-off-by: kaedwen <kaedwen@heinrich.blue> * run make reviewable Signed-off-by: kaedwen <kaedwen@heinrich.blue> * fix validation for given authRef Signed-off-by: kaedwen <kaedwen@heinrich.blue> * refactor kubernetes provider auth Signed-off-by: kaedwen <kaedwen@heinrich.blue> * satisfy linter Signed-off-by: kaedwen <kaedwen@heinrich.blue> * add URL for kubernetes provider tests Signed-off-by: kaedwen <kaedwen@heinrich.blue> --------- Signed-off-by: kaedwen <kaedwen@heinrich.blue>
This commit is contained in:
parent
c6bafe8c61
commit
48cccaeded
11 changed files with 401 additions and 94 deletions
|
@ -37,11 +37,17 @@ type KubernetesServer struct {
|
||||||
// Configures a store to sync secrets with a Kubernetes instance.
|
// Configures a store to sync secrets with a Kubernetes instance.
|
||||||
type KubernetesProvider struct {
|
type KubernetesProvider struct {
|
||||||
// configures the Kubernetes server Address.
|
// configures the Kubernetes server Address.
|
||||||
|
// +optional
|
||||||
Server KubernetesServer `json:"server,omitempty"`
|
Server KubernetesServer `json:"server,omitempty"`
|
||||||
|
|
||||||
// Auth configures how secret-manager authenticates with a Kubernetes instance.
|
// Auth configures how secret-manager authenticates with a Kubernetes instance.
|
||||||
|
// +optional
|
||||||
Auth KubernetesAuth `json:"auth"`
|
Auth KubernetesAuth `json:"auth"`
|
||||||
|
|
||||||
|
// A reference to a secret that contains the auth information.
|
||||||
|
// +optional
|
||||||
|
AuthRef *esmeta.SecretKeySelector `json:"authRef,omitempty"`
|
||||||
|
|
||||||
// Remote namespace to fetch the secrets from
|
// Remote namespace to fetch the secrets from
|
||||||
// +kubebuilder:default= default
|
// +kubebuilder:default= default
|
||||||
// +optional
|
// +optional
|
||||||
|
|
|
@ -1858,6 +1858,11 @@ func (in *KubernetesProvider) DeepCopyInto(out *KubernetesProvider) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Server.DeepCopyInto(&out.Server)
|
in.Server.DeepCopyInto(&out.Server)
|
||||||
in.Auth.DeepCopyInto(&out.Auth)
|
in.Auth.DeepCopyInto(&out.Auth)
|
||||||
|
if in.AuthRef != nil {
|
||||||
|
in, out := &in.AuthRef, &out.AuthRef
|
||||||
|
*out = new(metav1.SecretKeySelector)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesProvider.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesProvider.
|
||||||
|
|
|
@ -3199,6 +3199,25 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
|
authRef:
|
||||||
|
description: A reference to a secret that contains the auth
|
||||||
|
information.
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: |-
|
||||||
|
The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be
|
||||||
|
defaulted, in others it may be required.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: The name of the Secret resource being referred
|
||||||
|
to.
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: |-
|
||||||
|
Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults
|
||||||
|
to the namespace of the referent.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
remoteNamespace:
|
remoteNamespace:
|
||||||
default: default
|
default: default
|
||||||
description: Remote namespace to fetch the secrets from
|
description: Remote namespace to fetch the secrets from
|
||||||
|
@ -3242,8 +3261,6 @@ spec:
|
||||||
description: configures the Kubernetes server Address.
|
description: configures the Kubernetes server Address.
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
|
||||||
- auth
|
|
||||||
type: object
|
type: object
|
||||||
onboardbase:
|
onboardbase:
|
||||||
description: Onboardbase configures this store to sync secrets
|
description: Onboardbase configures this store to sync secrets
|
||||||
|
|
|
@ -3199,6 +3199,25 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
|
authRef:
|
||||||
|
description: A reference to a secret that contains the auth
|
||||||
|
information.
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: |-
|
||||||
|
The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be
|
||||||
|
defaulted, in others it may be required.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: The name of the Secret resource being referred
|
||||||
|
to.
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: |-
|
||||||
|
Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults
|
||||||
|
to the namespace of the referent.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
remoteNamespace:
|
remoteNamespace:
|
||||||
default: default
|
default: default
|
||||||
description: Remote namespace to fetch the secrets from
|
description: Remote namespace to fetch the secrets from
|
||||||
|
@ -3242,8 +3261,6 @@ spec:
|
||||||
description: configures the Kubernetes server Address.
|
description: configures the Kubernetes server Address.
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
|
||||||
- auth
|
|
||||||
type: object
|
type: object
|
||||||
onboardbase:
|
onboardbase:
|
||||||
description: Onboardbase configures this store to sync secrets
|
description: Onboardbase configures this store to sync secrets
|
||||||
|
|
|
@ -3634,6 +3634,23 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
|
authRef:
|
||||||
|
description: A reference to a secret that contains the auth information.
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: |-
|
||||||
|
The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be
|
||||||
|
defaulted, in others it may be required.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: The name of the Secret resource being referred to.
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: |-
|
||||||
|
Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults
|
||||||
|
to the namespace of the referent.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
remoteNamespace:
|
remoteNamespace:
|
||||||
default: default
|
default: default
|
||||||
description: Remote namespace to fetch the secrets from
|
description: Remote namespace to fetch the secrets from
|
||||||
|
@ -3674,8 +3691,6 @@ spec:
|
||||||
description: configures the Kubernetes server Address.
|
description: configures the Kubernetes server Address.
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
|
||||||
- auth
|
|
||||||
type: object
|
type: object
|
||||||
onboardbase:
|
onboardbase:
|
||||||
description: Onboardbase configures this store to sync secrets using the Onboardbase provider
|
description: Onboardbase configures this store to sync secrets using the Onboardbase provider
|
||||||
|
@ -9182,6 +9197,23 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
|
authRef:
|
||||||
|
description: A reference to a secret that contains the auth information.
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: |-
|
||||||
|
The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be
|
||||||
|
defaulted, in others it may be required.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: The name of the Secret resource being referred to.
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: |-
|
||||||
|
Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults
|
||||||
|
to the namespace of the referent.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
remoteNamespace:
|
remoteNamespace:
|
||||||
default: default
|
default: default
|
||||||
description: Remote namespace to fetch the secrets from
|
description: Remote namespace to fetch the secrets from
|
||||||
|
@ -9222,8 +9254,6 @@ spec:
|
||||||
description: configures the Kubernetes server Address.
|
description: configures the Kubernetes server Address.
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
|
||||||
- auth
|
|
||||||
type: object
|
type: object
|
||||||
onboardbase:
|
onboardbase:
|
||||||
description: Onboardbase configures this store to sync secrets using the Onboardbase provider
|
description: Onboardbase configures this store to sync secrets using the Onboardbase provider
|
||||||
|
|
|
@ -4864,6 +4864,7 @@ KubernetesServer
|
||||||
</em>
|
</em>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<em>(Optional)</em>
|
||||||
<p>configures the Kubernetes server Address.</p>
|
<p>configures the Kubernetes server Address.</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -4877,11 +4878,26 @@ KubernetesAuth
|
||||||
</em>
|
</em>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<em>(Optional)</em>
|
||||||
<p>Auth configures how secret-manager authenticates with a Kubernetes instance.</p>
|
<p>Auth configures how secret-manager authenticates with a Kubernetes instance.</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
<code>authRef</code></br>
|
||||||
|
<em>
|
||||||
|
<a href="https://pkg.go.dev/github.com/external-secrets/external-secrets/apis/meta/v1#SecretKeySelector">
|
||||||
|
External Secrets meta/v1.SecretKeySelector
|
||||||
|
</a>
|
||||||
|
</em>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<em>(Optional)</em>
|
||||||
|
<p>A reference to a secret that contains the auth information.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
<code>remoteNamespace</code></br>
|
<code>remoteNamespace</code></br>
|
||||||
<em>
|
<em>
|
||||||
string
|
string
|
||||||
|
|
|
@ -22,6 +22,8 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
|
||||||
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
|
||||||
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
|
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||||
|
@ -36,35 +38,63 @@ const (
|
||||||
errUnableCreateToken = "cannot create service account token: %q"
|
errUnableCreateToken = "cannot create service account token: %q"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) setAuth(ctx context.Context) error {
|
func (c *Client) getAuth(ctx context.Context) (*rest.Config, error) {
|
||||||
err := c.setCA(ctx)
|
if c.store.AuthRef != nil {
|
||||||
|
cfg, err := c.fetchSecretKey(ctx, *c.store.AuthRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return clientcmd.RESTConfigFromKubeConfig(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
ca, err := c.getCA(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var token []byte
|
||||||
if c.store.Auth.Token != nil {
|
if c.store.Auth.Token != nil {
|
||||||
c.BearerToken, err = c.fetchSecretKey(ctx, c.store.Auth.Token.BearerToken)
|
token, err = c.fetchSecretKey(ctx, c.store.Auth.Token.BearerToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not fetch Auth.Token.BearerToken: %w", err)
|
return nil, fmt.Errorf("could not fetch Auth.Token.BearerToken: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
} else if c.store.Auth.ServiceAccount != nil {
|
||||||
}
|
token, err = c.serviceAccountToken(ctx, c.store.Auth.ServiceAccount)
|
||||||
if c.store.Auth.ServiceAccount != nil {
|
|
||||||
c.BearerToken, err = c.serviceAccountToken(ctx, c.store.Auth.ServiceAccount)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not fetch Auth.ServiceAccount: %w", err)
|
return nil, fmt.Errorf("could not fetch Auth.ServiceAccount: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
} else {
|
||||||
|
return nil, fmt.Errorf("no auth provider given")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var key, cert []byte
|
||||||
if c.store.Auth.Cert != nil {
|
if c.store.Auth.Cert != nil {
|
||||||
return c.setClientCert(ctx)
|
key, cert, err = c.getClientKeyAndCert(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not fetch client key and cert: %w", err)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("no credentials provided")
|
}
|
||||||
|
|
||||||
|
if c.store.Server.URL == "" {
|
||||||
|
return nil, fmt.Errorf("no server URL provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rest.Config{
|
||||||
|
Host: c.store.Server.URL,
|
||||||
|
BearerToken: string(token),
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
Insecure: false,
|
||||||
|
CertData: cert,
|
||||||
|
KeyData: key,
|
||||||
|
CAData: ca,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) setCA(ctx context.Context) error {
|
func (c *Client) getCA(ctx context.Context) ([]byte, error) {
|
||||||
if c.store.Server.CABundle != nil {
|
if c.store.Server.CABundle != nil {
|
||||||
c.CA = c.store.Server.CABundle
|
return c.store.Server.CABundle, nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
if c.store.Server.CAProvider != nil {
|
if c.store.Server.CAProvider != nil {
|
||||||
var ca []byte
|
var ca []byte
|
||||||
|
@ -78,7 +108,7 @@ func (c *Client) setCA(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
ca, err = c.fetchConfigMapKey(ctx, keySelector)
|
ca, err = c.fetchConfigMapKey(ctx, keySelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch Server.CAProvider ConfigMap: %w", err)
|
return nil, fmt.Errorf("unable to fetch Server.CAProvider ConfigMap: %w", err)
|
||||||
}
|
}
|
||||||
case esv1beta1.CAProviderTypeSecret:
|
case esv1beta1.CAProviderTypeSecret:
|
||||||
keySelector := esmeta.SecretKeySelector{
|
keySelector := esmeta.SecretKeySelector{
|
||||||
|
@ -88,26 +118,25 @@ func (c *Client) setCA(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
ca, err = c.fetchSecretKey(ctx, keySelector)
|
ca, err = c.fetchSecretKey(ctx, keySelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch Server.CAProvider Secret: %w", err)
|
return nil, fmt.Errorf("unable to fetch Server.CAProvider Secret: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.CA = ca
|
return ca, nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return fmt.Errorf("no Certificate Authority provided")
|
return nil, fmt.Errorf("no Certificate Authority provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) setClientCert(ctx context.Context) error {
|
func (c *Client) getClientKeyAndCert(ctx context.Context) ([]byte, []byte, error) {
|
||||||
var err error
|
var err error
|
||||||
c.Certificate, err = c.fetchSecretKey(ctx, c.store.Auth.Cert.ClientCert)
|
cert, err := c.fetchSecretKey(ctx, c.store.Auth.Cert.ClientCert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch client certificate: %w", err)
|
return nil, nil, fmt.Errorf("unable to fetch client certificate: %w", err)
|
||||||
}
|
}
|
||||||
c.Key, err = c.fetchSecretKey(ctx, c.store.Auth.Cert.ClientKey)
|
key, err := c.fetchSecretKey(ctx, c.store.Auth.Cert.ClientKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to fetch client key: %w", err)
|
return nil, nil, fmt.Errorf("unable to fetch client key: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return key, cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) serviceAccountToken(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) ([]byte, error) {
|
func (c *Client) serviceAccountToken(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) ([]byte, error) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
pointer "k8s.io/utils/ptr"
|
pointer "k8s.io/utils/ptr"
|
||||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
fclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
fclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||||
|
@ -31,6 +32,43 @@ import (
|
||||||
utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake"
|
utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
caCert = `-----BEGIN CERTIFICATE-----
|
||||||
|
MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
|
||||||
|
CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
|
||||||
|
Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
|
||||||
|
MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
|
||||||
|
bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
|
||||||
|
ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
|
||||||
|
7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
|
||||||
|
0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
|
||||||
|
B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
|
||||||
|
BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
|
||||||
|
LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
|
||||||
|
DXZDjC5Ty3zfDBeWUA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
`
|
||||||
|
authTestKubeConfig = `apiVersion: v1
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
server: https://api.my-domain.tld
|
||||||
|
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNHVENDQVorZ0F3SUJBZ0lRQ2VDVFphejMyY2k1UGh3TEJDb3U4ekFLQmdncWhrak9QUVFEQXpCT01Rc3cKQ1FZRFZRUUdFd0pWVXpFWE1CVUdBMVVFQ2hNT1JHbG5hVU5sY25Rc0lFbHVZeTR4SmpBa0JnTlZCQU1USFVScApaMmxEWlhKMElGUk1VeUJGUTBNZ1VETTROQ0JTYjI5MElFYzFNQjRYRFRJeE1ERXhOVEF3TURBd01Gb1hEVFEyCk1ERXhOREl6TlRrMU9Wb3dUakVMTUFrR0ExVUVCaE1DVlZNeEZ6QVZCZ05WQkFvVERrUnBaMmxEWlhKMExDQkoKYm1NdU1TWXdKQVlEVlFRREV4MUVhV2RwUTJWeWRDQlVURk1nUlVORElGQXpPRFFnVW05dmRDQkhOVEIyTUJBRwpCeXFHU000OUFnRUdCU3VCQkFBaUEySUFCTUZFb2M4UmwxQ2EzaU9DTlFmTjBNc1luZEx4ZjNjMVR6dmRsSEpTCjdjSTcrT3o2ZTJ0WUlPeVpyc244YUxOMXVkc0o3TWdUOVU3R0NoMW1NRXk3SDBjS1BHRVFRaWw4cFFnTzRDTHAKMHpWb3pwdGpuNFMxbVUxWW9JNzFWT2VWeWFOQ01FQXdIUVlEVlIwT0JCWUVGTUZSUlZCWnF6N25MRnI2SUNJUwpCNENJZkJGcU1BNEdBMVVkRHdFQi93UUVBd0lCaGpBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5CkJBTURBMmdBTUdVQ01RQ0phbzFINSt6OGJsVUQyV2RzSms2RHh2M0oreXNUdkxkNmpMUmwwbWxwWXhOak95WlEKTGdHaGVRYVJuVWkvd3I0Q01FZkRGWHV4b0pHWlNaT29QSHpvUmdhTExQSXhBSlNkWXNpSnZSbUVGT21sK3dHNApEWFpEakM1VHkzemZEQmVXVUE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||||
|
name: mycluster
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: mycluster
|
||||||
|
user: myuser
|
||||||
|
name: mycontext
|
||||||
|
current-context: mycontext
|
||||||
|
kind: Config
|
||||||
|
preferences: {}
|
||||||
|
users:
|
||||||
|
- name: myuser
|
||||||
|
user:
|
||||||
|
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE3MTkzOTY4OTksImV4cCI6MTc1MDkzMjg4NywiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.xXrfIl0akhfjWU_BDl7Ad54SXje0YlJdnugzwh96VmM
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
func TestSetAuth(t *testing.T) {
|
func TestSetAuth(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
kube kclient.Client
|
kube kclient.Client
|
||||||
|
@ -39,16 +77,11 @@ func TestSetAuth(t *testing.T) {
|
||||||
namespace string
|
namespace string
|
||||||
storeKind string
|
storeKind string
|
||||||
}
|
}
|
||||||
type want struct {
|
type want = rest.Config
|
||||||
Certificate []byte
|
|
||||||
Key []byte
|
|
||||||
CA []byte
|
|
||||||
BearerToken []byte
|
|
||||||
}
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fields fields
|
fields fields
|
||||||
want want
|
want *want
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -58,7 +91,7 @@ func TestSetAuth(t *testing.T) {
|
||||||
Server: esv1beta1.KubernetesServer{},
|
Server: esv1beta1.KubernetesServer{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: want{},
|
want: nil,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -70,9 +103,7 @@ func TestSetAuth(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: want{
|
want: nil,
|
||||||
CA: []byte("1234"),
|
|
||||||
},
|
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -86,28 +117,51 @@ func TestSetAuth(t *testing.T) {
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"cert": []byte("1234"),
|
"cert": []byte("1234"),
|
||||||
|
"token": []byte("mytoken"),
|
||||||
},
|
},
|
||||||
}).Build(),
|
}).Build(),
|
||||||
store: &esv1beta1.KubernetesProvider{
|
store: &esv1beta1.KubernetesProvider{
|
||||||
Server: esv1beta1.KubernetesServer{
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
CAProvider: &esv1beta1.CAProvider{
|
CAProvider: &esv1beta1.CAProvider{
|
||||||
Type: esv1beta1.CAProviderTypeSecret,
|
Type: esv1beta1.CAProviderTypeSecret,
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Key: "cert",
|
Key: "cert",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Auth: esv1beta1.KubernetesAuth{
|
||||||
|
Token: &esv1beta1.TokenAuth{
|
||||||
|
BearerToken: v1.SecretKeySelector{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: pointer.To("shouldnotberelevant"),
|
||||||
|
Key: "token",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: want{
|
|
||||||
CA: []byte("1234"),
|
|
||||||
},
|
},
|
||||||
wantErr: true,
|
},
|
||||||
|
},
|
||||||
|
want: &want{
|
||||||
|
Host: "https://my.test.tld",
|
||||||
|
BearerToken: "mytoken",
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: []byte("1234"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "should fetch ca from ConfigMap",
|
name: "should fetch ca from ConfigMap",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
namespace: "default",
|
namespace: "default",
|
||||||
kube: fclient.NewClientBuilder().WithObjects(&corev1.ConfigMap{
|
kube: fclient.NewClientBuilder().WithObjects(&corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"token": []byte("mytoken"),
|
||||||
|
},
|
||||||
|
}, &corev1.ConfigMap{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
|
@ -118,18 +172,32 @@ func TestSetAuth(t *testing.T) {
|
||||||
}).Build(),
|
}).Build(),
|
||||||
store: &esv1beta1.KubernetesProvider{
|
store: &esv1beta1.KubernetesProvider{
|
||||||
Server: esv1beta1.KubernetesServer{
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
CAProvider: &esv1beta1.CAProvider{
|
CAProvider: &esv1beta1.CAProvider{
|
||||||
Type: esv1beta1.CAProviderTypeConfigMap,
|
Type: esv1beta1.CAProviderTypeConfigMap,
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Key: "cert",
|
Key: "cert",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Auth: esv1beta1.KubernetesAuth{
|
||||||
|
Token: &esv1beta1.TokenAuth{
|
||||||
|
BearerToken: v1.SecretKeySelector{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: pointer.To("shouldnotberelevant"),
|
||||||
|
Key: "token",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: want{
|
|
||||||
CA: []byte("1234"),
|
|
||||||
},
|
},
|
||||||
wantErr: true,
|
},
|
||||||
|
},
|
||||||
|
want: &want{
|
||||||
|
Host: "https://my.test.tld",
|
||||||
|
BearerToken: "mytoken",
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: []byte("1234"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "should set token from secret",
|
name: "should set token from secret",
|
||||||
|
@ -146,6 +214,7 @@ func TestSetAuth(t *testing.T) {
|
||||||
}).Build(),
|
}).Build(),
|
||||||
store: &esv1beta1.KubernetesProvider{
|
store: &esv1beta1.KubernetesProvider{
|
||||||
Server: esv1beta1.KubernetesServer{
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
CABundle: []byte("1234"),
|
CABundle: []byte("1234"),
|
||||||
},
|
},
|
||||||
Auth: esv1beta1.KubernetesAuth{
|
Auth: esv1beta1.KubernetesAuth{
|
||||||
|
@ -159,9 +228,12 @@ func TestSetAuth(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: want{
|
want: &want{
|
||||||
CA: []byte("1234"),
|
Host: "https://my.test.tld",
|
||||||
BearerToken: []byte("mytoken"),
|
BearerToken: "mytoken",
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: []byte("1234"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
@ -178,12 +250,28 @@ func TestSetAuth(t *testing.T) {
|
||||||
"cert": []byte("my-cert"),
|
"cert": []byte("my-cert"),
|
||||||
"key": []byte("my-key"),
|
"key": []byte("my-key"),
|
||||||
},
|
},
|
||||||
|
}, &corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"token": []byte("mytoken"),
|
||||||
|
},
|
||||||
}).Build(),
|
}).Build(),
|
||||||
store: &esv1beta1.KubernetesProvider{
|
store: &esv1beta1.KubernetesProvider{
|
||||||
Server: esv1beta1.KubernetesServer{
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
CABundle: []byte("1234"),
|
CABundle: []byte("1234"),
|
||||||
},
|
},
|
||||||
Auth: esv1beta1.KubernetesAuth{
|
Auth: esv1beta1.KubernetesAuth{
|
||||||
|
Token: &esv1beta1.TokenAuth{
|
||||||
|
BearerToken: v1.SecretKeySelector{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: pointer.To("shouldnotberelevant"),
|
||||||
|
Key: "token",
|
||||||
|
},
|
||||||
|
},
|
||||||
Cert: &esv1beta1.CertAuth{
|
Cert: &esv1beta1.CertAuth{
|
||||||
ClientCert: v1.SecretKeySelector{
|
ClientCert: v1.SecretKeySelector{
|
||||||
Name: "mycert",
|
Name: "mycert",
|
||||||
|
@ -197,15 +285,52 @@ func TestSetAuth(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: want{
|
want: &want{
|
||||||
CA: []byte("1234"),
|
Host: "https://my.test.tld",
|
||||||
Certificate: []byte("my-cert"),
|
BearerToken: "mytoken",
|
||||||
Key: []byte("my-key"),
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: []byte("1234"),
|
||||||
|
CertData: []byte("my-cert"),
|
||||||
|
KeyData: []byte("my-key"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "should set token from service account",
|
name: "should set token from service account",
|
||||||
|
fields: fields{
|
||||||
|
namespace: "default",
|
||||||
|
kube: fclient.NewClientBuilder().WithObjects(&corev1.ServiceAccount{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-sa",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
}).Build(),
|
||||||
|
kubeclientset: utilfake.NewCreateTokenMock().WithToken("my-sa-token"),
|
||||||
|
store: &esv1beta1.KubernetesProvider{
|
||||||
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
|
CABundle: []byte("1234"),
|
||||||
|
},
|
||||||
|
Auth: esv1beta1.KubernetesAuth{
|
||||||
|
ServiceAccount: &v1.ServiceAccountSelector{
|
||||||
|
Name: "my-sa",
|
||||||
|
Namespace: pointer.To("shouldnotberelevant"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: &want{
|
||||||
|
Host: "https://my.test.tld",
|
||||||
|
BearerToken: "my-sa-token",
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: []byte("1234"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail with missing URL",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
namespace: "default",
|
namespace: "default",
|
||||||
kube: fclient.NewClientBuilder().WithObjects(&corev1.ServiceAccount{
|
kube: fclient.NewClientBuilder().WithObjects(&corev1.ServiceAccount{
|
||||||
|
@ -227,9 +352,36 @@ func TestSetAuth(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: want{
|
want: nil,
|
||||||
CA: []byte("1234"),
|
wantErr: true,
|
||||||
BearerToken: []byte("my-sa-token"),
|
},
|
||||||
|
{
|
||||||
|
name: "should read config from secret",
|
||||||
|
fields: fields{
|
||||||
|
namespace: "default",
|
||||||
|
kube: fclient.NewClientBuilder().WithObjects(&corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"config": []byte(authTestKubeConfig),
|
||||||
|
},
|
||||||
|
}).Build(),
|
||||||
|
store: &esv1beta1.KubernetesProvider{
|
||||||
|
AuthRef: &v1.SecretKeySelector{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: pointer.To("default"),
|
||||||
|
Key: "config",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: &want{
|
||||||
|
Host: "https://api.my-domain.tld",
|
||||||
|
BearerToken: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE3MTkzOTY4OTksImV4cCI6MTc1MDkzMjg4NywiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.xXrfIl0akhfjWU_BDl7Ad54SXje0YlJdnugzwh96VmM",
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: []byte(caCert),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
@ -243,17 +395,12 @@ func TestSetAuth(t *testing.T) {
|
||||||
namespace: tt.fields.namespace,
|
namespace: tt.fields.namespace,
|
||||||
storeKind: tt.fields.storeKind,
|
storeKind: tt.fields.storeKind,
|
||||||
}
|
}
|
||||||
if err := k.setAuth(context.Background()); (err != nil) != tt.wantErr {
|
cfg, err := k.getAuth(context.Background())
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("BaseClient.setAuth() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("BaseClient.setAuth() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
w := want{
|
if !cmp.Equal(cfg, tt.want) {
|
||||||
Certificate: k.Certificate,
|
t.Errorf("unexpected value: expected %#v, got %#v", tt.want, cfg)
|
||||||
Key: k.Key,
|
|
||||||
CA: k.CA,
|
|
||||||
BearerToken: k.BearerToken,
|
|
||||||
}
|
|
||||||
if !cmp.Equal(w, tt.want) {
|
|
||||||
t.Errorf("unexpected value: expected %#v, got %#v", tt.want, w)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/client-go/rest"
|
|
||||||
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
kclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
|
ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||||
|
|
||||||
|
@ -74,10 +73,6 @@ type Client struct {
|
||||||
// namespace is the namespace of the
|
// namespace is the namespace of the
|
||||||
// ExternalSecret referencing this provider.
|
// ExternalSecret referencing this provider.
|
||||||
namespace string
|
namespace string
|
||||||
Certificate []byte
|
|
||||||
Key []byte
|
|
||||||
CA []byte
|
|
||||||
BearerToken []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -123,22 +118,12 @@ func (p *Provider) newClient(ctx context.Context, store esv1beta1.GenericStore,
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.setAuth(ctx); err != nil {
|
cfg, err := client.getAuth(ctx)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to prepare auth: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &rest.Config{
|
userClientset, err := kubernetes.NewForConfig(cfg)
|
||||||
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error configuring clientset: %w", err)
|
return nil, fmt.Errorf("error configuring clientset: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,24 @@ mv+AggtK0aRFb9o47z/BypLdk5mhbf3Mmr88C8XBzEnfdYyf4JpTlZrYLBmDCu5d
|
||||||
9RLLsjXxhag8xqMtd1uLUM8XOTGzVWacw8iGY+CTtBKqyA+AE6/bDwZvEwVtsKtC
|
9RLLsjXxhag8xqMtd1uLUM8XOTGzVWacw8iGY+CTtBKqyA+AE6/bDwZvEwVtsKtC
|
||||||
QJ85ioEpy00NioqcF0WyMZH80uMsPycfpnl5uF7RkW8u
|
QJ85ioEpy00NioqcF0WyMZH80uMsPycfpnl5uF7RkW8u
|
||||||
-----END CERTIFICATE-----`
|
-----END CERTIFICATE-----`
|
||||||
|
testKubeConfig = `apiVersion: v1
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
server: https://api.my-domain.tld
|
||||||
|
name: mycluster
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: mycluster
|
||||||
|
user: myuser
|
||||||
|
name: mycontext
|
||||||
|
current-context: mycontext
|
||||||
|
kind: Config
|
||||||
|
preferences: {}
|
||||||
|
users:
|
||||||
|
- name: myuser
|
||||||
|
user:
|
||||||
|
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE3MTkzOTY4OTksImV4cCI6MTc1MDkzMjg4NywiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.xXrfIl0akhfjWU_BDl7Ad54SXje0YlJdnugzwh96VmM
|
||||||
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewClient(t *testing.T) {
|
func TestNewClient(t *testing.T) {
|
||||||
|
@ -88,6 +106,40 @@ func TestNewClient(t *testing.T) {
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "test auth ref",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
store: &esv1beta1.ClusterSecretStore{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: esv1beta1.ClusterSecretStoreKind,
|
||||||
|
},
|
||||||
|
Spec: esv1beta1.SecretStoreSpec{
|
||||||
|
Provider: &esv1beta1.SecretStoreProvider{
|
||||||
|
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||||
|
AuthRef: &v1.SecretKeySelector{
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: pointer.To("default"),
|
||||||
|
Key: "config",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
namespace: "",
|
||||||
|
kube: fclient.NewClientBuilder().WithObjects(&corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"config": []byte(testKubeConfig),
|
||||||
|
},
|
||||||
|
}).Build(),
|
||||||
|
clientset: clientgofake.NewSimpleClientset(),
|
||||||
|
},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "test referent auth return",
|
name: "test referent auth return",
|
||||||
fields: fields{},
|
fields: fields{},
|
||||||
|
@ -100,6 +152,7 @@ func TestNewClient(t *testing.T) {
|
||||||
Provider: &esv1beta1.SecretStoreProvider{
|
Provider: &esv1beta1.SecretStoreProvider{
|
||||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||||
Server: esv1beta1.KubernetesServer{
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
CABundle: []byte(testCertificate),
|
CABundle: []byte(testCertificate),
|
||||||
},
|
},
|
||||||
Auth: esv1beta1.KubernetesAuth{
|
Auth: esv1beta1.KubernetesAuth{
|
||||||
|
@ -132,6 +185,7 @@ func TestNewClient(t *testing.T) {
|
||||||
Provider: &esv1beta1.SecretStoreProvider{
|
Provider: &esv1beta1.SecretStoreProvider{
|
||||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||||
Server: esv1beta1.KubernetesServer{
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
CABundle: []byte(testCertificate),
|
CABundle: []byte(testCertificate),
|
||||||
},
|
},
|
||||||
RemoteNamespace: "remote",
|
RemoteNamespace: "remote",
|
||||||
|
@ -166,6 +220,7 @@ func TestNewClient(t *testing.T) {
|
||||||
Provider: &esv1beta1.SecretStoreProvider{
|
Provider: &esv1beta1.SecretStoreProvider{
|
||||||
Kubernetes: &esv1beta1.KubernetesProvider{
|
Kubernetes: &esv1beta1.KubernetesProvider{
|
||||||
Server: esv1beta1.KubernetesServer{
|
Server: esv1beta1.KubernetesServer{
|
||||||
|
URL: "https://my.test.tld",
|
||||||
CABundle: []byte(testCertificate),
|
CABundle: []byte(testCertificate),
|
||||||
},
|
},
|
||||||
RemoteNamespace: "remote",
|
RemoteNamespace: "remote",
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
|
func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
|
||||||
storeSpec := store.GetSpec()
|
storeSpec := store.GetSpec()
|
||||||
k8sSpec := storeSpec.Provider.Kubernetes
|
k8sSpec := storeSpec.Provider.Kubernetes
|
||||||
if k8sSpec.Server.CABundle == nil && k8sSpec.Server.CAProvider == nil {
|
if k8sSpec.AuthRef == nil && k8sSpec.Server.CABundle == nil && k8sSpec.Server.CAProvider == nil {
|
||||||
return nil, fmt.Errorf("a CABundle or CAProvider is required")
|
return nil, fmt.Errorf("a CABundle or CAProvider is required")
|
||||||
}
|
}
|
||||||
if store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind &&
|
if store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind &&
|
||||||
|
|
Loading…
Reference in a new issue