mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-15 17:51:01 +00:00
fix: loosen validation to enable referent auth.
also adding tests for vault. this is the only provider that supports that as of now. Signed-off-by: Moritz Johner <beller.moritz@googlemail.com>
This commit is contained in:
parent
8e0a5b96c6
commit
8c14f8aff0
7 changed files with 185 additions and 26 deletions
|
@ -21,8 +21,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// Ready indicates that the client is confgured correctly
|
||||||
|
// and can be used.
|
||||||
ValidationResultReady ValidationResult = iota
|
ValidationResultReady ValidationResult = iota
|
||||||
|
|
||||||
|
// Unknown indicates that the client can be used
|
||||||
|
// but information is missing and it can not be validated.
|
||||||
ValidationResultUnknown
|
ValidationResultUnknown
|
||||||
|
|
||||||
|
// Error indicates that there is a misconfiguration.
|
||||||
ValidationResultError
|
ValidationResultError
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
52
docs/spec.md
52
docs/spec.md
|
@ -1552,14 +1552,16 @@ string
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<code>version</code></br>
|
<code>metadataPolicy</code></br>
|
||||||
<em>
|
<em>
|
||||||
string
|
<a href="#external-secrets.io/v1beta1.ExternalSecretMetadataPolicy">
|
||||||
|
ExternalSecretMetadataPolicy
|
||||||
|
</a>
|
||||||
</em>
|
</em>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<em>(Optional)</em>
|
<em>(Optional)</em>
|
||||||
<p>Used to select a specific version of the Provider value, if supported</p>
|
<p>Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -1576,6 +1578,18 @@ string
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
<code>version</code></br>
|
||||||
|
<em>
|
||||||
|
string
|
||||||
|
</em>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<em>(Optional)</em>
|
||||||
|
<p>Used to select a specific version of the Provider value, if supported</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
<code>conversionStrategy</code></br>
|
<code>conversionStrategy</code></br>
|
||||||
<em>
|
<em>
|
||||||
<a href="#external-secrets.io/v1beta1.ExternalSecretConversionStrategy">
|
<a href="#external-secrets.io/v1beta1.ExternalSecretConversionStrategy">
|
||||||
|
@ -1695,6 +1709,27 @@ ExternalSecretConversionStrategy
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<h3 id="external-secrets.io/v1beta1.ExternalSecretMetadataPolicy">ExternalSecretMetadataPolicy
|
||||||
|
(<code>string</code> alias)</p></h3>
|
||||||
|
<p>
|
||||||
|
(<em>Appears on:</em>
|
||||||
|
<a href="#external-secrets.io/v1beta1.ExternalSecretDataRemoteRef">ExternalSecretDataRemoteRef</a>)
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Value</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody><tr><td><p>"Fetch"</p></td>
|
||||||
|
<td></td>
|
||||||
|
</tr><tr><td><p>"None"</p></td>
|
||||||
|
<td></td>
|
||||||
|
</tr></tbody>
|
||||||
|
</table>
|
||||||
<h3 id="external-secrets.io/v1beta1.ExternalSecretSpec">ExternalSecretSpec
|
<h3 id="external-secrets.io/v1beta1.ExternalSecretSpec">ExternalSecretSpec
|
||||||
</h3>
|
</h3>
|
||||||
<p>
|
<p>
|
||||||
|
@ -4075,11 +4110,16 @@ github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody><tr><td><p>2</p></td>
|
<tbody><tr><td><p>2</p></td>
|
||||||
<td></td>
|
<td><p>Error indicates that there is a misconfiguration.</p>
|
||||||
|
</td>
|
||||||
</tr><tr><td><p>0</p></td>
|
</tr><tr><td><p>0</p></td>
|
||||||
<td></td>
|
<td><p>Ready indicates that the client is confgured correctly
|
||||||
|
and can be used.</p>
|
||||||
|
</td>
|
||||||
</tr><tr><td><p>1</p></td>
|
</tr><tr><td><p>1</p></td>
|
||||||
<td></td>
|
<td><p>Unknown indicates that the client can be used
|
||||||
|
but information is missing and it can not be validated.</p>
|
||||||
|
</td>
|
||||||
</tr></tbody>
|
</tr></tbody>
|
||||||
</table>
|
</table>
|
||||||
<h3 id="external-secrets.io/v1beta1.VaultAppRole">VaultAppRole
|
<h3 id="external-secrets.io/v1beta1.VaultAppRole">VaultAppRole
|
||||||
|
|
|
@ -48,6 +48,8 @@ const (
|
||||||
jwtProviderSecretName = "jwt-provider-credentials"
|
jwtProviderSecretName = "jwt-provider-credentials"
|
||||||
jwtK8sProviderName = "jwt-k8s-provider"
|
jwtK8sProviderName = "jwt-k8s-provider"
|
||||||
kubernetesProviderName = "kubernetes-provider"
|
kubernetesProviderName = "kubernetes-provider"
|
||||||
|
referentSecretName = "referent-secret"
|
||||||
|
referentKey = "referent-secret-key"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -99,6 +101,7 @@ func (s *vaultProvider) BeforeEach() {
|
||||||
s.CreateJWTStore(v, ns)
|
s.CreateJWTStore(v, ns)
|
||||||
s.CreateJWTK8sStore(v, ns)
|
s.CreateJWTK8sStore(v, ns)
|
||||||
s.CreateKubernetesAuthStore(v, ns)
|
s.CreateKubernetesAuthStore(v, ns)
|
||||||
|
s.CreateReferentTokenStore(v, ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeStore(name, ns string, v *addon.Vault) *esv1beta1.SecretStore {
|
func makeStore(name, ns string, v *addon.Vault) *esv1beta1.SecretStore {
|
||||||
|
@ -120,6 +123,14 @@ func makeStore(name, ns string, v *addon.Vault) *esv1beta1.SecretStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeClusterStore(name, ns string, v *addon.Vault) *esv1beta1.ClusterSecretStore {
|
||||||
|
store := makeStore(name, ns, v)
|
||||||
|
return &esv1beta1.ClusterSecretStore{
|
||||||
|
ObjectMeta: store.ObjectMeta,
|
||||||
|
Spec: store.Spec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *vaultProvider) CreateCertStore(v *addon.Vault, ns string) {
|
func (s *vaultProvider) CreateCertStore(v *addon.Vault, ns string) {
|
||||||
By("creating a vault secret")
|
By("creating a vault secret")
|
||||||
clientCert := v.ClientCert
|
clientCert := v.ClientCert
|
||||||
|
@ -179,6 +190,33 @@ func (s vaultProvider) CreateTokenStore(v *addon.Vault, ns string) {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateReferentTokenStore creates a secret in the ExternalSecrets
|
||||||
|
// namespace and creates a ClusterSecretStore with an empty namespace
|
||||||
|
// that can be used to test the referent namespace feature.
|
||||||
|
func (s vaultProvider) CreateReferentTokenStore(v *addon.Vault, ns string) {
|
||||||
|
referentSecret := &v1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: referentSecretName,
|
||||||
|
Namespace: s.framework.Namespace.Name,
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
referentKey: []byte(v.RootToken),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := s.framework.KubeClientSet.CoreV1().Secrets(s.framework.Namespace.Name).Create(context.Background(), referentSecret, metav1.CreateOptions{})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
secretStore := makeClusterStore(referentSecretStoreName(s.framework), ns, v)
|
||||||
|
secretStore.Spec.Provider.Vault.Auth = esv1beta1.VaultAuth{
|
||||||
|
TokenSecretRef: &esmeta.SecretKeySelector{
|
||||||
|
Name: referentSecretName,
|
||||||
|
Key: referentKey,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = s.framework.CRClient.Create(context.Background(), secretStore)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
func (s vaultProvider) CreateAppRoleStore(v *addon.Vault, ns string) {
|
func (s vaultProvider) CreateAppRoleStore(v *addon.Vault, ns string) {
|
||||||
By("creating a vault secret")
|
By("creating a vault secret")
|
||||||
vaultCreds := &v1.Secret{
|
vaultCreds := &v1.Secret{
|
||||||
|
@ -296,3 +334,7 @@ func (s vaultProvider) CreateKubernetesAuthStore(v *addon.Vault, ns string) {
|
||||||
err := s.framework.CRClient.Create(context.Background(), secretStore)
|
err := s.framework.CRClient.Create(context.Background(), secretStore)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func referentSecretStoreName(f *framework.Framework) string {
|
||||||
|
return "referent-provider-" + f.Namespace.Name
|
||||||
|
}
|
||||||
|
|
|
@ -25,13 +25,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
withTokenAuth = "with token auth"
|
withTokenAuth = "with token auth"
|
||||||
withCertAuth = "with cert auth"
|
withCertAuth = "with cert auth"
|
||||||
withApprole = "with approle auth"
|
withApprole = "with approle auth"
|
||||||
withV1 = "with v1 provider"
|
withV1 = "with v1 provider"
|
||||||
withJWT = "with jwt provider"
|
withJWT = "with jwt provider"
|
||||||
withJWTK8s = "with jwt k8s provider"
|
withJWTK8s = "with jwt k8s provider"
|
||||||
withK8s = "with kubernetes provider"
|
withK8s = "with kubernetes provider"
|
||||||
|
withReferentAuth = "with referent provider"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("[vault]", Label("vault"), func() {
|
var _ = Describe("[vault]", Label("vault"), func() {
|
||||||
|
@ -88,6 +89,8 @@ var _ = Describe("[vault]", Label("vault"), func() {
|
||||||
framework.Compose(withK8s, f, common.JSONDataWithTemplate, useKubernetesProvider),
|
framework.Compose(withK8s, f, common.JSONDataWithTemplate, useKubernetesProvider),
|
||||||
framework.Compose(withK8s, f, common.DataPropertyDockerconfigJSON, useKubernetesProvider),
|
framework.Compose(withK8s, f, common.DataPropertyDockerconfigJSON, useKubernetesProvider),
|
||||||
framework.Compose(withK8s, f, common.JSONDataWithoutTargetName, useKubernetesProvider),
|
framework.Compose(withK8s, f, common.JSONDataWithoutTargetName, useKubernetesProvider),
|
||||||
|
// use referent auth
|
||||||
|
framework.Compose(withReferentAuth, f, common.JSONDataFromSync, useReferentAuth),
|
||||||
// vault-specific test cases
|
// vault-specific test cases
|
||||||
Entry("secret value via data without property should return json-encoded string", Label("json"), testJSONWithoutProperty),
|
Entry("secret value via data without property should return json-encoded string", Label("json"), testJSONWithoutProperty),
|
||||||
Entry("secret value via data with property should return json-encoded string", Label("json"), testJSONWithProperty),
|
Entry("secret value via data with property should return json-encoded string", Label("json"), testJSONWithProperty),
|
||||||
|
@ -124,6 +127,11 @@ func useKubernetesProvider(tc *framework.TestCase) {
|
||||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = kubernetesProviderName
|
tc.ExternalSecret.Spec.SecretStoreRef.Name = kubernetesProviderName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func useReferentAuth(tc *framework.TestCase) {
|
||||||
|
tc.ExternalSecret.Spec.SecretStoreRef.Name = referentSecretStoreName(tc.Framework)
|
||||||
|
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esapi.ClusterSecretStoreKind
|
||||||
|
}
|
||||||
|
|
||||||
const jsonVal = `{"foo":{"nested":{"bar":"mysecret","baz":"bang"}}}`
|
const jsonVal = `{"foo":{"nested":{"bar":"mysecret","baz":"bang"}}}`
|
||||||
|
|
||||||
// when no property is set it should return the json-encoded at path.
|
// when no property is set it should return the json-encoded at path.
|
||||||
|
|
|
@ -64,6 +64,7 @@ func reconcile(ctx context.Context, req ctrl.Request, ss esapi.GenericStore, cl
|
||||||
log.V(1).Info("validating")
|
log.V(1).Info("validating")
|
||||||
err := validateStore(ctx, req.Namespace, ss, cl, recorder)
|
err := validateStore(ctx, req.Namespace, ss, cl, recorder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error(err, "unable to validate store")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,6 +277,11 @@ func (c *connector) newClient(ctx context.Context, store esv1beta1.GenericStore,
|
||||||
vStore.logical = client.Logical()
|
vStore.logical = client.Logical()
|
||||||
vStore.token = client.AuthToken()
|
vStore.token = client.AuthToken()
|
||||||
|
|
||||||
|
// allow SecretStore controller validation to pass
|
||||||
|
// when using referent namespace.
|
||||||
|
if vStore.storeKind == esv1beta1.ClusterSecretStoreKind && vStore.namespace == "" {
|
||||||
|
return vStore, nil
|
||||||
|
}
|
||||||
if err := vStore.setAuth(ctx, cfg); err != nil {
|
if err := vStore.setAuth(ctx, cfg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -300,25 +305,25 @@ func (c *connector) ValidateStore(store esv1beta1.GenericStore) error {
|
||||||
return fmt.Errorf(errInvalidVaultProv)
|
return fmt.Errorf(errInvalidVaultProv)
|
||||||
}
|
}
|
||||||
if p.Auth.AppRole != nil {
|
if p.Auth.AppRole != nil {
|
||||||
if err := utils.ValidateSecretSelector(store, p.Auth.AppRole.SecretRef); err != nil {
|
if err := utils.ValidateReferentSecretSelector(store, p.Auth.AppRole.SecretRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidAppRoleSec, err)
|
return fmt.Errorf(errInvalidAppRoleSec, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Auth.Cert != nil {
|
if p.Auth.Cert != nil {
|
||||||
if err := utils.ValidateSecretSelector(store, p.Auth.Cert.ClientCert); err != nil {
|
if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.ClientCert); err != nil {
|
||||||
return fmt.Errorf(errInvalidClientCert, err)
|
return fmt.Errorf(errInvalidClientCert, err)
|
||||||
}
|
}
|
||||||
if err := utils.ValidateSecretSelector(store, p.Auth.Cert.SecretRef); err != nil {
|
if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.SecretRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidCertSec, err)
|
return fmt.Errorf(errInvalidCertSec, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Auth.Jwt != nil {
|
if p.Auth.Jwt != nil {
|
||||||
if p.Auth.Jwt.SecretRef != nil {
|
if p.Auth.Jwt.SecretRef != nil {
|
||||||
if err := utils.ValidateSecretSelector(store, *p.Auth.Jwt.SecretRef); err != nil {
|
if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Jwt.SecretRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidJwtSec, err)
|
return fmt.Errorf(errInvalidJwtSec, err)
|
||||||
}
|
}
|
||||||
} else if p.Auth.Jwt.KubernetesServiceAccountToken != nil {
|
} else if p.Auth.Jwt.KubernetesServiceAccountToken != nil {
|
||||||
if err := utils.ValidateServiceAccountSelector(store, p.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef); err != nil {
|
if err := utils.ValidateReferentServiceAccountSelector(store, p.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidJwtK8sSA, err)
|
return fmt.Errorf(errInvalidJwtK8sSA, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -327,23 +332,23 @@ func (c *connector) ValidateStore(store esv1beta1.GenericStore) error {
|
||||||
}
|
}
|
||||||
if p.Auth.Kubernetes != nil {
|
if p.Auth.Kubernetes != nil {
|
||||||
if p.Auth.Kubernetes.ServiceAccountRef != nil {
|
if p.Auth.Kubernetes.ServiceAccountRef != nil {
|
||||||
if err := utils.ValidateServiceAccountSelector(store, *p.Auth.Kubernetes.ServiceAccountRef); err != nil {
|
if err := utils.ValidateReferentServiceAccountSelector(store, *p.Auth.Kubernetes.ServiceAccountRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidKubeSA, err)
|
return fmt.Errorf(errInvalidKubeSA, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Auth.Kubernetes.SecretRef != nil {
|
if p.Auth.Kubernetes.SecretRef != nil {
|
||||||
if err := utils.ValidateSecretSelector(store, *p.Auth.Kubernetes.SecretRef); err != nil {
|
if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Kubernetes.SecretRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidKubeSec, err)
|
return fmt.Errorf(errInvalidKubeSec, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Auth.Ldap != nil {
|
if p.Auth.Ldap != nil {
|
||||||
if err := utils.ValidateSecretSelector(store, p.Auth.Ldap.SecretRef); err != nil {
|
if err := utils.ValidateReferentSecretSelector(store, p.Auth.Ldap.SecretRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidLdapSec, err)
|
return fmt.Errorf(errInvalidLdapSec, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Auth.TokenSecretRef != nil {
|
if p.Auth.TokenSecretRef != nil {
|
||||||
if err := utils.ValidateSecretSelector(store, *p.Auth.TokenSecretRef); err != nil {
|
if err := utils.ValidateReferentSecretSelector(store, *p.Auth.TokenSecretRef); err != nil {
|
||||||
return fmt.Errorf(errInvalidTokenRef, err)
|
return fmt.Errorf(errInvalidTokenRef, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,6 +586,32 @@ func (v *client) Close(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *client) Validate() (esv1beta1.ValidationResult, error) {
|
func (v *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 v.storeKind == esv1beta1.ClusterSecretStoreKind {
|
||||||
|
if v.store.Auth.TokenSecretRef != nil && v.store.Auth.TokenSecretRef.Namespace == nil {
|
||||||
|
return esv1beta1.ValidationResultUnknown, nil
|
||||||
|
}
|
||||||
|
if v.store.Auth.AppRole != nil && v.store.Auth.AppRole.SecretRef.Namespace == nil {
|
||||||
|
return esv1beta1.ValidationResultUnknown, nil
|
||||||
|
}
|
||||||
|
if v.store.Auth.Kubernetes != nil && v.store.Auth.Kubernetes.SecretRef != nil && v.store.Auth.Kubernetes.SecretRef.Namespace == nil {
|
||||||
|
return esv1beta1.ValidationResultUnknown, nil
|
||||||
|
}
|
||||||
|
if v.store.Auth.Kubernetes != nil && v.store.Auth.Kubernetes.ServiceAccountRef != nil && v.store.Auth.Kubernetes.ServiceAccountRef.Namespace == nil {
|
||||||
|
return esv1beta1.ValidationResultUnknown, nil
|
||||||
|
}
|
||||||
|
if v.store.Auth.Ldap != nil && v.store.Auth.Ldap.SecretRef.Namespace == nil {
|
||||||
|
return esv1beta1.ValidationResultUnknown, nil
|
||||||
|
}
|
||||||
|
if v.store.Auth.Jwt != nil && v.store.Auth.Jwt.SecretRef.Namespace == nil {
|
||||||
|
return esv1beta1.ValidationResultUnknown, nil
|
||||||
|
}
|
||||||
|
if v.store.Auth.Cert != nil && v.store.Auth.Cert.SecretRef.Namespace == nil {
|
||||||
|
return esv1beta1.ValidationResultUnknown, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
_, err := checkToken(context.Background(), v)
|
_, err := checkToken(context.Background(), v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return esv1beta1.ValidationResultError, fmt.Errorf(errInvalidCredentials, err)
|
return esv1beta1.ValidationResultError, fmt.Errorf(errInvalidCredentials, err)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
// nolint:gosec
|
// nolint:gosec
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -110,16 +111,33 @@ func ErrorContains(out error, want string) bool {
|
||||||
return strings.Contains(out.Error(), want)
|
return strings.Contains(out.Error(), want)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errNamespaceNotAllowed = errors.New("namespace not allowed with namespaced SecretStore")
|
||||||
|
errRequireNamespace = errors.New("cluster scope requires namespace")
|
||||||
|
)
|
||||||
|
|
||||||
// ValidateSecretSelector just checks if the namespace field is present/absent
|
// ValidateSecretSelector just checks if the namespace field is present/absent
|
||||||
// depending on the secret store type.
|
// depending on the secret store type.
|
||||||
// We MUST NOT check the name or key property here. It MAY be defaulted by the provider.
|
// We MUST NOT check the name or key property here. It MAY be defaulted by the provider.
|
||||||
func ValidateSecretSelector(store esv1beta1.GenericStore, ref esmeta.SecretKeySelector) error {
|
func ValidateSecretSelector(store esv1beta1.GenericStore, ref esmeta.SecretKeySelector) error {
|
||||||
clusterScope := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind
|
clusterScope := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind
|
||||||
if clusterScope && ref.Namespace == nil {
|
if clusterScope && ref.Namespace == nil {
|
||||||
return fmt.Errorf("cluster scope requires namespace")
|
return errRequireNamespace
|
||||||
}
|
}
|
||||||
if !clusterScope && ref.Namespace != nil {
|
if !clusterScope && ref.Namespace != nil {
|
||||||
return fmt.Errorf("namespace not allowed with namespaced SecretStore")
|
return errNamespaceNotAllowed
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateReferentSecretSelector allows
|
||||||
|
// cluster scoped store without namespace
|
||||||
|
// this should replace above ValidateServiceAccountSelector once all providers
|
||||||
|
// support referent auth.
|
||||||
|
func ValidateReferentSecretSelector(store esv1beta1.GenericStore, ref esmeta.SecretKeySelector) error {
|
||||||
|
clusterScope := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind
|
||||||
|
if !clusterScope && ref.Namespace != nil {
|
||||||
|
return errNamespaceNotAllowed
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -130,10 +148,22 @@ func ValidateSecretSelector(store esv1beta1.GenericStore, ref esmeta.SecretKeySe
|
||||||
func ValidateServiceAccountSelector(store esv1beta1.GenericStore, ref esmeta.ServiceAccountSelector) error {
|
func ValidateServiceAccountSelector(store esv1beta1.GenericStore, ref esmeta.ServiceAccountSelector) error {
|
||||||
clusterScope := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind
|
clusterScope := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind
|
||||||
if clusterScope && ref.Namespace == nil {
|
if clusterScope && ref.Namespace == nil {
|
||||||
return fmt.Errorf("cluster scope requires namespace")
|
return errRequireNamespace
|
||||||
}
|
}
|
||||||
if !clusterScope && ref.Namespace != nil {
|
if !clusterScope && ref.Namespace != nil {
|
||||||
return fmt.Errorf("namespace not allowed with namespaced SecretStore")
|
return errNamespaceNotAllowed
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateReferentServiceAccountSelector allows
|
||||||
|
// cluster scoped store without namespace
|
||||||
|
// this should replace above ValidateServiceAccountSelector once all providers
|
||||||
|
// support referent auth.
|
||||||
|
func ValidateReferentServiceAccountSelector(store esv1beta1.GenericStore, ref esmeta.ServiceAccountSelector) error {
|
||||||
|
clusterScope := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind
|
||||||
|
if !clusterScope && ref.Namespace != nil {
|
||||||
|
return errNamespaceNotAllowed
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue