Skip to content

Commit

Permalink
internal/credentials: make kubernetes auth service account namespaced
Browse files Browse the repository at this point in the history
This commit adds the ability to specify a namespace for the service
account used to authenticate to Vault. This is useful when you want to
use a service account in a different namespace than the one the secret
(vaultStaticSecret, vaultDynamicSecret) is located. This change is
backwards compatible, so if no namespace is specified, the service
account will be looked up in the same namespace as the secret.

Example: Here the service account that will be used to authenticate to
Vault is the service account `default` that it is in the namespace
"vault-secrets-operator-system".

```yaml
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
  name: static-auth
  namespace: app
spec:
  vaultConnectionRef: vault-connection
  allowedNamespaces:
    - "*"
  method: kubernetes
  mount: demo-auth-mount
  kubernetes:
    role: role1
    serviceAccount: vault-secrets-operator-system/default
```

Closes hashicorp#336
  • Loading branch information
glerchundi committed Jan 4, 2024
1 parent 120446d commit 7ba3571
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
14 changes: 14 additions & 0 deletions internal/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,17 @@ func NewSyncableSecretMetaData(obj ctrlclient.Object) (*SyncableSecretMetaData,
return nil, fmt.Errorf("unsupported type %T", t)
}
}

// GetKubernetesServiceAccountNamespacedName returns the NamespacedName for the Kubernetes VaultAuth's configured
// serviceAccount.
// If the serviceAccount is empty then defaults Namespace and Name will be returned.
func GetKubernetesServiceAccountNamespacedName(a *secretsv1beta1.VaultAuthConfigKubernetes, providerNamespace string) (types.NamespacedName, error) {
if a.ServiceAccount == "" && providerNamespace == "" {
return types.NamespacedName{}, fmt.Errorf("provider's default namespace is not set, this is a bug")
}
saRef, err := parseResourceRef(a.ServiceAccount, providerNamespace)
if err != nil {
return types.NamespacedName{}, err
}
return saRef, nil
}
57 changes: 57 additions & 0 deletions internal/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,60 @@ func TestGetHCPAuthForObj(t *testing.T) {
})
}
}

func Test_GetKubernetesServiceAccountNamespacedName(t *testing.T) {
tests := []struct {
name string
a *secretsv1beta1.VaultAuthConfigKubernetes
providerNamespace string
want types.NamespacedName
wantErr assert.ErrorAssertionFunc
unsetDefaultsNS bool
}{
{
name: "empty-sa-ref",
a: &secretsv1beta1.VaultAuthConfigKubernetes{
ServiceAccount: "",
},
providerNamespace: "test",
want: types.NamespacedName{
Namespace: OperatorNamespace,
Name: consts.NameDefault,
},
wantErr: assert.NoError,
},
{
name: "with-sa-ref-with-ns",
a: &secretsv1beta1.VaultAuthConfigKubernetes{
ServiceAccount: "foo/bar",
},
providerNamespace: "baz",
want: types.NamespacedName{
Name: "bar",
Namespace: "foo",
},
wantErr: assert.NoError,
},
{
name: "with-sa-ref-without-ns",
a: &secretsv1beta1.VaultAuthConfigKubernetes{
ServiceAccount: "foo",
},
providerNamespace: "baz",
want: types.NamespacedName{
Namespace: "baz",
Name: "foo",
},
wantErr: assert.NoError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetKubernetesServiceAccountNamespacedName(tt.a, tt.providerNamespace)
if !tt.wantErr(t, err, fmt.Sprintf("getKubernetesServiceAccountNamespacedName(%v)", tt.a)) {
return
}
assert.Equalf(t, tt.want, got, "getKubernetesServiceAccountNamespacedName(%v)", tt.a)
})
}
}
9 changes: 7 additions & 2 deletions internal/credentials/vault/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log"

secretsv1beta1 "github.com/hashicorp/vault-secrets-operator/api/v1beta1"
"github.com/hashicorp/vault-secrets-operator/internal/common"
"github.com/hashicorp/vault-secrets-operator/internal/helpers"
)

Expand Down Expand Up @@ -56,9 +57,13 @@ func (l *KubernetesCredentialProvider) Init(ctx context.Context, client ctrlclie
}

func (l *KubernetesCredentialProvider) getServiceAccount(ctx context.Context, client ctrlclient.Client) (*corev1.ServiceAccount, error) {
a, err := common.GetKubernetesServiceAccountNamespacedName(l.authObj.Spec.Kubernetes, l.providerNamespace)
if err != nil {
return nil, err
}
key := ctrlclient.ObjectKey{
Namespace: l.providerNamespace,
Name: l.authObj.Spec.Kubernetes.ServiceAccount,
Namespace: a.Namespace,
Name: a.Name,
}
sa := &corev1.ServiceAccount{}
if err := client.Get(ctx, key, sa); err != nil {
Expand Down

0 comments on commit 7ba3571

Please sign in to comment.