This feature is in preview and is off by default. To enable, set features.alpha.sharedSecrets.enabled=true
when installing Spaces:
up space init --token-file="${SPACES_TOKEN_PATH}" "v${SPACES_VERSION}" \
...
--set "features.alpha.sharedSecrets.enabled=true" \
Upbound has built-in features to help you manage secrets for control planes running in a Space. Upbound offers:
- New
SharedSecretStore
andSharedExternalSecret
resources to manage syncing external secrets into groups of control planes. - Built-in support for External Secrets Operator (ESO) APIs. This allows you to synchronize secrets from external secret stores into a managed control plane.
Shared secrets in a Space
Spaces administrators can manage external secrets for multiple control planes with two new API types. SharedSecretStore
and SharedExternalSecret
allow admins to provision group-scoped secret stores and external secrets into their control planes.
Shared Secret Stores
SharedSecretStore
is group-scoped and created in the namespace of a Space containing one or more ControlPlane
instances.
It provisions ClusterSecretStore
resources into control planes with a group:
- If the provided selector matches, all matching control planes in the group receive the corresponding
ClusterSecretStore
. - If the provided selector doesn’t match, the non-matched control planes in the namespace remove the corresponding
ClusterSecretStore
- You can use the
ClusterSecretStore
within a control plane context:ExternalSecret
andClusterExternalSecret
can access the store as documented in the ESO documentation.
Shared External Secrets
SharedExternalSecret
is group-scoped and created in the namespace of a Space containing one or more ControlPlane
instances.
It enables provisioning of ClusterExternalSecret
resources into control planes within the group boundary:
- If the provided selector matches, all matching control planes in the group receive the corresponding
ClusterExternalSecret
. - If the provided selector doesn’t match, the non-matched control planes in the namespace remove the corresponding
ClusterExternalSecret
- You can use the
ClusterExternalSecret
within a control plane context:ClusterSecretStore
can access the secret as documented in the ESO documentation.
Usage
Create two managed control planes in acmeorg
namespace.
cat <<EOF | kubectl apply -n acmeorg -f -
apiVersion: spaces.upbound.io/v1beta1
kind: ControlPlane
metadata:
labels:
# example label, to be matched in SharedSecretStore/SharedExternalSecret examples
org: foo
name: ctp
spec:
writeConnectionSecretToRef:
name: kubeconfig-ctp2
cat <<EOF | kubectl apply -n acmeorg -f -
apiVersion: spaces.upbound.io/v1beta1
kind: ControlPlane
metadata:
labels:
# example label, to be matched in SharedSecretStore/SharedExternalSecret examples
org: foo
name: ctp2
spec:
writeConnectionSecretToRef:
name: kubeconfig-ctp
Deploy SharedSecretStore in the same namespace. This example uses fake provider.
cat <<EOF | kubectl apply -n acmeorg -f -
apiVersion: spaces.upbound.io/v1alpha1
kind: SharedSecretStore
metadata:
name: fake
spec:
controlPlaneSelector:
labelSelectors:
- matchLabels:
org: foo
namespaceSelector:
names:
- default
provider:
fake:
data:
- key: "/foo/bar"
value: "HELLO1"
version: "v1"
- key: "/foo/bar"
value: "HELLO2"
version: "v2"
- key: "/foo/baz"
value: '{"john": "doe"}'
version: "v1"
Deploy SharedExternalSecret in the same namespace.
cat <<EOF | kubectl apply -n acmeorg -f -
apiVersion: spaces.upbound.io/v1alpha1
kind: SharedExternalSecret
metadata:
name: fake-secret
spec:
controlPlaneSelector:
labelSelectors:
- matchLabels:
org: foo
namespaceSelector:
names:
- default
externalSecretSpec:
refreshInterval: 1h
secretStoreRef:
# refer the projected store
name: fake
kind: ClusterSecretStore
data:
- secretKey: "foo"
remoteRef:
key: "/foo/bar"
version: "v1"
Check if control planes are available:
$ kubectl get controlplanes
NAME CROSSPLANE VERSION SUPPORTED READY MESSAGE AGE
ctp 1.13.2-up.3 True True 21m
ctp2 1.13.2-up.3 True True 22m
Connect to control plane ctp
:
up ctp connect ctp
Check if Kubernetes secret fake-secret
is available in default namespace:
$ kubectl get secret fake-secret
NAME TYPE DATA AGE
fake-secret Opaque 1 20s
Perform the same check on control plane ctp2
.
Verify the projected ClusterSecretStore and ClusterExternalSecret.
$ kubectl get clustersecretstore
NAME AGE STATUS CAPABILITIES READY
fake 5m18s Valid ReadOnly True
$ kubectl get clusterexternalsecret
NAME STORE REFRESH INTERVAL READY
fake-secret fake True
External secrets in a control plane
You can use ESO API types in a Spaces-managed control plane as you would in a standalone Crossplane instance or Kubernetes cluster. Below is an example of the AWS Secrets Manager configuration.
Usage
First, create a secret in the managed control plane which contains the auth credentials to access the external secret store.
kubectl create secret generic awssm-secret \
--from-file=./access-key \
--from-file=./secret-access-key
Create a SecretStore resource in your managed control plane, referencing the auth secret created in the previous step.
cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secretsmanager
namespace: default
spec:
provider:
aws:
service: SecretsManager
region: us-east-1
auth:
secretRef:
accessKeyIDSecretRef:
name: awssm-secret
key: access-key
secretAccessKeySecretRef:
name: awssm-secret
key: secret-access-key
EOF
Once you have a secret store configured, you can pull external secrets into your control plane by creating new ExternalSecrets
. As an example, you can store ProviderConfig credentials in a central secret management service and pull them into your managed control plane.
cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: providerconfig-aws-secret
namespace: default
spec:
refreshInterval: 15s
secretStoreRef:
name: aws-secretsmanager
kind: SecretStore
target:
creationPolicy: Owner
data:
- secretKey: aws_access_key_id
remoteRef:
key: providerconfigs
property: aws_access_key_id
- secretKey: aws_secret_access_key
remoteRef:
key: providerconfigs
property: aws_secret_access_key
EOF
For a full guide on using ESO API types and how to connect it to various external secret stores, read the ESO documentation.