diff --git a/apis/externalsecrets/v1beta1/secretstore_conjur_types.go b/apis/externalsecrets/v1beta1/secretstore_conjur_types.go
index f0043da23..517552adb 100644
--- a/apis/externalsecrets/v1beta1/secretstore_conjur_types.go
+++ b/apis/externalsecrets/v1beta1/secretstore_conjur_types.go
@@ -27,12 +27,12 @@ type ConjurProvider struct {
type ConjurAuth struct {
// +optional
- Apikey *ConjurApikey `json:"apikey,omitempty"`
+ APIKey *ConjurAPIKey `json:"apikey,omitempty"`
// +optional
Jwt *ConjurJWT `json:"jwt,omitempty"`
}
-type ConjurApikey struct {
+type ConjurAPIKey struct {
Account string `json:"account"`
UserRef *esmeta.SecretKeySelector `json:"userRef"`
APIKeyRef *esmeta.SecretKeySelector `json:"apiKeyRef"`
diff --git a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go
index 2cbaae24a..87abd5d5c 100644
--- a/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go
+++ b/apis/externalsecrets/v1beta1/zz_generated.deepcopy.go
@@ -654,7 +654,7 @@ func (in *ClusterSecretStoreList) DeepCopyObject() runtime.Object {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ConjurApikey) DeepCopyInto(out *ConjurApikey) {
+func (in *ConjurAPIKey) DeepCopyInto(out *ConjurAPIKey) {
*out = *in
if in.UserRef != nil {
in, out := &in.UserRef, &out.UserRef
@@ -668,12 +668,12 @@ func (in *ConjurApikey) DeepCopyInto(out *ConjurApikey) {
}
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConjurApikey.
-func (in *ConjurApikey) DeepCopy() *ConjurApikey {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConjurAPIKey.
+func (in *ConjurAPIKey) DeepCopy() *ConjurAPIKey {
if in == nil {
return nil
}
- out := new(ConjurApikey)
+ out := new(ConjurAPIKey)
in.DeepCopyInto(out)
return out
}
@@ -681,9 +681,9 @@ func (in *ConjurApikey) DeepCopy() *ConjurApikey {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConjurAuth) DeepCopyInto(out *ConjurAuth) {
*out = *in
- if in.Apikey != nil {
- in, out := &in.Apikey, &out.Apikey
- *out = new(ConjurApikey)
+ if in.APIKey != nil {
+ in, out := &in.APIKey, &out.APIKey
+ *out = new(ConjurAPIKey)
(*in).DeepCopyInto(*out)
}
if in.Jwt != nil {
diff --git a/docs/api/spec.md b/docs/api/spec.md
index 9b9350a71..479819bbb 100644
--- a/docs/api/spec.md
+++ b/docs/api/spec.md
@@ -1691,7 +1691,7 @@ Kubernetes meta/v1.LabelSelector
-
ConjurApikey
+ConjurAPIKey
(Appears on:
@@ -1763,8 +1763,8 @@ External Secrets meta/v1.SecretKeySelector
apikey
-
-ConjurApikey
+
+ConjurAPIKey
|
diff --git a/pkg/generator/gcr/gcr.go b/pkg/generator/gcr/gcr.go
index 770646b03..8264b84e1 100644
--- a/pkg/generator/gcr/gcr.go
+++ b/pkg/generator/gcr/gcr.go
@@ -27,6 +27,7 @@ import (
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
genv1alpha1 "github.com/external-secrets/external-secrets/apis/generators/v1alpha1"
"github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
type Generator struct{}
@@ -65,7 +66,7 @@ func (g *Generator) generate(
ts, err := tokenSource(ctx, esv1beta1.GCPSMAuth{
SecretRef: (*esv1beta1.GCPSMAuthSecretRef)(res.Spec.Auth.SecretRef),
WorkloadIdentity: (*esv1beta1.GCPWorkloadIdentity)(res.Spec.Auth.WorkloadIdentity),
- }, res.Spec.ProjectID, false, kube, namespace)
+ }, res.Spec.ProjectID, resolvers.EmptyStoreKind, kube, namespace)
if err != nil {
return nil, err
}
@@ -81,7 +82,7 @@ func (g *Generator) generate(
}, nil
}
-type tokenSourceFunc func(ctx context.Context, auth esv1beta1.GCPSMAuth, projectID string, isClusterKind bool, kube client.Client, namespace string) (oauth2.TokenSource, error)
+type tokenSourceFunc func(ctx context.Context, auth esv1beta1.GCPSMAuth, projectID string, storeKind string, kube client.Client, namespace string) (oauth2.TokenSource, error)
func parseSpec(data []byte) (*genv1alpha1.GCRAccessToken, error) {
var spec genv1alpha1.GCRAccessToken
diff --git a/pkg/generator/gcr/gcr_test.go b/pkg/generator/gcr/gcr_test.go
index 5a937f8e7..e7aeb786d 100644
--- a/pkg/generator/gcr/gcr_test.go
+++ b/pkg/generator/gcr/gcr_test.go
@@ -65,7 +65,7 @@ func TestGenerate(t *testing.T) {
"foo": []byte("bar"),
},
}).Build(),
- fakeTokenSource: func(ctx context.Context, auth v1beta1.GCPSMAuth, projectID string, isClusterKind bool, kube client.Client, namespace string) (oauth2.TokenSource, error) {
+ fakeTokenSource: func(ctx context.Context, auth v1beta1.GCPSMAuth, projectID string, storeKind string, kube client.Client, namespace string) (oauth2.TokenSource, error) {
return oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: "1234",
Expiry: time.Unix(5555, 0),
diff --git a/pkg/provider/akeyless/akeyless.go b/pkg/provider/akeyless/akeyless.go
index 589c8f2d3..48d5b8177 100644
--- a/pkg/provider/akeyless/akeyless.go
+++ b/pkg/provider/akeyless/akeyless.go
@@ -39,6 +39,7 @@ import (
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
"github.com/external-secrets/external-secrets/pkg/find"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
@@ -426,12 +427,14 @@ func (a *akeylessBase) getCACertPool(provider *esv1beta1.AkeylessProvider) (*x50
}
ok := caCertPool.AppendCertsFromPEM(pem)
if !ok {
- return nil, fmt.Errorf("failed to append cabundle")
+ return nil, fmt.Errorf("failed to append caBundle")
}
}
- if provider.CAProvider != nil && a.storeKind == esv1beta1.ClusterSecretStoreKind && provider.CAProvider.Namespace == nil {
- return nil, fmt.Errorf("missing namespace on CAProvider secret")
+ if provider.CAProvider != nil &&
+ a.storeKind == esv1beta1.ClusterSecretStoreKind &&
+ provider.CAProvider.Namespace == nil {
+ return nil, fmt.Errorf("missing namespace on caProvider secret")
}
if provider.CAProvider != nil {
@@ -444,7 +447,7 @@ func (a *akeylessBase) getCACertPool(provider *esv1beta1.AkeylessProvider) (*x50
case esv1beta1.CAProviderTypeConfigMap:
cert, err = a.getCertFromConfigMap(provider)
default:
- err = fmt.Errorf("unknown caprovider type: %s", provider.CAProvider.Type)
+ err = fmt.Errorf("unknown CAProvider type: %s", provider.CAProvider.Type)
}
if err != nil {
@@ -456,7 +459,7 @@ func (a *akeylessBase) getCACertPool(provider *esv1beta1.AkeylessProvider) (*x50
}
ok := caCertPool.AppendCertsFromPEM(pem)
if !ok {
- return nil, fmt.Errorf("failed to append cabundle")
+ return nil, fmt.Errorf("failed to append caBundle")
}
}
return caCertPool, nil
@@ -473,12 +476,12 @@ func (a *akeylessBase) getCertFromSecret(provider *esv1beta1.AkeylessProvider) (
}
ctx := context.Background()
- res, err := a.secretKeyRef(ctx, &secretRef)
+ cert, err := resolvers.SecretKeyRef(ctx, a.kube, a.storeKind, a.namespace, &secretRef)
if err != nil {
return nil, err
}
- return []byte(res), nil
+ return []byte(cert), nil
}
func (a *akeylessBase) getCertFromConfigMap(provider *esv1beta1.AkeylessProvider) ([]byte, error) {
@@ -494,12 +497,12 @@ func (a *akeylessBase) getCertFromConfigMap(provider *esv1beta1.AkeylessProvider
ctx := context.Background()
err := a.kube.Get(ctx, objKey, configMapRef)
if err != nil {
- return nil, fmt.Errorf("failed to get caprovider secret %s: %w", objKey.Name, err)
+ return nil, fmt.Errorf("failed to get caProvider secret %s: %w", objKey.Name, err)
}
val, ok := configMapRef.Data[provider.CAProvider.Key]
if !ok {
- return nil, fmt.Errorf("failed to get caprovider configmap %s -> %s", objKey.Name, provider.CAProvider.Key)
+ return nil, fmt.Errorf("failed to get caProvider configMap %s -> %s", objKey.Name, provider.CAProvider.Key)
}
return []byte(val), nil
diff --git a/pkg/provider/akeyless/akeyless_api.go b/pkg/provider/akeyless/akeyless_api.go
index 66d610715..080cdce41 100644
--- a/pkg/provider/akeyless/akeyless_api.go
+++ b/pkg/provider/akeyless/akeyless_api.go
@@ -35,6 +35,7 @@ import (
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
var apiErr akeyless.GenericOpenAPIError
@@ -335,7 +336,7 @@ func (a *akeylessBase) getK8SServiceAccountJWT(ctx context.Context, kubernetesAu
tokenRef = kubernetesAuth.SecretRef.DeepCopy()
tokenRef.Key = "token"
}
- jwt, err := a.secretKeyRef(ctx, tokenRef)
+ jwt, err := resolvers.SecretKeyRef(ctx, a.kube, a.storeKind, a.namespace, tokenRef)
if err != nil {
return "", err
}
@@ -363,7 +364,7 @@ func (a *akeylessBase) getJWTFromServiceAccount(ctx context.Context, serviceAcco
return "", fmt.Errorf(errGetKubeSASecrets, ref.Name)
}
for _, tokenRef := range serviceAccount.Secrets {
- retval, err := a.secretKeyRef(ctx, &esmeta.SecretKeySelector{
+ token, err := resolvers.SecretKeyRef(ctx, a.kube, a.storeKind, a.namespace, &esmeta.SecretKeySelector{
Name: tokenRef.Name,
Namespace: &ref.Namespace,
Key: "token",
@@ -372,36 +373,11 @@ func (a *akeylessBase) getJWTFromServiceAccount(ctx context.Context, serviceAcco
continue
}
- return retval, nil
+ return token, nil
}
return "", fmt.Errorf(errGetKubeSANoToken, ref.Name)
}
-func (a *akeylessBase) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
- secret := &corev1.Secret{}
- ref := types.NamespacedName{
- Namespace: a.namespace,
- Name: secretRef.Name,
- }
- if (a.storeKind == esv1beta1.ClusterSecretStoreKind) &&
- (secretRef.Namespace != nil) {
- ref.Namespace = *secretRef.Namespace
- }
- err := a.kube.Get(ctx, ref, secret)
- if err != nil {
- return "", fmt.Errorf(errGetKubeSecret, ref.Name, err)
- }
-
- keyBytes, ok := secret.Data[secretRef.Key]
- if !ok {
- return "", fmt.Errorf(errSecretKeyFmt, secretRef.Key)
- }
-
- value := string(keyBytes)
- valueStr := strings.TrimSpace(value)
- return valueStr, nil
-}
-
func (a *akeylessBase) getJWTfromServiceAccountToken(ctx context.Context, serviceAccountRef esmeta.ServiceAccountSelector, additionalAud []string, expirationSeconds int64) (string, error) {
audiences := serviceAccountRef.Audiences
if len(additionalAud) > 0 {
diff --git a/pkg/provider/akeyless/auth.go b/pkg/provider/akeyless/auth.go
index 420ea1457..fac21bc9e 100644
--- a/pkg/provider/akeyless/auth.go
+++ b/pkg/provider/akeyless/auth.go
@@ -18,19 +18,15 @@ import (
"context"
"fmt"
- v1 "k8s.io/api/core/v1"
- "sigs.k8s.io/controller-runtime/pkg/client"
-
- esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
- errInvalidClusterStoreMissingAKIDNamespace = "invalid ClusterSecretStore: missing Akeyless AccessID Namespace"
- errInvalidClusterStoreMissingSAKNamespace = "invalid ClusterSecretStore: missing Akeyless AccessType Namespace"
- errFetchAKIDSecret = "could not fetch accessID secret: %w"
- errFetchSAKSecret = "could not fetch AccessType secret: %w"
- errMissingSAK = "missing SecretAccessKey"
- errMissingAKID = "missing AccessKeyID"
+ errFetchAccessIDSecret = "could not fetch accessID secret: %w"
+ errFetchAccessTypeSecret = "could not fetch AccessType secret: %w"
+ errFetchAccessTypeParamSecret = "could not fetch AccessTypeParam secret: %w"
+ errMissingSAK = "missing SecretAccessKey"
+ errMissingAKID = "missing AccessKeyID"
)
func (a *akeylessBase) TokenFromSecretRef(ctx context.Context) (string, error) {
@@ -44,58 +40,36 @@ func (a *akeylessBase) TokenFromSecretRef(ctx context.Context) (string, error) {
return a.GetToken(auth.AccessID, "k8s", auth.K8sConfName, auth)
}
- ke := client.ObjectKey{
- Name: prov.Auth.SecretRef.AccessID.Name,
- Namespace: a.namespace, // default to ExternalSecret namespace
- }
- // only ClusterStore is allowed to set namespace (and then it's required)
- if a.store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind {
- if prov.Auth.SecretRef.AccessID.Namespace == nil {
- return "", fmt.Errorf(errInvalidClusterStoreMissingAKIDNamespace)
- }
- ke.Namespace = *prov.Auth.SecretRef.AccessID.Namespace
- }
- accessIDSecret := v1.Secret{}
- err = a.kube.Get(ctx, ke, &accessIDSecret)
+ accessID, err := resolvers.SecretKeyRef(
+ ctx,
+ a.kube,
+ a.storeKind,
+ a.namespace,
+ &prov.Auth.SecretRef.AccessID,
+ )
if err != nil {
- return "", fmt.Errorf(errFetchAKIDSecret, err)
+ return "", fmt.Errorf(errFetchAccessIDSecret, err)
}
- ke = client.ObjectKey{
- Name: prov.Auth.SecretRef.AccessType.Name,
- Namespace: a.namespace, // default to ExternalSecret namespace
- }
- // only ClusterStore is allowed to set namespace (and then it's required)
- if a.store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind {
- if prov.Auth.SecretRef.AccessType.Namespace == nil {
- return "", fmt.Errorf(errInvalidClusterStoreMissingSAKNamespace)
- }
- ke.Namespace = *prov.Auth.SecretRef.AccessType.Namespace
- }
- accessTypeSecret := v1.Secret{}
- err = a.kube.Get(ctx, ke, &accessTypeSecret)
+ accessType, err := resolvers.SecretKeyRef(
+ ctx,
+ a.kube,
+ a.storeKind,
+ a.namespace,
+ &prov.Auth.SecretRef.AccessType,
+ )
if err != nil {
- return "", fmt.Errorf(errFetchSAKSecret, err)
+ return "", fmt.Errorf(errFetchAccessTypeSecret, err)
}
-
- ke = client.ObjectKey{
- Name: prov.Auth.SecretRef.AccessTypeParam.Name,
- Namespace: a.namespace, // default to ExternalSecret namespace
- }
- // only ClusterStore is allowed to set namespace (and then it's required)
- if a.store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind {
- if prov.Auth.SecretRef.AccessType.Namespace == nil {
- return "", fmt.Errorf(errInvalidClusterStoreMissingSAKNamespace)
- }
- ke.Namespace = *prov.Auth.SecretRef.AccessType.Namespace
- }
- accessTypeParamSecret := v1.Secret{}
- err = a.kube.Get(ctx, ke, &accessTypeParamSecret)
+ accessTypeParam, err := resolvers.SecretKeyRef(
+ ctx,
+ a.kube,
+ a.storeKind,
+ a.namespace,
+ &prov.Auth.SecretRef.AccessTypeParam,
+ )
if err != nil {
- return "", fmt.Errorf(errFetchSAKSecret, err)
+ return "", fmt.Errorf(errFetchAccessTypeParamSecret, err)
}
- accessID := string(accessIDSecret.Data[prov.Auth.SecretRef.AccessID.Key])
- accessType := string(accessTypeSecret.Data[prov.Auth.SecretRef.AccessType.Key])
- accessTypeParam := string(accessTypeSecret.Data[prov.Auth.SecretRef.AccessTypeParam.Key])
if accessID == "" {
return "", fmt.Errorf(errMissingSAK)
diff --git a/pkg/provider/alibaba/kms.go b/pkg/provider/alibaba/kms.go
index 7c944e0cc..cdf059e98 100644
--- a/pkg/provider/alibaba/kms.go
+++ b/pkg/provider/alibaba/kms.go
@@ -26,22 +26,18 @@ import (
"github.com/avast/retry-go/v4"
"github.com/tidwall/gjson"
corev1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
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/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
- errAlibabaClient = "cannot setup new Alibaba client: %w"
- errAlibabaCredSecretName = "invalid Alibaba SecretStore resource: missing Alibaba APIKey"
- errUninitalizedAlibabaProvider = "provider Alibaba is not initialized"
- errInvalidClusterStoreMissingAKIDNamespace = "invalid ClusterStore, missing AccessKeyID namespace"
- errInvalidClusterStoreMissingSKNamespace = "invalid ClusterStore, missing namespace"
- errFetchAKIDSecret = "could not fetch AccessKeyID secret: %w"
- errMissingSAK = "missing AccessSecretKey"
- errMissingAKID = "missing AccessKeyID"
+ errAlibabaClient = "cannot setup new Alibaba client: %w"
+ errUninitalizedAlibabaProvider = "provider Alibaba is not initialized"
+ errFetchAccessKeyID = "could not fetch AccessKeyID secret: %w"
+ errFetchAccessKeySecret = "could not fetch AccessKeySecret secret: %w"
)
// https://github.com/external-secrets/external-secrets/issues/644
@@ -222,54 +218,17 @@ func newAccessKeyAuth(ctx context.Context, kube kclient.Client, store esv1beta1.
storeSpec := store.GetSpec()
alibabaSpec := storeSpec.Provider.Alibaba
storeKind := store.GetObjectKind().GroupVersionKind().Kind
-
- credentialsSecret := &corev1.Secret{}
- credentialsSecretName := alibabaSpec.Auth.SecretRef.AccessKeyID.Name
- if credentialsSecretName == "" {
- return nil, fmt.Errorf(errAlibabaCredSecretName)
- }
- objectKey := types.NamespacedName{
- Name: credentialsSecretName,
- Namespace: namespace,
- }
-
- // only ClusterStore is allowed to set namespace (and then it's required)
- if storeKind == esv1beta1.ClusterSecretStoreKind {
- if alibabaSpec.Auth.SecretRef.AccessKeyID.Namespace == nil {
- return nil, fmt.Errorf(errInvalidClusterStoreMissingAKIDNamespace)
- }
- objectKey.Namespace = *alibabaSpec.Auth.SecretRef.AccessKeyID.Namespace
- }
-
- err := kube.Get(ctx, objectKey, credentialsSecret)
+ accessKeyID, err := resolvers.SecretKeyRef(ctx, kube, storeKind, namespace, &alibabaSpec.Auth.SecretRef.AccessKeyID)
if err != nil {
- return nil, fmt.Errorf(errFetchAKIDSecret, err)
+ return nil, fmt.Errorf(errFetchAccessKeyID, err)
}
-
- objectKey = types.NamespacedName{
- Name: alibabaSpec.Auth.SecretRef.AccessKeySecret.Name,
- Namespace: namespace,
+ accessKeySecret, err := resolvers.SecretKeyRef(ctx, kube, storeKind, namespace, &alibabaSpec.Auth.SecretRef.AccessKeySecret)
+ if err != nil {
+ return nil, fmt.Errorf(errFetchAccessKeySecret, err)
}
- if storeKind == esv1beta1.ClusterSecretStoreKind {
- if alibabaSpec.Auth.SecretRef.AccessKeySecret.Namespace == nil {
- return nil, fmt.Errorf(errInvalidClusterStoreMissingSKNamespace)
- }
- objectKey.Namespace = *alibabaSpec.Auth.SecretRef.AccessKeySecret.Namespace
- }
-
- accessKeyID := credentialsSecret.Data[alibabaSpec.Auth.SecretRef.AccessKeyID.Key]
- if (accessKeyID == nil) || (len(accessKeyID) == 0) {
- return nil, fmt.Errorf(errMissingAKID)
- }
-
- accessKeySecret := credentialsSecret.Data[alibabaSpec.Auth.SecretRef.AccessKeySecret.Key]
- if (accessKeySecret == nil) || (len(accessKeySecret) == 0) {
- return nil, fmt.Errorf(errMissingSAK)
- }
-
credentialConfig := &credential.Config{
- AccessKeyId: utils.Ptr(string(accessKeyID)),
- AccessKeySecret: utils.Ptr(string(accessKeySecret)),
+ AccessKeyId: utils.Ptr(accessKeyID),
+ AccessKeySecret: utils.Ptr(accessKeySecret),
Type: utils.Ptr("access_key"),
ConnectTimeout: utils.Ptr(30),
Timeout: utils.Ptr(60),
diff --git a/pkg/provider/aws/auth/auth.go b/pkg/provider/aws/auth/auth.go
index 85c448270..83e66770d 100644
--- a/pkg/provider/aws/auth/auth.go
+++ b/pkg/provider/aws/auth/auth.go
@@ -38,6 +38,7 @@ import (
"github.com/external-secrets/external-secrets/pkg/cache"
"github.com/external-secrets/external-secrets/pkg/feature"
"github.com/external-secrets/external-secrets/pkg/provider/aws/util"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
// Config contains configuration to create a new AWS provider.
@@ -58,13 +59,9 @@ const (
audienceAnnotation = "eks.amazonaws.com/audience"
defaultTokenAudience = "sts.amazonaws.com"
- errInvalidClusterStoreMissingAKIDNamespace = "invalid ClusterSecretStore: missing AWS AccessKeyID Namespace"
- errInvalidClusterStoreMissingSAKNamespace = "invalid ClusterSecretStore: missing AWS SecretAccessKey Namespace"
- errFetchAKIDSecret = "could not fetch accessKeyID secret: %w"
- errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
- errFetchSTSecret = "could not fetch SessionToken secret: %w"
- errMissingSAK = "missing SecretAccessKey"
- errMissingAKID = "missing AccessKeyID"
+ errFetchAKIDSecret = "could not fetch accessKeyID secret: %w"
+ errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
+ errFetchSTSecret = "could not fetch SessionToken secret: %w"
)
func init() {
@@ -98,11 +95,11 @@ func New(ctx context.Context, store esv1beta1.GenericStore, kube client.Client,
}
}
- // use credentials from sercretRef
+ // use credentials from secretRef
secretRef := prov.Auth.SecretRef
if secretRef != nil {
log.V(1).Info("using credentials from secretRef")
- creds, err = credsFromSecretRef(ctx, prov.Auth, isClusterKind, kube, namespace)
+ creds, err = credsFromSecretRef(ctx, prov.Auth, store.GetKind(), kube, namespace)
if err != nil {
return nil, err
}
@@ -176,11 +173,11 @@ func NewGeneratorSession(ctx context.Context, auth esv1beta1.AWSAuth, role, regi
}
}
- // use credentials from sercretRef
+ // use credentials from secretRef
secretRef := auth.SecretRef
if secretRef != nil {
log.V(1).Info("using credentials from secretRef")
- creds, err = credsFromSecretRef(ctx, auth, false, kube, namespace)
+ creds, err = credsFromSecretRef(ctx, auth, "", kube, namespace)
if err != nil {
return nil, err
}
@@ -211,55 +208,22 @@ func NewGeneratorSession(ctx context.Context, auth esv1beta1.AWSAuth, role, regi
// construct a aws.Credentials object
// The namespace of the external secret is used if the ClusterSecretStore does not specify a namespace (referentAuth)
// If the ClusterSecretStore defines a namespace it will take precedence.
-func credsFromSecretRef(ctx context.Context, auth esv1beta1.AWSAuth, isClusterKind bool, kube client.Client, namespace string) (*credentials.Credentials, error) {
- ke := client.ObjectKey{
- Name: auth.SecretRef.AccessKeyID.Name,
- Namespace: namespace,
- }
- if isClusterKind && auth.SecretRef.AccessKeyID.Namespace != nil {
- ke.Namespace = *auth.SecretRef.AccessKeyID.Namespace
- }
- akSecret := v1.Secret{}
- err := kube.Get(ctx, ke, &akSecret)
- if err != nil {
- return nil, fmt.Errorf(errFetchAKIDSecret, err)
- }
- ke = client.ObjectKey{
- Name: auth.SecretRef.SecretAccessKey.Name,
- Namespace: namespace,
- }
- if isClusterKind && auth.SecretRef.SecretAccessKey.Namespace != nil {
- ke.Namespace = *auth.SecretRef.SecretAccessKey.Namespace
- }
- sakSecret := v1.Secret{}
- err = kube.Get(ctx, ke, &sakSecret)
+func credsFromSecretRef(ctx context.Context, auth esv1beta1.AWSAuth, storeKind string, kube client.Client, namespace string) (*credentials.Credentials, error) {
+ sak, err := resolvers.SecretKeyRef(ctx, kube, storeKind, namespace, &auth.SecretRef.SecretAccessKey)
if err != nil {
return nil, fmt.Errorf(errFetchSAKSecret, err)
}
- sak := string(sakSecret.Data[auth.SecretRef.SecretAccessKey.Key])
- aks := string(akSecret.Data[auth.SecretRef.AccessKeyID.Key])
- if sak == "" {
- return nil, fmt.Errorf(errMissingSAK)
- }
- if aks == "" {
- return nil, fmt.Errorf(errMissingAKID)
+ aks, err := resolvers.SecretKeyRef(ctx, kube, storeKind, namespace, &auth.SecretRef.AccessKeyID)
+ if err != nil {
+ return nil, fmt.Errorf(errFetchAKIDSecret, err)
}
var sessionToken string
if auth.SecretRef.SessionToken != nil {
- ke = client.ObjectKey{
- Name: auth.SecretRef.SessionToken.Name,
- Namespace: namespace,
- }
- if isClusterKind && auth.SecretRef.SessionToken.Namespace != nil {
- ke.Namespace = *auth.SecretRef.SessionToken.Namespace
- }
- stSecret := v1.Secret{}
- err = kube.Get(ctx, ke, &stSecret)
+ sessionToken, err = resolvers.SecretKeyRef(ctx, kube, storeKind, namespace, auth.SecretRef.SessionToken)
if err != nil {
return nil, fmt.Errorf(errFetchSTSecret, err)
}
- sessionToken = string(stSecret.Data[auth.SecretRef.SessionToken.Key])
}
return credentials.NewStaticCredentials(aks, sak, sessionToken), err
diff --git a/pkg/provider/aws/auth/auth_test.go b/pkg/provider/aws/auth/auth_test.go
index d61694dd6..9453248aa 100644
--- a/pkg/provider/aws/auth/auth_test.go
+++ b/pkg/provider/aws/auth/auth_test.go
@@ -224,7 +224,7 @@ func TestNewSession(t *testing.T) {
Data: map[string][]byte{},
},
},
- expectErr: "missing SecretAccessKey",
+ expectErr: "could not fetch SecretAccessKey secret: cannot find secret data for key: \"two\"",
},
{
name: "should not be able to access secrets from different namespace",
diff --git a/pkg/provider/azure/keyvault/keyvault.go b/pkg/provider/azure/keyvault/keyvault.go
index d66b48c18..09cae40d2 100644
--- a/pkg/provider/azure/keyvault/keyvault.go
+++ b/pkg/provider/azure/keyvault/keyvault.go
@@ -48,10 +48,10 @@ import (
ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
- smmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
"github.com/external-secrets/external-secrets/pkg/constants"
"github.com/external-secrets/external-secrets/pkg/metrics"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
@@ -886,46 +886,28 @@ func (a *Azure) authorizerForServicePrincipal(ctx context.Context) (autorest.Aut
if a.provider.AuthSecretRef.ClientID == nil || a.provider.AuthSecretRef.ClientSecret == nil {
return nil, fmt.Errorf(errMissingClientIDSecret)
}
- clusterScoped := false
- if a.store.GetKind() == esv1beta1.ClusterSecretStoreKind {
- clusterScoped = true
- }
- cid, err := a.secretKeyRef(ctx, a.namespace, *a.provider.AuthSecretRef.ClientID, clusterScoped)
+ clientID, err := resolvers.SecretKeyRef(
+ ctx,
+ a.crClient,
+ a.store.GetKind(),
+ a.namespace, a.provider.AuthSecretRef.ClientID)
if err != nil {
return nil, err
}
- csec, err := a.secretKeyRef(ctx, a.namespace, *a.provider.AuthSecretRef.ClientSecret, clusterScoped)
+ clientSecret, err := resolvers.SecretKeyRef(
+ ctx,
+ a.crClient,
+ a.store.GetKind(),
+ a.namespace, a.provider.AuthSecretRef.ClientSecret)
if err != nil {
return nil, err
}
- clientCredentialsConfig := kvauth.NewClientCredentialsConfig(cid, csec, *a.provider.TenantID)
+ clientCredentialsConfig := kvauth.NewClientCredentialsConfig(clientID, clientSecret, *a.provider.TenantID)
clientCredentialsConfig.Resource = kvResourceForProviderConfig(a.provider.EnvironmentType)
clientCredentialsConfig.AADEndpoint = AadEndpointForType(a.provider.EnvironmentType)
return clientCredentialsConfig.Authorizer()
}
-// secretKeyRef fetch a secret key.
-func (a *Azure) secretKeyRef(ctx context.Context, namespace string, secretRef smmeta.SecretKeySelector, clusterScoped bool) (string, error) {
- var secret corev1.Secret
- ref := types.NamespacedName{
- Name: secretRef.Name,
- Namespace: namespace,
- }
- if clusterScoped && secretRef.Namespace != nil {
- ref.Namespace = *secretRef.Namespace
- }
- err := a.crClient.Get(ctx, ref, &secret)
- if err != nil {
- return "", fmt.Errorf(errFindSecret, ref.Namespace, ref.Name, err)
- }
- keyBytes, ok := secret.Data[secretRef.Key]
- if !ok {
- return "", fmt.Errorf(errFindDataKey, secretRef.Key, secretRef.Name, namespace)
- }
- value := strings.TrimSpace(string(keyBytes))
- return value, nil
-}
-
func (a *Azure) Close(_ context.Context) error {
return nil
}
diff --git a/pkg/provider/azure/keyvault/keyvault_auth_test.go b/pkg/provider/azure/keyvault/keyvault_auth_test.go
index 807fdb00b..76a13f501 100644
--- a/pkg/provider/azure/keyvault/keyvault_auth_test.go
+++ b/pkg/provider/azure/keyvault/keyvault_auth_test.go
@@ -244,7 +244,7 @@ func TestAuth(t *testing.T) {
},
{
name: "bad config: missing secret",
- expErr: "could not find secret default/password: secrets \"password\" not found",
+ expErr: "cannot get Kubernetes secret \"password\": secrets \"password\" not found",
store: &defaultStore,
provider: &esv1beta1.AzureKVProvider{
AuthType: &authType,
@@ -258,7 +258,7 @@ func TestAuth(t *testing.T) {
},
{
name: "cluster secret store",
- expErr: "could not find secret foo/password: secrets \"password\" not found",
+ expErr: "cannot get Kubernetes secret \"password\": secrets \"password\" not found",
store: &esv1beta1.ClusterSecretStore{
TypeMeta: metav1.TypeMeta{
Kind: esv1beta1.ClusterSecretStoreKind,
diff --git a/pkg/provider/conjur/auth_jwt.go b/pkg/provider/conjur/auth_jwt.go
index 762cc377f..545bfc805 100644
--- a/pkg/provider/conjur/auth_jwt.go
+++ b/pkg/provider/conjur/auth_jwt.go
@@ -27,6 +27,7 @@ import (
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const JwtLifespan = 600 // 10 minutes
@@ -46,7 +47,12 @@ func (p *Client) getJWTToken(ctx context.Context, conjurJWTConfig *esv1beta1.Con
tokenRef = conjurJWTConfig.SecretRef.DeepCopy()
tokenRef.Key = "token"
}
- jwtToken, err := p.secretKeyRef(ctx, tokenRef)
+ jwtToken, err := resolvers.SecretKeyRef(
+ ctx,
+ p.kube,
+ p.StoreKind,
+ p.namespace,
+ tokenRef)
if err != nil {
return "", err
}
diff --git a/pkg/provider/conjur/provider.go b/pkg/provider/conjur/provider.go
index 1627d53ee..a3f5a26aa 100644
--- a/pkg/provider/conjur/provider.go
+++ b/pkg/provider/conjur/provider.go
@@ -32,6 +32,7 @@ import (
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
"github.com/external-secrets/external-secrets/pkg/provider/conjur/util"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
var (
@@ -109,13 +110,22 @@ func (p *Client) GetConjurClient(ctx context.Context) (SecretsClient, error) {
SSLCert: cert,
}
- if prov.Auth.Apikey != nil {
- config.Account = prov.Auth.Apikey.Account
- conjUser, secErr := p.secretKeyRef(ctx, prov.Auth.Apikey.UserRef)
+ if prov.Auth.APIKey != nil {
+ config.Account = prov.Auth.APIKey.Account
+ conjUser, secErr := resolvers.SecretKeyRef(
+ ctx,
+ p.kube,
+ p.StoreKind,
+ p.namespace, prov.Auth.APIKey.UserRef)
if secErr != nil {
return nil, fmt.Errorf(errBadServiceUser, secErr)
}
- conjAPIKey, secErr := p.secretKeyRef(ctx, prov.Auth.Apikey.APIKeyRef)
+ conjAPIKey, secErr := resolvers.SecretKeyRef(
+ ctx,
+ p.kube,
+ p.StoreKind,
+ p.namespace,
+ prov.Auth.APIKey.APIKeyRef)
if secErr != nil {
return nil, fmt.Errorf(errBadServiceAPIKey, secErr)
}
@@ -224,20 +234,20 @@ func (c *Provider) ValidateStore(store esv1beta1.GenericStore) error {
if prov.URL == "" {
return fmt.Errorf("conjur URL cannot be empty")
}
- if prov.Auth.Apikey != nil {
- if prov.Auth.Apikey.Account == "" {
+ if prov.Auth.APIKey != nil {
+ if prov.Auth.APIKey.Account == "" {
return fmt.Errorf("missing Auth.ApiKey.Account")
}
- if prov.Auth.Apikey.UserRef == nil {
+ if prov.Auth.APIKey.UserRef == nil {
return fmt.Errorf("missing Auth.Apikey.UserRef")
}
- if prov.Auth.Apikey.APIKeyRef == nil {
+ if prov.Auth.APIKey.APIKeyRef == nil {
return fmt.Errorf("missing Auth.Apikey.ApiKeyRef")
}
- if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.Apikey.UserRef); err != nil {
+ if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.APIKey.UserRef); err != nil {
return fmt.Errorf("invalid Auth.Apikey.UserRef: %w", err)
}
- if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.Apikey.APIKeyRef); err != nil {
+ if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.APIKey.APIKeyRef); err != nil {
return fmt.Errorf("invalid Auth.Apikey.ApiKeyRef: %w", err)
}
}
@@ -265,7 +275,7 @@ func (c *Provider) ValidateStore(store esv1beta1.GenericStore) error {
}
// At least one auth must be configured
- if prov.Auth.Apikey == nil && prov.Auth.Jwt == nil {
+ if prov.Auth.APIKey == nil && prov.Auth.Jwt == nil {
return fmt.Errorf("missing Auth.* configuration")
}
@@ -277,32 +287,7 @@ func (c *Provider) Capabilities() esv1beta1.SecretStoreCapabilities {
return esv1beta1.SecretStoreReadOnly
}
-func (p *Client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
- secret := &corev1.Secret{}
- ref := client.ObjectKey{
- Namespace: p.namespace,
- Name: secretRef.Name,
- }
- if (p.StoreKind == esv1beta1.ClusterSecretStoreKind) &&
- (secretRef.Namespace != nil) {
- ref.Namespace = *secretRef.Namespace
- }
- err := p.kube.Get(ctx, ref, secret)
- if err != nil {
- return "", err
- }
-
- keyBytes, ok := secret.Data[secretRef.Key]
- if !ok {
- return "", err
- }
-
- value := string(keyBytes)
- valueStr := strings.TrimSpace(value)
- return valueStr, nil
-}
-
-// configMapKeyRef returns the value of a key in a configmap.
+// configMapKeyRef returns the value of a key in a ConfigMap.
func (p *Client) configMapKeyRef(ctx context.Context, cmRef *esmeta.SecretKeySelector) (string, error) {
configMap := &corev1.ConfigMap{}
ref := client.ObjectKey{
@@ -349,7 +334,12 @@ func (p *Client) getCA(ctx context.Context, provider *esv1beta1.ConjurProvider)
Namespace: provider.CAProvider.Namespace,
Key: provider.CAProvider.Key,
}
- ca, err = p.secretKeyRef(ctx, &keySelector)
+ ca, err = resolvers.SecretKeyRef(
+ ctx,
+ p.kube,
+ p.StoreKind,
+ p.namespace,
+ &keySelector)
if err != nil {
return "", fmt.Errorf(errUnableToFetchCAProviderSecret, err)
}
diff --git a/pkg/provider/conjur/provider_test.go b/pkg/provider/conjur/provider_test.go
index 1b49efb66..3f62d2b7e 100644
--- a/pkg/provider/conjur/provider_test.go
+++ b/pkg/provider/conjur/provider_test.go
@@ -351,7 +351,7 @@ func makeAPIKeySecretStore(svcURL, svcUser, svcApikey, svcAccount string) *esv1b
Conjur: &esv1beta1.ConjurProvider{
URL: svcURL,
Auth: esv1beta1.ConjurAuth{
- Apikey: &esv1beta1.ConjurApikey{
+ APIKey: &esv1beta1.ConjurAPIKey{
Account: svcAccount,
UserRef: uref,
APIKeyRef: aref,
@@ -465,7 +465,7 @@ func makeFakeCASource(kind, caData string) kclient.Object {
Namespace: "default",
},
Data: map[string][]byte{
- "conjur-cert": []byte(caData),
+ "ca": []byte(caData),
},
}
}
diff --git a/pkg/provider/delinea/provider.go b/pkg/provider/delinea/provider.go
index 68e809cb3..5bafca41b 100644
--- a/pkg/provider/delinea/provider.go
+++ b/pkg/provider/delinea/provider.go
@@ -17,14 +17,13 @@ package delinea
import (
"context"
"errors"
- "fmt"
"github.com/DelineaXPM/dsv-sdk-go/v2/vault"
- corev1 "k8s.io/api/core/v1"
kubeClient "sigs.k8s.io/controller-runtime/pkg/client"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
var (
@@ -38,8 +37,6 @@ var (
errMissingSecretName = errors.New("must specify a secret name")
errMissingSecretKey = errors.New("must specify a secret key")
errClusterStoreRequiresNamespace = errors.New("when using a ClusterSecretStore, namespaces must be explicitly set")
-
- errNoSuchKeyFmt = "no such key in secret: %q"
)
type Provider struct{}
@@ -62,12 +59,12 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
return nil, errClusterStoreRequiresNamespace
}
- clientID, err := loadConfigSecret(ctx, cfg.ClientID, kube, namespace)
+ clientID, err := loadConfigSecret(ctx, store.GetKind(), cfg.ClientID, kube, namespace)
if err != nil {
return nil, err
}
- clientSecret, err := loadConfigSecret(ctx, cfg.ClientSecret, kube, namespace)
+ clientSecret, err := loadConfigSecret(ctx, store.GetKind(), cfg.ClientSecret, kube, namespace)
if err != nil {
return nil, err
}
@@ -90,33 +87,19 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
}, nil
}
-func loadConfigSecret(ctx context.Context, ref *esv1beta1.DelineaProviderSecretRef, kube kubeClient.Client, defaultNamespace string) (string, error) {
+func loadConfigSecret(
+ ctx context.Context,
+ storeKind string,
+ ref *esv1beta1.DelineaProviderSecretRef,
+ kube kubeClient.Client,
+ namespace string) (string, error) {
if ref.SecretRef == nil {
return ref.Value, nil
}
-
if err := validateSecretRef(ref); err != nil {
return "", err
}
-
- namespace := defaultNamespace
- if ref.SecretRef.Namespace != nil {
- namespace = *ref.SecretRef.Namespace
- }
-
- objKey := kubeClient.ObjectKey{Namespace: namespace, Name: ref.SecretRef.Name}
- secret := corev1.Secret{}
- err := kube.Get(ctx, objKey, &secret)
- if err != nil {
- return "", err
- }
-
- value, ok := secret.Data[ref.SecretRef.Key]
- if !ok {
- return "", fmt.Errorf(errNoSuchKeyFmt, ref.SecretRef.Key)
- }
-
- return string(value), nil
+ return resolvers.SecretKeyRef(ctx, kube, storeKind, namespace, ref.SecretRef)
}
func validateStoreSecretRef(store esv1beta1.GenericStore, ref *esv1beta1.DelineaProviderSecretRef) error {
diff --git a/pkg/provider/delinea/provider_test.go b/pkg/provider/delinea/provider_test.go
index cc779ba5d..861584499 100644
--- a/pkg/provider/delinea/provider_test.go
+++ b/pkg/provider/delinea/provider_test.go
@@ -15,7 +15,6 @@ package delinea
import (
"context"
- "fmt"
"testing"
"github.com/DelineaXPM/dsv-sdk-go/v2/vault"
@@ -283,7 +282,7 @@ func TestNewClient(t *testing.T) {
},
kube: clientfake.NewClientBuilder().WithObjects(clientSecret).Build(),
errCheck: func(t *testing.T, err error) {
- assert.EqualError(t, err, fmt.Sprintf(errNoSuchKeyFmt, "typo"))
+ assert.EqualError(t, err, "cannot find secret data for key: \"typo\"")
},
},
"valid secret refs": {
diff --git a/pkg/provider/doppler/client.go b/pkg/provider/doppler/client.go
index e24fa60aa..08db81973 100644
--- a/pkg/provider/doppler/client.go
+++ b/pkg/provider/doppler/client.go
@@ -23,13 +23,13 @@ import (
"time"
corev1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
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"
dClient "github.com/external-secrets/external-secrets/pkg/provider/doppler/client"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
@@ -41,8 +41,6 @@ const (
secretsDownloadFileKey = "DOPPLER_SECRETS_FILE"
errDopplerTokenSecretName = "missing auth.secretRef.dopplerToken.name"
errInvalidClusterStoreMissingDopplerTokenNamespace = "missing auth.secretRef.dopplerToken.namespace"
- errFetchDopplerTokenSecret = "unable to find find DopplerToken secret: %w"
- errMissingDopplerToken = "auth.secretRef.dopplerToken.key '%s' not found in secret '%s'"
)
type Client struct {
@@ -68,35 +66,16 @@ type SecretsClientInterface interface {
}
func (c *Client) setAuth(ctx context.Context) error {
- credentialsSecret := &corev1.Secret{}
- credentialsSecretName := c.store.Auth.SecretRef.DopplerToken.Name
- if credentialsSecretName == "" {
- return fmt.Errorf(errDopplerTokenSecretName)
- }
- objectKey := types.NamespacedName{
- Name: credentialsSecretName,
- Namespace: c.namespace,
- }
- // only ClusterStore is allowed to set namespace (and then it's required)
- if c.storeKind == esv1beta1.ClusterSecretStoreKind {
- if c.store.Auth.SecretRef.DopplerToken.Namespace == nil {
- return fmt.Errorf(errInvalidClusterStoreMissingDopplerTokenNamespace)
- }
- objectKey.Namespace = *c.store.Auth.SecretRef.DopplerToken.Namespace
- }
-
- err := c.kube.Get(ctx, objectKey, credentialsSecret)
+ token, err := resolvers.SecretKeyRef(
+ ctx,
+ c.kube,
+ c.storeKind,
+ c.namespace,
+ &c.store.Auth.SecretRef.DopplerToken)
if err != nil {
- return fmt.Errorf(errFetchDopplerTokenSecret, err)
+ return err
}
-
- dopplerToken := credentialsSecret.Data[c.store.Auth.SecretRef.DopplerToken.Key]
- if (dopplerToken == nil) || (len(dopplerToken) == 0) {
- return fmt.Errorf(errMissingDopplerToken, c.store.Auth.SecretRef.DopplerToken.Key, credentialsSecretName)
- }
-
- c.dopplerToken = string(dopplerToken)
-
+ c.dopplerToken = token
return nil
}
diff --git a/pkg/provider/gcp/secretmanager/auth.go b/pkg/provider/gcp/secretmanager/auth.go
index 2b80fff13..d7da8ec1b 100644
--- a/pkg/provider/gcp/secretmanager/auth.go
+++ b/pkg/provider/gcp/secretmanager/auth.go
@@ -19,15 +19,14 @@ import (
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
- v1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
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/utils/resolvers"
)
-func NewTokenSource(ctx context.Context, auth esv1beta1.GCPSMAuth, projectID string, isClusterKind bool, kube kclient.Client, namespace string) (oauth2.TokenSource, error) {
- ts, err := serviceAccountTokenSource(ctx, auth, isClusterKind, kube, namespace)
+func NewTokenSource(ctx context.Context, auth esv1beta1.GCPSMAuth, projectID, storeKind string, kube kclient.Client, namespace string) (oauth2.TokenSource, error) {
+ ts, err := serviceAccountTokenSource(ctx, auth, storeKind, kube, namespace)
if ts != nil || err != nil {
return ts, err
}
@@ -36,6 +35,7 @@ func NewTokenSource(ctx context.Context, auth esv1beta1.GCPSMAuth, projectID str
return nil, fmt.Errorf("unable to initialize workload identity")
}
defer wi.Close()
+ isClusterKind := storeKind == esv1beta1.ClusterSecretStoreKind
ts, err = wi.TokenSource(ctx, auth, isClusterKind, kube, namespace)
if ts != nil || err != nil {
return ts, err
@@ -43,29 +43,21 @@ func NewTokenSource(ctx context.Context, auth esv1beta1.GCPSMAuth, projectID str
return google.DefaultTokenSource(ctx, CloudPlatformRole)
}
-func serviceAccountTokenSource(ctx context.Context, auth esv1beta1.GCPSMAuth, isClusterKind bool, kube kclient.Client, namespace string) (oauth2.TokenSource, error) {
+func serviceAccountTokenSource(ctx context.Context, auth esv1beta1.GCPSMAuth, storeKind string, kube kclient.Client, namespace string) (oauth2.TokenSource, error) {
sr := auth.SecretRef
if sr == nil {
return nil, nil
}
- credentialsSecret := &v1.Secret{}
- credentialsSecretName := sr.SecretAccessKey.Name
- objectKey := types.NamespacedName{
- Name: credentialsSecretName,
- Namespace: namespace,
- }
- if isClusterKind && sr.SecretAccessKey.Namespace != nil {
- objectKey.Namespace = *sr.SecretAccessKey.Namespace
- }
- err := kube.Get(ctx, objectKey, credentialsSecret)
+ credentials, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ storeKind,
+ namespace,
+ &auth.SecretRef.SecretAccessKey)
if err != nil {
- return nil, fmt.Errorf(errFetchSAKSecret, err)
+ return nil, err
}
- credentials := credentialsSecret.Data[sr.SecretAccessKey.Key]
- if (credentials == nil) || (len(credentials) == 0) {
- return nil, fmt.Errorf(errMissingSAK)
- }
- config, err := google.JWTConfigFromJSON(credentials, CloudPlatformRole)
+ config, err := google.JWTConfigFromJSON([]byte(credentials), CloudPlatformRole)
if err != nil {
return nil, fmt.Errorf(errUnableProcessJSONCredentials, err)
}
diff --git a/pkg/provider/gcp/secretmanager/client.go b/pkg/provider/gcp/secretmanager/client.go
index 04d3c1530..6d49776bf 100644
--- a/pkg/provider/gcp/secretmanager/client.go
+++ b/pkg/provider/gcp/secretmanager/client.go
@@ -50,7 +50,6 @@ const (
errClientClose = "unable to close SecretManager client: %w"
errMissingStoreSpec = "invalid: missing store spec"
errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
- errMissingSAK = "missing SecretAccessKey"
errUnableProcessJSONCredentials = "failed to process the provided JSON credentials: %w"
errUnableCreateGCPSMClient = "failed to create GCP secretmanager client: %w"
errUninitalizedGCPProvider = "provider GCP is not initialized"
diff --git a/pkg/provider/gcp/secretmanager/provider.go b/pkg/provider/gcp/secretmanager/provider.go
index fd346a1b0..ac92bfb29 100644
--- a/pkg/provider/gcp/secretmanager/provider.go
+++ b/pkg/provider/gcp/secretmanager/provider.go
@@ -90,7 +90,7 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
return client, nil
}
- ts, err := NewTokenSource(ctx, gcpStore.Auth, clusterProjectID, isClusterKind, kube, namespace)
+ ts, err := NewTokenSource(ctx, gcpStore.Auth, clusterProjectID, store.GetKind(), kube, namespace)
if err != nil {
return nil, fmt.Errorf(errUnableCreateGCPSMClient, err)
}
diff --git a/pkg/provider/gitlab/gitlab.go b/pkg/provider/gitlab/gitlab.go
index 844f95022..987f65884 100644
--- a/pkg/provider/gitlab/gitlab.go
+++ b/pkg/provider/gitlab/gitlab.go
@@ -25,7 +25,6 @@ import (
"github.com/tidwall/gjson"
"github.com/xanzy/go-gitlab"
corev1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
@@ -33,13 +32,13 @@ import (
"github.com/external-secrets/external-secrets/pkg/find"
"github.com/external-secrets/external-secrets/pkg/metrics"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
errGitlabCredSecretName = "credentials are empty"
errInvalidClusterStoreMissingSAKNamespace = "invalid clusterStore missing SAK namespace"
errFetchSAKSecret = "couldn't find secret on cluster: %w"
- errMissingSAK = "missing credentials while setting auth"
errList = "could not verify whether the gilabClient is valid: %w"
errProjectAuth = "gitlabClient is not allowed to get secrets for project id [%s]"
errGroupAuth = "gitlabClient is not allowed to get secrets for group id [%s]"
@@ -78,34 +77,13 @@ func (a ProjectGroupPathSorter) Less(i, j int) bool { return len(a[i].FullPath)
var log = ctrl.Log.WithName("provider").WithName("gitlab")
// Set gitlabBase credentials to Access Token.
-func (g *gitlabBase) getAuth(ctx context.Context) ([]byte, error) {
- credentialsSecret := &corev1.Secret{}
- credentialsSecretName := g.store.Auth.SecretRef.AccessToken.Name
- if credentialsSecretName == "" {
- return nil, fmt.Errorf(errGitlabCredSecretName)
- }
- objectKey := types.NamespacedName{
- Name: credentialsSecretName,
- Namespace: g.namespace,
- }
- // only ClusterStore is allowed to set namespace (and then it's required)
- if g.storeKind == esv1beta1.ClusterSecretStoreKind {
- if g.store.Auth.SecretRef.AccessToken.Namespace == nil {
- return nil, fmt.Errorf(errInvalidClusterStoreMissingSAKNamespace)
- }
- objectKey.Namespace = *g.store.Auth.SecretRef.AccessToken.Namespace
- }
-
- err := g.kube.Get(ctx, objectKey, credentialsSecret)
- if err != nil {
- return nil, fmt.Errorf(errFetchSAKSecret, err)
- }
-
- credentials := credentialsSecret.Data[g.store.Auth.SecretRef.AccessToken.Key]
- if len(credentials) == 0 {
- return nil, fmt.Errorf(errMissingSAK)
- }
- return credentials, nil
+func (g *gitlabBase) getAuth(ctx context.Context) (string, error) {
+ return resolvers.SecretKeyRef(
+ ctx,
+ g.kube,
+ g.storeKind,
+ g.namespace,
+ &g.store.Auth.SecretRef.AccessToken)
}
func (g *gitlabBase) DeleteSecret(_ context.Context, _ esv1beta1.PushSecretRemoteRef) error {
diff --git a/pkg/provider/gitlab/gitlab_test.go b/pkg/provider/gitlab/gitlab_test.go
index c10fb34f9..dc788a6d0 100644
--- a/pkg/provider/gitlab/gitlab_test.go
+++ b/pkg/provider/gitlab/gitlab_test.go
@@ -46,7 +46,7 @@ const (
groupvalue = "groupvalue"
groupid = "groupId"
defaultErrorMessage = "[%d] unexpected error: [%s], expected: [%s]"
- errMissingCredentials = "credentials are empty"
+ errMissingCredentials = "cannot get Kubernetes secret \"\": secrets \"\" not found"
testKey = "testKey"
findTestPrefix = "test.*"
)
@@ -351,7 +351,7 @@ func TestNewClient(t *testing.T) {
store.Spec.Provider.Gitlab.Auth.SecretRef.AccessToken.Name = authorizedKeySecretName
store.Spec.Provider.Gitlab.Auth.SecretRef.AccessToken.Key = authorizedKeySecretKey
secretClient, err = provider.NewClient(context.Background(), store, k8sClient, namespace)
- tassert.EqualError(t, err, "couldn't find secret on cluster: secrets \"authorizedKeySecretName\" not found")
+ tassert.EqualError(t, err, "cannot get Kubernetes secret \"authorizedKeySecretName\": secrets \"authorizedKeySecretName\" not found")
tassert.Nil(t, secretClient)
err = createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, newFakeAuthorizedKey()))
diff --git a/pkg/provider/gitlab/provider.go b/pkg/provider/gitlab/provider.go
index 279cf85e3..005db3c4f 100644
--- a/pkg/provider/gitlab/provider.go
+++ b/pkg/provider/gitlab/provider.go
@@ -86,7 +86,7 @@ func (g *gitlabBase) getClient(ctx context.Context, provider *esv1beta1.GitlabPr
// in a similar way to extend functionality of the provider
// Create a new GitLab Client using credentials and options
- client, err := gitlab.NewClient(string(credentials), opts...)
+ client, err := gitlab.NewClient(credentials, opts...)
if err != nil {
return nil, err
}
diff --git a/pkg/provider/ibm/provider.go b/pkg/provider/ibm/provider.go
index 2a0fdbc54..baaf3ed94 100644
--- a/pkg/provider/ibm/provider.go
+++ b/pkg/provider/ibm/provider.go
@@ -26,13 +26,13 @@ import (
"github.com/google/uuid"
"github.com/tidwall/gjson"
corev1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
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/constants"
"github.com/external-secrets/external-secrets/pkg/metrics"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
@@ -51,15 +51,13 @@ const (
payloadConst = "payload"
smAPIKeyConst = "api_key"
- errIBMClient = "cannot setup new ibm client: %w"
- errIBMCredSecretName = "invalid IBM SecretStore resource: missing IBM APIKey"
- errUninitalizedIBMProvider = "provider IBM is not initialized"
- errInvalidClusterStoreMissingSKNamespace = "invalid ClusterStore, missing namespace"
- errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
- errMissingSAK = "missing SecretAccessKey"
- errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
- errJSONSecretMarshal = "unable to marshal secret: %w"
- errExtractingSecret = "unable to extract the fetched secret %s of type %s while performing %s"
+ errIBMClient = "cannot setup new ibm client: %w"
+ errIBMCredSecretName = "invalid IBM SecretStore resource: missing IBM APIKey"
+ errUninitalizedIBMProvider = "provider IBM is not initialized"
+ errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
+ errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
+ errJSONSecretMarshal = "unable to marshal secret: %w"
+ errExtractingSecret = "unable to extract the fetched secret %s of type %s while performing %s"
defaultCacheSize = 100
defaultCacheExpiry = 1 * time.Hour
@@ -93,33 +91,11 @@ type client struct {
}
func (c *client) setAuth(ctx context.Context) error {
- credentialsSecret := &corev1.Secret{}
- credentialsSecretName := c.store.Auth.SecretRef.SecretAPIKey.Name
- if credentialsSecretName == "" {
- return fmt.Errorf(errIBMCredSecretName)
- }
- objectKey := types.NamespacedName{
- Name: credentialsSecretName,
- Namespace: c.namespace,
- }
-
- // only ClusterStore is allowed to set namespace (and then it's required)
- if c.storeKind == esv1beta1.ClusterSecretStoreKind {
- if c.store.Auth.SecretRef.SecretAPIKey.Namespace == nil {
- return fmt.Errorf(errInvalidClusterStoreMissingSKNamespace)
- }
- objectKey.Namespace = *c.store.Auth.SecretRef.SecretAPIKey.Namespace
- }
-
- err := c.kube.Get(ctx, objectKey, credentialsSecret)
+ apiKey, err := resolvers.SecretKeyRef(ctx, c.kube, c.storeKind, c.namespace, &c.store.Auth.SecretRef.SecretAPIKey)
if err != nil {
- return fmt.Errorf(errFetchSAKSecret, err)
- }
-
- c.credentials = credentialsSecret.Data[c.store.Auth.SecretRef.SecretAPIKey.Key]
- if (c.credentials == nil) || (len(c.credentials) == 0) {
- return fmt.Errorf(errMissingSAK)
+ return err
}
+ c.credentials = []byte(apiKey)
return nil
}
diff --git a/pkg/provider/keepersecurity/provider.go b/pkg/provider/keepersecurity/provider.go
index fc1b87fb5..b7ed5a556 100644
--- a/pkg/provider/keepersecurity/provider.go
+++ b/pkg/provider/keepersecurity/provider.go
@@ -19,12 +19,11 @@ import (
ksm "github.com/keeper-security/secrets-manager-go/core"
"github.com/keeper-security/secrets-manager-go/core/logger"
- v1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
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/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
@@ -66,8 +65,7 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
keeperStore := storeSpec.Provider.KeeperSecurity
- isClusterKind := store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind
- clientConfig, err := getKeeperSecurityAuth(ctx, keeperStore, kube, isClusterKind, namespace)
+ clientConfig, err := getKeeperSecurityAuth(ctx, keeperStore, kube, store.GetKind(), namespace)
if err != nil {
return nil, fmt.Errorf(errKeeperSecurityUnableToCreateConfig, err)
}
@@ -112,33 +110,11 @@ func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
return nil
}
-func getKeeperSecurityAuth(ctx context.Context, store *esv1beta1.KeeperSecurityProvider, kube kclient.Client, isClusterKind bool, namespace string) (string, error) {
- auth := store.Auth
-
- credentialsSecret := &v1.Secret{}
- credentialsSecretName := auth.Name
- objectKey := types.NamespacedName{
- Name: credentialsSecretName,
- Namespace: namespace,
- }
-
- // only ClusterStore is allowed to set namespace (and then it's required)
- if isClusterKind {
- if credentialsSecretName != "" && auth.Namespace == nil {
- return "", fmt.Errorf(errInvalidClusterStoreMissingK8sSecretNamespace)
- } else if credentialsSecretName != "" {
- objectKey.Namespace = *auth.Namespace
- }
- }
-
- err := kube.Get(ctx, objectKey, credentialsSecret)
- if err != nil {
- return "", fmt.Errorf(errFetchK8sSecret, err)
- }
- data := credentialsSecret.Data[auth.Key]
- if (data == nil) || (len(data) == 0) {
- return "", fmt.Errorf(errMissingK8sSecretKey, auth.Key)
- }
-
- return string(data), nil
+func getKeeperSecurityAuth(ctx context.Context, store *esv1beta1.KeeperSecurityProvider, kube kclient.Client, storeKind, namespace string) (string, error) {
+ return resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ storeKind,
+ namespace,
+ &store.Auth)
}
diff --git a/pkg/provider/kubernetes/auth.go b/pkg/provider/kubernetes/auth.go
index 4a760dc5e..a4118de67 100644
--- a/pkg/provider/kubernetes/auth.go
+++ b/pkg/provider/kubernetes/auth.go
@@ -25,6 +25,7 @@ import (
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
@@ -128,31 +129,18 @@ func (c *Client) serviceAccountToken(ctx context.Context, serviceAccountRef *esm
return []byte(tr.Status.Token), nil
}
-func (c *Client) fetchSecretKey(ctx context.Context, key esmeta.SecretKeySelector) ([]byte, error) {
- keySecret := &corev1.Secret{}
- objectKey := types.NamespacedName{
- Name: key.Name,
- Namespace: c.namespace,
- }
- // only ClusterStore is allowed to set namespace (and then it's required)
- if c.storeKind == esv1beta1.ClusterSecretStoreKind {
- if key.Namespace == nil {
- return nil, fmt.Errorf(errInvalidClusterStoreMissingNamespace)
- }
- objectKey.Namespace = *key.Namespace
- }
- err := c.ctrlClient.Get(ctx, objectKey, keySecret)
+func (c *Client) fetchSecretKey(ctx context.Context, ref esmeta.SecretKeySelector) ([]byte, error) {
+ secret, err := resolvers.SecretKeyRef(
+ ctx,
+ c.ctrlClient,
+ c.storeKind,
+ c.namespace,
+ &ref,
+ )
if err != nil {
- return nil, fmt.Errorf(errFetchCredentials, err)
+ return nil, err
}
- val, ok := keySecret.Data[key.Key]
- if !ok {
- return nil, fmt.Errorf(errMissingCredentials, key.Key)
- }
- if len(val) == 0 {
- return nil, fmt.Errorf(errEmptyKey, key.Key)
- }
- return val, nil
+ return []byte(secret), nil
}
func (c *Client) fetchConfigMapKey(ctx context.Context, key esmeta.SecretKeySelector) ([]byte, error) {
diff --git a/pkg/provider/onepassword/onepassword.go b/pkg/provider/onepassword/onepassword.go
index 2e42420e0..936beedd1 100644
--- a/pkg/provider/onepassword/onepassword.go
+++ b/pkg/provider/onepassword/onepassword.go
@@ -23,12 +23,12 @@ import (
"github.com/1Password/connect-sdk-go/connect"
"github.com/1Password/connect-sdk-go/onepassword"
corev1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
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"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
@@ -95,29 +95,18 @@ func (provider *ProviderOnePassword) Capabilities() esv1beta1.SecretStoreCapabil
// NewClient constructs a 1Password Provider.
func (provider *ProviderOnePassword) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
config := store.GetSpec().Provider.OnePassword
-
- credentialsSecret := &corev1.Secret{}
- objectKey := types.NamespacedName{
- Name: config.Auth.SecretRef.ConnectToken.Name,
- Namespace: namespace,
- }
-
- // only ClusterSecretStore is allowed to set namespace (and then it's required)
- if store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind {
- objectKey.Namespace = *config.Auth.SecretRef.ConnectToken.Namespace
- }
-
- err := kube.Get(ctx, objectKey, credentialsSecret)
+ token, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ store.GetKind(),
+ namespace,
+ &config.Auth.SecretRef.ConnectToken,
+ )
if err != nil {
- return nil, fmt.Errorf(errFetchK8sSecret, err)
+ return nil, err
}
- token := credentialsSecret.Data[config.Auth.SecretRef.ConnectToken.Key]
- if (token == nil) || (len(token) == 0) {
- return nil, fmt.Errorf(errMissingToken)
- }
- provider.client = connect.NewClientWithUserAgent(config.ConnectHost, string(token), userAgent)
+ provider.client = connect.NewClientWithUserAgent(config.ConnectHost, token, userAgent)
provider.vaults = config.Vaults
-
return provider, nil
}
diff --git a/pkg/provider/oracle/oracle.go b/pkg/provider/oracle/oracle.go
index 5a0cd4838..4940ba826 100644
--- a/pkg/provider/oracle/oracle.go
+++ b/pkg/provider/oracle/oracle.go
@@ -32,7 +32,6 @@ import (
"github.com/oracle/oci-go-sdk/v65/vault"
"github.com/tidwall/gjson"
corev1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
kclient "sigs.k8s.io/controller-runtime/pkg/client"
ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
@@ -40,23 +39,23 @@ import (
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const (
- errOracleClient = "cannot setup new oracle client: %w"
- errORACLECredSecretName = "invalid oracle SecretStore resource: missing oracle APIKey"
- errUninitalizedOracleProvider = "provider oracle is not initialized"
- errInvalidClusterStoreMissingSKNamespace = "invalid ClusterStore, missing namespace"
- errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
- errMissingPK = "missing PrivateKey"
- errMissingUser = "missing User ID"
- errMissingTenancy = "missing Tenancy ID"
- errMissingRegion = "missing Region"
- errMissingFingerprint = "missing Fingerprint"
- errMissingVault = "missing Vault"
- errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
- errMissingKey = "missing Key in secret: %s"
- errUnexpectedContent = "unexpected secret bundle content"
+ errOracleClient = "cannot setup new oracle client: %w"
+ errORACLECredSecretName = "invalid oracle SecretStore resource: missing oracle APIKey"
+ errUninitalizedOracleProvider = "provider oracle is not initialized"
+ errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
+ errMissingPK = "missing PrivateKey"
+ errMissingUser = "missing User ID"
+ errMissingTenancy = "missing Tenancy ID"
+ errMissingRegion = "missing Region"
+ errMissingFingerprint = "missing Fingerprint"
+ errMissingVault = "missing Vault"
+ errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
+ errMissingKey = "missing Key in secret: %s"
+ errUnexpectedContent = "unexpected secret bundle content"
)
// https://github.com/external-secrets/external-secrets/issues/644
@@ -398,27 +397,17 @@ func getSecretData(ctx context.Context, kube kclient.Client, namespace, storeKin
if secretRef.Name == "" {
return "", fmt.Errorf(errORACLECredSecretName)
}
-
- objectKey := types.NamespacedName{
- Name: secretRef.Name,
- Namespace: namespace,
- }
-
- // only ClusterStore is allowed to set namespace (and then it's required)
- if storeKind == esv1beta1.ClusterSecretStoreKind {
- if secretRef.Namespace == nil {
- return "", fmt.Errorf(errInvalidClusterStoreMissingSKNamespace)
- }
- objectKey.Namespace = *secretRef.Namespace
- }
-
- secret := corev1.Secret{}
- err := kube.Get(ctx, objectKey, &secret)
+ secret, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ storeKind,
+ namespace,
+ &secretRef,
+ )
if err != nil {
return "", fmt.Errorf(errFetchSAKSecret, err)
}
-
- return string(secret.Data[secretRef.Key]), nil
+ return secret, nil
}
func getUserAuthConfigurationProvider(ctx context.Context, kube kclient.Client, store *esv1beta1.OracleProvider, namespace, storeKind, region string) (common.ConfigurationProvider, error) {
diff --git a/pkg/provider/oracle/oracle_test.go b/pkg/provider/oracle/oracle_test.go
index 6bc209528..c46702a47 100644
--- a/pkg/provider/oracle/oracle_test.go
+++ b/pkg/provider/oracle/oracle_test.go
@@ -440,7 +440,7 @@ func TestVaultManagementService_NewClient(t *testing.T) {
},
},
},
- expectedErr: `could not fetch SecretAccessKey secret: secrets "non-existing-secret"`,
+ expectedErr: `cannot get Kubernetes secret "non-existing-secret": secrets "non-existing-secret" not found`,
},
{
desc: "invalid retry interval",
diff --git a/pkg/provider/scaleway/provider.go b/pkg/provider/scaleway/provider.go
index 1ba131b6a..404d98f1f 100644
--- a/pkg/provider/scaleway/provider.go
+++ b/pkg/provider/scaleway/provider.go
@@ -21,12 +21,12 @@ import (
smapi "github.com/scaleway/scaleway-sdk-go/api/secret/v1alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/scaleway-sdk-go/validation"
- corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
kubeClient "sigs.k8s.io/controller-runtime/pkg/client"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
var (
@@ -52,12 +52,12 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
return nil, fmt.Errorf("when using a ClusterSecretStore, namespaces must be explicitly set")
}
- accessKey, err := loadConfigSecret(ctx, cfg.AccessKey, kube, namespace)
+ accessKey, err := loadConfigSecret(ctx, cfg.AccessKey, kube, namespace, store.GetKind())
if err != nil {
return nil, err
}
- secretKey, err := loadConfigSecret(ctx, cfg.SecretKey, kube, namespace)
+ secretKey, err := loadConfigSecret(ctx, cfg.SecretKey, kube, namespace, store.GetKind())
if err != nil {
return nil, err
}
@@ -80,42 +80,17 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
}, nil
}
-func loadConfigSecret(ctx context.Context, ref *esv1beta1.ScalewayProviderSecretRef, kube kubeClient.Client, defaultNamespace string) (string, error) {
+func loadConfigSecret(ctx context.Context, ref *esv1beta1.ScalewayProviderSecretRef, kube kubeClient.Client, defaultNamespace, storeKind string) (string, error) {
if ref.SecretRef == nil {
return ref.Value, nil
}
-
- namespace := defaultNamespace
- if ref.SecretRef.Namespace != nil {
- namespace = *ref.SecretRef.Namespace
- }
-
- if ref.SecretRef.Name == "" {
- return "", fmt.Errorf("must specify a value or a reference to a secret")
- }
-
- if ref.SecretRef.Key == "" {
- return "", fmt.Errorf("must specify a secret key")
- }
-
- objKey := kubeClient.ObjectKey{
- Namespace: namespace,
- Name: ref.SecretRef.Name,
- }
-
- secret := corev1.Secret{}
-
- err := kube.Get(ctx, objKey, &secret)
- if err != nil {
- return "", err
- }
-
- value, ok := secret.Data[ref.SecretRef.Key]
- if !ok {
- return "", fmt.Errorf("no such key in secret: %v", ref.SecretRef.Key)
- }
-
- return string(value), nil
+ return resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ storeKind,
+ defaultNamespace,
+ ref.SecretRef,
+ )
}
func validateSecretRef(store esv1beta1.GenericStore, ref *esv1beta1.ScalewayProviderSecretRef) error {
diff --git a/pkg/provider/senhasegura/auth/iso.go b/pkg/provider/senhasegura/auth/iso.go
index 8478d1c72..7c2713436 100644
--- a/pkg/provider/senhasegura/auth/iso.go
+++ b/pkg/provider/senhasegura/auth/iso.go
@@ -28,6 +28,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
type ISOInterface interface {
@@ -76,12 +77,18 @@ func Authenticate(ctx context.Context, store esv1beta1.GenericStore, provider *e
IsoSessionFromSecretRef initialize an ISO OAuth2 flow with .spec.provider.senhasegura.auth.isoSecretRef parameters.
*/
func (s *SenhaseguraIsoSession) IsoSessionFromSecretRef(ctx context.Context, provider *esv1beta1.SenhaseguraProvider, store esv1beta1.GenericStore, kube client.Client, namespace string) (*SenhaseguraIsoSession, error) {
- clientSecret, err := getKubernetesSecret(ctx, provider.Auth.ClientSecret, store, kube, namespace)
+ secret, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ store.GetKind(),
+ namespace,
+ &provider.Auth.ClientSecret,
+ )
if err != nil {
return &SenhaseguraIsoSession{}, err
}
- isoToken, err := s.GetIsoToken(provider.Auth.ClientID, clientSecret, provider.URL, provider.IgnoreSslCertificate)
+ isoToken, err := s.GetIsoToken(provider.Auth.ClientID, secret, provider.URL, provider.IgnoreSslCertificate)
if err != nil {
return &SenhaseguraIsoSession{}, err
}
diff --git a/pkg/provider/senhasegura/auth/kubernetes_secret.go b/pkg/provider/senhasegura/auth/kubernetes_secret.go
deleted file mode 100644
index 59747047c..000000000
--- a/pkg/provider/senhasegura/auth/kubernetes_secret.go
+++ /dev/null
@@ -1,57 +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 auth
-
-import (
- "context"
- "fmt"
-
- v1 "k8s.io/api/core/v1"
- "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"
-)
-
-const (
- errRequiredNamespaceNotFound = "invalid ClusterSecretStore: missing namespace in %s"
- errCannotFetchKubernetesSecret = "could not fetch Kubernetes secret %s"
-)
-
-/*
-getKubernetesSecret get Kubernetes Secret based on object parameter in namespace where ESO is installed or another, if ClusterSecretStore is used.
-*/
-func getKubernetesSecret(ctx context.Context, object esmeta.SecretKeySelector, store esv1beta1.GenericStore, kube client.Client, namespace string) (string, error) {
- ke := client.ObjectKey{
- Name: object.Name,
- Namespace: namespace, // Default to ExternalSecret namespace
- }
-
- // Only ClusterStore is allowed to set namespace (and then it's required)
- if store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind {
- if object.Namespace == nil {
- return "", fmt.Errorf(errRequiredNamespaceNotFound, object.Key)
- }
- ke.Namespace = *object.Namespace
- }
-
- secret := v1.Secret{}
- err := kube.Get(ctx, ke, &secret)
- if err != nil {
- return "", fmt.Errorf(errCannotFetchKubernetesSecret, object.Name)
- }
-
- return string(secret.Data[object.Key]), nil
-}
diff --git a/pkg/provider/vault/iamauth/iamauth.go b/pkg/provider/vault/iamauth/iamauth.go
index e26631834..74192db1f 100644
--- a/pkg/provider/vault/iamauth/iamauth.go
+++ b/pkg/provider/vault/iamauth/iamauth.go
@@ -41,6 +41,7 @@ import (
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
"github.com/external-secrets/external-secrets/pkg/provider/vault/util"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
var (
@@ -54,14 +55,6 @@ const (
STSEndpointEnv = "AWS_STS_ENDPOINT"
AWSWebIdentityTokenFileEnvVar = "AWS_WEB_IDENTITY_TOKEN_FILE"
-
- errInvalidClusterStoreMissingAKIDNamespace = "invalid ClusterSecretStore: missing AWS AccessKeyID Namespace"
- errInvalidClusterStoreMissingSAKNamespace = "invalid ClusterSecretStore: missing AWS SecretAccessKey Namespace"
- errFetchAKIDSecret = "could not fetch accessKeyID secret: %w"
- errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
- errFetchSTSecret = "could not fetch SessionToken secret: %w"
- errMissingSAK = "missing SecretAccessKey"
- errMissingAKID = "missing AccessKeyID"
)
// DefaultJWTProvider returns a credentials.Provider that calls the AssumeRoleWithWebidentity
@@ -232,58 +225,37 @@ func CredsFromControllerServiceAccount(ctx context.Context, saname, ns, region s
// construct a aws.Credentials object
// The namespace of the external secret is used if the ClusterSecretStore does not specify a namespace (referentAuth)
// If the ClusterSecretStore defines a namespace it will take precedence.
-func CredsFromSecretRef(ctx context.Context, auth esv1beta1.VaultIamAuth, isClusterKind bool, kube kclient.Client, namespace string) (*credentials.Credentials, error) {
- ke := kclient.ObjectKey{
- Name: auth.SecretRef.AccessKeyID.Name,
- Namespace: namespace,
- }
- if isClusterKind && auth.SecretRef.AccessKeyID.Namespace != nil {
- ke.Namespace = *auth.SecretRef.AccessKeyID.Namespace
- }
- akSecret := v1.Secret{}
- err := kube.Get(ctx, ke, &akSecret)
+func CredsFromSecretRef(ctx context.Context, auth esv1beta1.VaultIamAuth, storeKind string, kube kclient.Client, namespace string) (*credentials.Credentials, error) {
+ akid, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ storeKind,
+ namespace,
+ &auth.SecretRef.AccessKeyID,
+ )
if err != nil {
- return nil, fmt.Errorf(errFetchAKIDSecret, err)
+ return nil, err
}
- ke = kclient.ObjectKey{
- Name: auth.SecretRef.SecretAccessKey.Name,
- Namespace: namespace,
- }
- if isClusterKind && auth.SecretRef.SecretAccessKey.Namespace != nil {
- ke.Namespace = *auth.SecretRef.SecretAccessKey.Namespace
- }
- sakSecret := v1.Secret{}
- err = kube.Get(ctx, ke, &sakSecret)
+ sak, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ storeKind,
+ namespace,
+ &auth.SecretRef.SecretAccessKey,
+ )
if err != nil {
- return nil, fmt.Errorf(errFetchSAKSecret, err)
- }
- sak := string(sakSecret.Data[auth.SecretRef.SecretAccessKey.Key])
- aks := string(akSecret.Data[auth.SecretRef.AccessKeyID.Key])
- if sak == "" {
- return nil, fmt.Errorf(errMissingSAK)
- }
- if aks == "" {
- return nil, fmt.Errorf(errMissingAKID)
+ return nil, err
}
- var sessionToken string
- if auth.SecretRef.SessionToken != nil {
- ke = kclient.ObjectKey{
- Name: auth.SecretRef.SessionToken.Name,
- Namespace: namespace,
- }
- if isClusterKind && auth.SecretRef.SessionToken.Namespace != nil {
- ke.Namespace = *auth.SecretRef.SessionToken.Namespace
- }
- stSecret := v1.Secret{}
- err = kube.Get(ctx, ke, &stSecret)
- if err != nil {
- return nil, fmt.Errorf(errFetchSTSecret, err)
- }
- sessionToken = string(stSecret.Data[auth.SecretRef.SessionToken.Key])
- }
-
- return credentials.NewStaticCredentials(aks, sak, sessionToken), err
+ // session token is optional
+ sessionToken, _ := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ storeKind,
+ namespace,
+ auth.SecretRef.SessionToken,
+ )
+ return credentials.NewStaticCredentials(akid, sak, sessionToken), err
}
type STSProvider func(*session.Session) stsiface.STSAPI
diff --git a/pkg/provider/vault/vault.go b/pkg/provider/vault/vault.go
index ada6020bb..13e66d889 100644
--- a/pkg/provider/vault/vault.go
+++ b/pkg/provider/vault/vault.go
@@ -40,7 +40,7 @@ import (
authuserpass "github.com/hashicorp/vault/api/auth/userpass"
"github.com/spf13/pflag"
"github.com/tidwall/gjson"
- authenticationv1 "k8s.io/api/authentication/v1"
+ authv1 "k8s.io/api/authentication/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
@@ -60,6 +60,7 @@ import (
vaultiamauth "github.com/external-secrets/external-secrets/pkg/provider/vault/iamauth"
"github.com/external-secrets/external-secrets/pkg/provider/vault/util"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
var (
@@ -1088,7 +1089,7 @@ func (v *client) configureClientTLS(ctx context.Context, cfg *vault.Config) erro
if clientTLS.KeySecretRef.Key == "" {
clientTLS.KeySecretRef.Key = corev1.TLSPrivateKeyKey
}
- clientKey, err := v.secretKeyRef(ctx, clientTLS.KeySecretRef)
+ clientKey, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, clientTLS.KeySecretRef)
if err != nil {
return err
}
@@ -1096,7 +1097,7 @@ func (v *client) configureClientTLS(ctx context.Context, cfg *vault.Config) erro
if clientTLS.CertSecretRef.Key == "" {
clientTLS.CertSecretRef.Key = corev1.TLSCertKey
}
- clientCert, err := v.secretKeyRef(ctx, clientTLS.CertSecretRef)
+ clientCert, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, clientTLS.CertSecretRef)
if err != nil {
return err
}
@@ -1125,7 +1126,7 @@ func getCertFromSecret(v *client) ([]byte, error) {
}
ctx := context.Background()
- res, err := v.secretKeyRef(ctx, &secretRef)
+ res, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, &secretRef)
if err != nil {
return nil, fmt.Errorf(errVaultCert, err)
}
@@ -1226,7 +1227,7 @@ func (v *client) setAuth(ctx context.Context, cfg *vault.Config) error {
func setSecretKeyToken(ctx context.Context, v *client) (bool, error) {
tokenRef := v.store.Auth.TokenSecretRef
if tokenRef != nil {
- token, err := v.secretKeyRef(ctx, tokenRef)
+ token, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, tokenRef)
if err != nil {
return true, err
}
@@ -1339,71 +1340,19 @@ func (v *client) secretKeyRefForServiceAccount(ctx context.Context, serviceAccou
return "", fmt.Errorf(errGetKubeSASecrets, ref.Name)
}
for _, tokenRef := range serviceAccount.Secrets {
- retval, err := v.secretKeyRef(ctx, &esmeta.SecretKeySelector{
+ token, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, &esmeta.SecretKeySelector{
Name: tokenRef.Name,
Namespace: &ref.Namespace,
Key: "token",
})
-
if err != nil {
continue
}
-
- return retval, nil
+ return token, nil
}
return "", fmt.Errorf(errGetKubeSANoToken, ref.Name)
}
-func (v *client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
- secret := &corev1.Secret{}
- ref := types.NamespacedName{
- Namespace: v.namespace,
- Name: secretRef.Name,
- }
- if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
- (secretRef.Namespace != nil) {
- ref.Namespace = *secretRef.Namespace
- }
- err := v.kube.Get(ctx, ref, secret)
- if err != nil {
- return "", fmt.Errorf(errGetKubeSecret, ref.Name, ref.Namespace, err)
- }
-
- keyBytes, ok := secret.Data[secretRef.Key]
- if !ok {
- return "", fmt.Errorf(errSecretKeyFmt, secretRef.Key)
- }
-
- value := string(keyBytes)
- valueStr := strings.TrimSpace(value)
- return valueStr, nil
-}
-
-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,
- },
- Spec: authenticationv1.TokenRequestSpec{
- Audiences: audiences,
- ExpirationSeconds: &expirationSeconds,
- },
- }
- if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
- (serviceAccountRef.Namespace != nil) {
- tokenRequest.Namespace = *serviceAccountRef.Namespace
- }
- tokenResponse, err := v.corev1.ServiceAccounts(tokenRequest.Namespace).CreateToken(ctx, serviceAccountRef.Name, tokenRequest, metav1.CreateOptions{})
- if err != nil {
- return "", fmt.Errorf(errGetKubeSATokenRequest, serviceAccountRef.Name, err)
- }
- return tokenResponse.Status.Token, nil
-}
-
// checkToken does a lookup and checks if the provided token exists.
func checkToken(ctx context.Context, token util.Token) (bool, error) {
// https://www.vaultproject.io/api-docs/auth/token#lookup-a-token-self
@@ -1447,7 +1396,7 @@ func (v *client) requestTokenWithAppRoleRef(ctx context.Context, appRole *esv1be
if appRole.RoleID != "" { // use roleId from CRD, if configured
roleID = strings.TrimSpace(appRole.RoleID)
} else if appRole.RoleRef != nil { // use RoleID from Secret, if configured
- roleID, err = v.secretKeyRef(ctx, appRole.RoleRef)
+ roleID, err = resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, appRole.RoleRef)
if err != nil {
return err
}
@@ -1455,7 +1404,7 @@ func (v *client) requestTokenWithAppRoleRef(ctx context.Context, appRole *esv1be
return fmt.Errorf(errInvalidAppRoleID)
}
- secretID, err := v.secretKeyRef(ctx, &appRole.SecretRef)
+ secretID, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, &appRole.SecretRef)
if err != nil {
return err
}
@@ -1503,7 +1452,14 @@ func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.Vaul
// 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)
+ jwt, err = createServiceAccountToken(
+ ctx,
+ v.corev1,
+ v.storeKind,
+ v.namespace,
+ *kubernetesAuth.ServiceAccountRef,
+ nil,
+ 600)
if err != nil {
return "", err
}
@@ -1514,7 +1470,7 @@ func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.Vaul
tokenRef = kubernetesAuth.SecretRef.DeepCopy()
tokenRef.Key = "token"
}
- jwt, err := v.secretKeyRef(ctx, tokenRef)
+ jwt, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, tokenRef)
if err != nil {
return "", err
}
@@ -1536,8 +1492,7 @@ func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.Vaul
func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1beta1.VaultLdapAuth) error {
username := strings.TrimSpace(ldapAuth.Username)
-
- password, err := v.secretKeyRef(ctx, &ldapAuth.SecretRef)
+ password, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, &ldapAuth.SecretRef)
if err != nil {
return err
}
@@ -1556,8 +1511,7 @@ func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1bet
func (v *client) requestTokenWithUserPassAuth(ctx context.Context, userPassAuth *esv1beta1.VaultUserPassAuth) error {
username := strings.TrimSpace(userPassAuth.Username)
-
- password, err := v.secretKeyRef(ctx, &userPassAuth.SecretRef)
+ password, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, &userPassAuth.SecretRef)
if err != nil {
return err
}
@@ -1579,7 +1533,7 @@ func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1
var jwt string
var err error
if jwtAuth.SecretRef != nil {
- jwt, err = v.secretKeyRef(ctx, jwtAuth.SecretRef)
+ jwt, err = resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, jwtAuth.SecretRef)
} else if k8sServiceAccountToken := jwtAuth.KubernetesServiceAccountToken; k8sServiceAccountToken != nil {
audiences := k8sServiceAccountToken.Audiences
if audiences == nil {
@@ -1590,7 +1544,14 @@ func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1
tmp := int64(600)
expirationSeconds = &tmp
}
- jwt, err = v.serviceAccountToken(ctx, k8sServiceAccountToken.ServiceAccountRef, *audiences, *expirationSeconds)
+ jwt, err = createServiceAccountToken(
+ ctx,
+ v.corev1,
+ v.storeKind,
+ v.namespace,
+ k8sServiceAccountToken.ServiceAccountRef,
+ *audiences,
+ *expirationSeconds)
} else {
err = fmt.Errorf(errJwtNoTokenSource)
}
@@ -1618,12 +1579,12 @@ func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1
}
func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1beta1.VaultCertAuth, cfg *vault.Config) error {
- clientKey, err := v.secretKeyRef(ctx, &certAuth.SecretRef)
+ clientKey, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, &certAuth.SecretRef)
if err != nil {
return err
}
- clientCert, err := v.secretKeyRef(ctx, &certAuth.ClientCert)
+ clientCert, err := resolvers.SecretKeyRef(ctx, v.kube, v.storeKind, v.namespace, &certAuth.ClientCert)
if err != nil {
return err
}
@@ -1651,7 +1612,40 @@ func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1bet
return nil
}
-func (v *client) requestTokenWithIamAuth(ctx context.Context, iamAuth *esv1beta1.VaultIamAuth, ick bool, k kclient.Client, n string, jwtProvider util.JwtProviderFactory, assumeRoler vaultiamauth.STSProvider) error {
+func createServiceAccountToken(
+ ctx context.Context,
+ corev1Client typedcorev1.CoreV1Interface,
+ storeKind string,
+ namespace string,
+ serviceAccountRef esmeta.ServiceAccountSelector,
+ additionalAud []string,
+ expirationSeconds int64) (string, error) {
+ audiences := serviceAccountRef.Audiences
+ if len(additionalAud) > 0 {
+ audiences = append(audiences, additionalAud...)
+ }
+ tokenRequest := &authv1.TokenRequest{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: namespace,
+ },
+ Spec: authv1.TokenRequestSpec{
+ Audiences: audiences,
+ ExpirationSeconds: &expirationSeconds,
+ },
+ }
+ if (storeKind == esv1beta1.ClusterSecretStoreKind) &&
+ (serviceAccountRef.Namespace != nil) {
+ tokenRequest.Namespace = *serviceAccountRef.Namespace
+ }
+ tokenResponse, err := corev1Client.ServiceAccounts(tokenRequest.Namespace).
+ CreateToken(ctx, serviceAccountRef.Name, tokenRequest, metav1.CreateOptions{})
+ if err != nil {
+ return "", fmt.Errorf(errGetKubeSATokenRequest, serviceAccountRef.Name, err)
+ }
+ return tokenResponse.Status.Token, nil
+}
+
+func (v *client) requestTokenWithIamAuth(ctx context.Context, iamAuth *esv1beta1.VaultIamAuth, isClusterKind bool, k kclient.Client, n string, jwtProvider util.JwtProviderFactory, assumeRoler vaultiamauth.STSProvider) error {
jwtAuth := iamAuth.JWTAuth
secretRefAuth := iamAuth.SecretRef
regionAWS := defaultAWSRegion
@@ -1665,13 +1659,13 @@ func (v *client) requestTokenWithIamAuth(ctx context.Context, iamAuth *esv1beta1
var creds *credentials.Credentials
var err error
if jwtAuth != nil { // use credentials from a sa explicitly defined and referenced. Highest preference is given to this method/configuration.
- creds, err = vaultiamauth.CredsFromServiceAccount(ctx, *iamAuth, regionAWS, ick, k, n, jwtProvider)
+ creds, err = vaultiamauth.CredsFromServiceAccount(ctx, *iamAuth, regionAWS, isClusterKind, k, n, jwtProvider)
if err != nil {
return err
}
} else if secretRefAuth != nil { // if jwtAuth is not defined, check if secretRef is defined. Second preference.
logger.V(1).Info("using credentials from secretRef")
- creds, err = vaultiamauth.CredsFromSecretRef(ctx, *iamAuth, ick, k, n)
+ creds, err = vaultiamauth.CredsFromSecretRef(ctx, *iamAuth, v.storeKind, k, n)
if err != nil {
return err
}
diff --git a/pkg/provider/vault/vault_test.go b/pkg/provider/vault/vault_test.go
index 1c7302f6f..770c1c668 100644
--- a/pkg/provider/vault/vault_test.go
+++ b/pkg/provider/vault/vault_test.go
@@ -332,7 +332,7 @@ MIIFkTCCA3mgAwIBAgIUBEUg3m/WqAsWHG4Q/II3IePFfuowDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE
kube: clientfake.NewClientBuilder().Build(),
},
want: want{
- err: fmt.Errorf(errGetKubeSecret, "vault-secret", "default", errors.New("secrets \"vault-secret\" not found")),
+ err: fmt.Errorf(`cannot get Kubernetes secret "vault-secret": %w`, errors.New(`secrets "vault-secret" not found`)),
},
},
"SuccessfulVaultStoreWithCertAuth": {
diff --git a/pkg/provider/webhook/webhook.go b/pkg/provider/webhook/webhook.go
index 0d3ad605f..c60e6b16a 100644
--- a/pkg/provider/webhook/webhook.go
+++ b/pkg/provider/webhook/webhook.go
@@ -25,7 +25,6 @@ import (
"net/http"
"net/url"
"strconv"
- "strings"
tpl "text/template"
"time"
@@ -39,6 +38,7 @@ import (
"github.com/external-secrets/external-secrets/pkg/metrics"
"github.com/external-secrets/external-secrets/pkg/template/v2"
"github.com/external-secrets/external-secrets/pkg/utils"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
// https://github.com/external-secrets/external-secrets/issues/644
@@ -383,8 +383,9 @@ func (w *WebHook) getCACertPool(provider *esv1beta1.WebhookProvider) (*x509.Cert
func (w *WebHook) getCertFromSecret(provider *esv1beta1.WebhookProvider) ([]byte, error) {
secretRef := esmeta.SecretKeySelector{
- Name: provider.CAProvider.Name,
- Key: provider.CAProvider.Key,
+ Name: provider.CAProvider.Name,
+ Namespace: &w.namespace,
+ Key: provider.CAProvider.Key,
}
if provider.CAProvider.Namespace != nil {
@@ -392,37 +393,18 @@ func (w *WebHook) getCertFromSecret(provider *esv1beta1.WebhookProvider) ([]byte
}
ctx := context.Background()
- res, err := w.secretKeyRef(ctx, &secretRef)
+ cert, err := resolvers.SecretKeyRef(
+ ctx,
+ w.kube,
+ w.storeKind,
+ w.namespace,
+ &secretRef,
+ )
if err != nil {
return nil, err
}
- return []byte(res), nil
-}
-
-func (w *WebHook) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
- secret := &corev1.Secret{}
- ref := client.ObjectKey{
- Namespace: w.namespace,
- Name: secretRef.Name,
- }
- if (w.storeKind == esv1beta1.ClusterSecretStoreKind) &&
- (secretRef.Namespace != nil) {
- ref.Namespace = *secretRef.Namespace
- }
- err := w.kube.Get(ctx, ref, secret)
- if err != nil {
- return "", err
- }
-
- keyBytes, ok := secret.Data[secretRef.Key]
- if !ok {
- return "", err
- }
-
- value := string(keyBytes)
- valueStr := strings.TrimSpace(value)
- return valueStr, nil
+ return []byte(cert), nil
}
func (w *WebHook) getCertFromConfigMap(provider *esv1beta1.WebhookProvider) ([]byte, error) {
diff --git a/pkg/provider/yandex/certificatemanager/certificatemanager_test.go b/pkg/provider/yandex/certificatemanager/certificatemanager_test.go
index f4a7c248a..2c263a99b 100644
--- a/pkg/provider/yandex/certificatemanager/certificatemanager_test.go
+++ b/pkg/provider/yandex/certificatemanager/certificatemanager_test.go
@@ -80,7 +80,7 @@ func TestNewClient(t *testing.T) {
store.Spec.Provider.YandexCertificateManager.Auth.AuthorizedKey.Name = authorizedKeySecretName
store.Spec.Provider.YandexCertificateManager.Auth.AuthorizedKey.Key = authorizedKeySecretKey
secretClient, err = provider.NewClient(context.Background(), store, k8sClient, namespace)
- tassert.EqualError(t, err, "could not fetch AuthorizedKey secret: secrets \"authorizedKeySecretName\" not found")
+ tassert.EqualError(t, err, "cannot get Kubernetes secret \"authorizedKeySecretName\": secrets \"authorizedKeySecretName\" not found")
tassert.Nil(t, secretClient)
err = createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, newFakeAuthorizedKey()))
@@ -95,7 +95,7 @@ func TestNewClient(t *testing.T) {
},
}
secretClient, err = provider.NewClient(context.Background(), store, k8sClient, namespace)
- tassert.EqualError(t, err, "could not fetch CA certificate secret: secrets \"caCertificateSecretName\" not found")
+ tassert.EqualError(t, err, "cannot get Kubernetes secret \"caCertificateSecretName\": secrets \"caCertificateSecretName\" not found")
tassert.Nil(t, secretClient)
err = createK8sSecret(ctx, t, k8sClient, namespace, caCertificateSecretName, caCertificateSecretKey, []byte("it-is-not-a-certificate"))
diff --git a/pkg/provider/yandex/common/provider.go b/pkg/provider/yandex/common/provider.go
index 974d1fb97..156304fea 100644
--- a/pkg/provider/yandex/common/provider.go
+++ b/pkg/provider/yandex/common/provider.go
@@ -24,13 +24,12 @@ import (
"github.com/go-logr/logr"
"github.com/yandex-cloud/go-sdk/iamkey"
- corev1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
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"
clock2 "github.com/external-secrets/external-secrets/pkg/provider/yandex/common/clock"
+ "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
)
const maxSecretsClientLifetime = 5 * time.Minute // supposed SecretsClient lifetime is quite short
@@ -115,61 +114,36 @@ func (p *YandexCloudProvider) NewClient(ctx context.Context, store esv1beta1.Gen
return nil, err
}
- objectKey := types.NamespacedName{
- Name: input.AuthorizedKey.Name,
- Namespace: namespace,
- }
-
- // only ClusterStore is allowed to set namespace (and then it's required)
- if store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind {
- if input.AuthorizedKey.Namespace == nil {
- return nil, fmt.Errorf("invalid ClusterSecretStore: missing AuthorizedKey Namespace")
- }
- objectKey.Namespace = *input.AuthorizedKey.Namespace
- }
-
- authorizedKeySecret := &corev1.Secret{}
- err = kube.Get(ctx, objectKey, authorizedKeySecret)
+ key, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ store.GetKind(),
+ namespace,
+ &input.AuthorizedKey,
+ )
if err != nil {
- return nil, fmt.Errorf("could not fetch AuthorizedKey secret: %w", err)
- }
-
- authorizedKeySecretData := authorizedKeySecret.Data[input.AuthorizedKey.Key]
- if (authorizedKeySecretData == nil) || (len(authorizedKeySecretData) == 0) {
- return nil, fmt.Errorf("missing AuthorizedKey")
+ return nil, err
}
var authorizedKey iamkey.Key
- err = json.Unmarshal(authorizedKeySecretData, &authorizedKey)
+ err = json.Unmarshal([]byte(key), &authorizedKey)
if err != nil {
return nil, fmt.Errorf("unable to unmarshal authorized key: %w", err)
}
var caCertificateData []byte
-
if input.CACertificate != nil {
- certObjectKey := types.NamespacedName{
- Name: input.CACertificate.Name,
- Namespace: namespace,
- }
-
- if store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind {
- if input.CACertificate.Namespace == nil {
- return nil, fmt.Errorf("invalid ClusterSecretStore: missing CA certificate Namespace")
- }
- certObjectKey.Namespace = *input.CACertificate.Namespace
- }
-
- caCertificateSecret := &corev1.Secret{}
- err := kube.Get(ctx, certObjectKey, caCertificateSecret)
+ caCert, err := resolvers.SecretKeyRef(
+ ctx,
+ kube,
+ store.GetKind(),
+ namespace,
+ input.CACertificate,
+ )
if err != nil {
- return nil, fmt.Errorf("could not fetch CA certificate secret: %w", err)
- }
-
- caCertificateData = caCertificateSecret.Data[input.CACertificate.Key]
- if (caCertificateData == nil) || (len(caCertificateData) == 0) {
- return nil, fmt.Errorf("missing CA Certificate")
+ return nil, err
}
+ caCertificateData = []byte(caCert)
}
secretGetter, err := p.getOrCreateSecretGetter(ctx, input.APIEndpoint, &authorizedKey, caCertificateData)
diff --git a/pkg/provider/yandex/lockbox/lockbox_test.go b/pkg/provider/yandex/lockbox/lockbox_test.go
index 25794c9a1..fa8f70cd1 100644
--- a/pkg/provider/yandex/lockbox/lockbox_test.go
+++ b/pkg/provider/yandex/lockbox/lockbox_test.go
@@ -80,7 +80,7 @@ func TestNewClient(t *testing.T) {
store.Spec.Provider.YandexLockbox.Auth.AuthorizedKey.Name = authorizedKeySecretName
store.Spec.Provider.YandexLockbox.Auth.AuthorizedKey.Key = authorizedKeySecretKey
secretClient, err = provider.NewClient(context.Background(), store, k8sClient, namespace)
- tassert.EqualError(t, err, "could not fetch AuthorizedKey secret: secrets \"authorizedKeySecretName\" not found")
+ tassert.EqualError(t, err, "cannot get Kubernetes secret \"authorizedKeySecretName\": secrets \"authorizedKeySecretName\" not found")
tassert.Nil(t, secretClient)
err = createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, newFakeAuthorizedKey()))
@@ -95,7 +95,7 @@ func TestNewClient(t *testing.T) {
},
}
secretClient, err = provider.NewClient(context.Background(), store, k8sClient, namespace)
- tassert.EqualError(t, err, "could not fetch CA certificate secret: secrets \"caCertificateSecretName\" not found")
+ tassert.EqualError(t, err, "cannot get Kubernetes secret \"caCertificateSecretName\": secrets \"caCertificateSecretName\" not found")
tassert.Nil(t, secretClient)
err = createK8sSecret(ctx, t, k8sClient, namespace, caCertificateSecretName, caCertificateSecretKey, []byte("it-is-not-a-certificate"))
diff --git a/pkg/utils/resolvers/secret_ref.go b/pkg/utils/resolvers/secret_ref.go
new file mode 100644
index 000000000..5f7843f71
--- /dev/null
+++ b/pkg/utils/resolvers/secret_ref.go
@@ -0,0 +1,71 @@
+/*
+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 resolvers
+
+import (
+ "context"
+ "fmt"
+
+ corev1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/types"
+ "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"
+)
+
+const (
+
+ // This is used to determine if a store is cluster-scoped or not.
+ // The EmptyStoreKind is not cluster-scoped, hence resources
+ // cannot be resolved across namespaces.
+ // TODO: when we implement cluster-scoped generators
+ // we can remove this and replace it with a interface.
+ EmptyStoreKind = "EmptyStoreKind"
+
+ errGetKubeSecret = "cannot get Kubernetes secret %q: %w"
+ errSecretKeyFmt = "cannot find secret data for key: %q"
+ errGetKubeSATokenRequest = "cannot request Kubernetes service account token for service account %q: %w"
+)
+
+// SecretKeyRef resolves a metav1.SecretKeySelector and returns the value of the secret it points to.
+// A user must pass the namespace of the originating ExternalSecret, as this may differ
+// from the namespace defined in the SecretKeySelector.
+// This func ensures that only a ClusterSecretStore is able to request secrets across namespaces.
+func SecretKeyRef(
+ ctx context.Context,
+ c client.Client,
+ storeKind string,
+ esNamespace string,
+ ref *esmeta.SecretKeySelector) (string, error) {
+ key := types.NamespacedName{
+ Namespace: esNamespace,
+ Name: ref.Name,
+ }
+ if (storeKind == esv1beta1.ClusterSecretStoreKind) &&
+ (ref.Namespace != nil) {
+ key.Namespace = *ref.Namespace
+ }
+ secret := &corev1.Secret{}
+ err := c.Get(ctx, key, secret)
+ if err != nil {
+ return "", fmt.Errorf(errGetKubeSecret, ref.Name, err)
+ }
+ val, ok := secret.Data[ref.Key]
+ if !ok {
+ return "", fmt.Errorf(errSecretKeyFmt, ref.Key)
+ }
+ return string(val), nil
+}
diff --git a/pkg/utils/resolvers/secret_ref_test.go b/pkg/utils/resolvers/secret_ref_test.go
new file mode 100644
index 000000000..a3b8fdd2c
--- /dev/null
+++ b/pkg/utils/resolvers/secret_ref_test.go
@@ -0,0 +1,129 @@
+/*
+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 resolvers
+
+import (
+ "context"
+ "errors"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
+
+ esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+)
+
+func TestResolveSecretKeyRef(t *testing.T) {
+ ctx := context.TODO()
+ c := fake.NewClientBuilder().WithScheme(scheme.Scheme).Build()
+ testNamespace := "test-namespace"
+ testSecret := "test-secret"
+ testKey := "test-key"
+ testValue := "test-value"
+ secret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: testNamespace,
+ Name: testSecret,
+ },
+ Data: map[string][]byte{
+ testKey: []byte(testValue),
+ },
+ }
+ err := c.Create(ctx, secret)
+ require.NoError(t, err)
+
+ testCases := []struct {
+ name string
+ namespace string
+ storeKind string
+ selector *esmeta.SecretKeySelector
+ expected string
+ err error
+ }{
+ {
+ name: "namespaced secret store can access secret in same namespace",
+ namespace: testNamespace,
+ storeKind: "SecretStore",
+ selector: &esmeta.SecretKeySelector{
+ Name: testSecret,
+ Namespace: ptr.To(testNamespace),
+ Key: testKey,
+ },
+ expected: testValue,
+ err: nil,
+ },
+ {
+ name: "omitting namespace in secret store defaults to same namespace",
+ namespace: testNamespace,
+ storeKind: "SecretStore",
+ selector: &esmeta.SecretKeySelector{
+ Name: testSecret,
+ Key: testKey,
+ },
+ expected: testValue,
+ err: nil,
+ },
+ {
+ name: "namespaced secret store can not access secret in different namespace",
+ namespace: "other-namespace",
+ storeKind: "SecretStore",
+ selector: &esmeta.SecretKeySelector{
+ Name: testSecret,
+ Namespace: ptr.To(testNamespace),
+ Key: testKey,
+ },
+ err: errors.New(`cannot get Kubernetes secret "test-secret": secrets "test-secret" not found`),
+ },
+ {
+ name: "cluster secret store may access all namespaces",
+ storeKind: "ClusterSecretStore",
+ selector: &esmeta.SecretKeySelector{
+ Name: testSecret,
+ Namespace: ptr.To(testNamespace),
+ Key: testKey,
+ },
+ expected: testValue,
+ err: nil,
+ },
+ {
+ name: "key not found in secret",
+ namespace: testNamespace,
+ storeKind: "SecretStore",
+ selector: &esmeta.SecretKeySelector{
+ Name: testSecret,
+ Namespace: ptr.To(testNamespace),
+ Key: "xxxxxxxx",
+ },
+ expected: "",
+ err: errors.New(`cannot find secret data for key: "xxxxxxxx"`),
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ resolvedValue, err := SecretKeyRef(ctx, c, tc.storeKind, tc.namespace, tc.selector)
+ if tc.err != nil {
+ assert.EqualError(t, err, tc.err.Error())
+ } else {
+ require.NoError(t, err)
+ }
+ assert.Equal(t, tc.expected, resolvedValue)
+ })
+ }
+}