Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor/centralise secretKeyRef usage #3022

Merged
merged 4 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions apis/externalsecrets/v1beta1/secretstore_conjur_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
14 changes: 7 additions & 7 deletions apis/externalsecrets/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -1691,7 +1691,7 @@ Kubernetes meta/v1.LabelSelector
</tr>
</tbody>
</table>
<h3 id="external-secrets.io/v1beta1.ConjurApikey">ConjurApikey
<h3 id="external-secrets.io/v1beta1.ConjurAPIKey">ConjurAPIKey
</h3>
<p>
(<em>Appears on:</em>
Expand Down Expand Up @@ -1763,8 +1763,8 @@ External Secrets meta/v1.SecretKeySelector
<td>
<code>apikey</code></br>
<em>
<a href="#external-secrets.io/v1beta1.ConjurApikey">
ConjurApikey
<a href="#external-secrets.io/v1beta1.ConjurAPIKey">
ConjurAPIKey
</a>
</em>
</td>
Expand Down
5 changes: 3 additions & 2 deletions pkg/generator/gcr/gcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand Down Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️❤️

if err != nil {
return nil, err
}
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pkg/generator/gcr/gcr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
21 changes: 12 additions & 9 deletions pkg/provider/akeyless/akeyless.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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) {
Expand All @@ -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
Expand Down
32 changes: 4 additions & 28 deletions pkg/provider/akeyless/akeyless_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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",
Expand All @@ -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 {
Expand Down
86 changes: 30 additions & 56 deletions pkg/provider/akeyless/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
}
ke = client.ObjectKey{
Name: prov.Auth.SecretRef.AccessType.Name,
Namespace: a.namespace, // default to ExternalSecret namespace
return "", fmt.Errorf(errFetchAccessIDSecret, err)
}
// 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)
}

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
return "", fmt.Errorf(errFetchAccessTypeSecret, err)
}
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)
Expand Down