21 KiB
title | weight | description |
---|---|---|
Connection Details | 110 | How to create and manage connection details across Crossplane managed resources, composite resources, Compositions and Claims |
Using connection details in Crossplane requires the following components:
- Defining the
writeConnectionSecretToRef.name
in a [Claim]({{<ref "/master/concepts/claims#claim-connection-secrets">}}). - Defining the
writeConnectionSecretsToNamespace
value in the [Composition]({{<ref "/master/concepts/compositions#composite-resource-combined-secret">}}). - Define the
writeConnectionSecretToRef
name and namespace for each resource in the [Composition]({{<ref "/master/concepts/compositions#composed-resource-secrets">}}). - Define the list of secret keys produced by each composed resource with in the [Composition]({{<ref "/master/concepts/compositions">}}).
- Optionally, define the
connectionSecretKeys
in a [CompositeResourceDefinition]({{<ref "/master/concepts/composite-resource-definitions#manage-connection-secrets">}}).
{{<hint "note">}}
This guide discusses creating Kubernetes secrets.
Crossplane also supports using external secret stores like HashiCorp Vault.
Read the [external secrets store guide]({{<ref "../guides/vault-as-secret-store">}}) for more information on using Crossplane with an external secret store. {{}}
Background
When a [Provider]({{<ref "/master/concepts/providers">}}) creates a managed resource, the resource may generate resource-specific details. These details can include usernames, passwords or connection details like an IP address.
Crossplane refers to this information as the connection details or connection secrets.
The Provider defines what information to present as a connection detail from a managed resource.
When a managed resource is part of a [Composition]({{<ref "/master/concepts/compositions">}}), the Composition, [Composite Resource Definition]({{<ref "/master/concepts/composite-resource-definitions">}}) and optionally, the [Claim]({{<ref "/master/concepts/claims">}}) define what details are visible and where they're stored.
{{<hint "note">}} All the following examples use the same set of Compositions, CompositeResourceDefinitions and Claims.
All examples rely on provider-aws-iam to create resources.
{{<expand "Reference Composition" >}}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xsecrettest.example.org
spec:
writeConnectionSecretsToNamespace: other-namespace
compositeTypeRef:
apiVersion: example.org/v1alpha1
kind: XSecretTest
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
userSelector:
matchControllerRef: true
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: password
type: FromConnectionSecretKey
fromConnectionSecretKey: password
- name: key
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.secret
- name: smtp
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.ses_smtp_password_v4
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
type: Format
fmt: "%s-secret1"
- name: user
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: User
spec:
forProvider: {}
- name: user2
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: User
metadata:
labels:
docs.crossplane.io: user
spec:
forProvider: {}
- name: key2
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
userSelector:
matchLabels:
docs.crossplane.io: user
writeConnectionSecretToRef:
namespace: docs
name: key2
connectionDetails:
- name: key2-user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: key2-password
type: FromConnectionSecretKey
fromConnectionSecretKey: password
- name: key2-secret
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.secret
- name: key2-smtp
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.ses_smtp_password_v4
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
type: Format
fmt: "%s-secret2"
{{}}
{{<expand "Reference CompositeResourceDefinition" >}}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xsecrettests.example.org
spec:
group: example.org
connectionSecretKeys:
- username
- password
- attribute.secret
- attribute.ses_smtp_password_v4
- key2-user
- key2-pass
- key2-secret
- key2-smtp
names:
kind: XSecretTest
plural: xsecrettests
claimNames:
kind: SecretTest
plural: secrettests
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
{{</ expand >}}
{{<expand "Reference Claim" >}}
apiVersion: example.org/v1alpha1
kind: SecretTest
metadata:
name: test-secrets
namespace: default
spec:
writeConnectionSecretToRef:
name: my-access-key-secret
{{}} {{}}
Connection secrets in a managed resource
When a managed resource creates connection secrets, Crossplane can write the secrets to a [Kubernetes secret]({{<ref "/master/concepts/managed-resources#publish-secrets-to-kubernetes">}}) or an [external secret store]({{<ref "/master/concepts/managed-resources#publish-secrets-to-an-external-secrets-store">}}).
Creating an individual managed resource shows the connection secrets the resource creates.
{{<hint "note" >}} Read the [managed resources]({{<ref "/master/concepts/managed-resources">}}) documentation for more information on configuring resources and storing connection secrets for individual resources. {{< /hint >}}
For example, create an {{}}AccessKey{{}} resource and save the connection secrets in a Kubernetes secret named {{}}my-accesskey-secret{{}} in the {{}}default{{}} namespace.
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
metadata:
name: test-accesskey
spec:
forProvider:
userSelector:
matchLabels:
docs.crossplane.io: user
writeConnectionSecretToRef:
namespace: default
name: my-accesskey-secret
View the Kubernetes secret to see the connection details from the managed
resource.
This includes an
{{}}attribute.secret{{}},
{{}}attribute.ses_smtp_password_v4{{}},
{{}}password{{}} and
{{}}username{{}}
kubectl describe secret my-accesskey-secret
Name: my-accesskey-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: connection.crossplane.io/v1alpha1
Data
====
attribute.secret: 40 bytes
attribute.ses_smtp_password_v4: 44 bytes
password: 40 bytes
username: 20 bytes
Compositions and CompositeResourceDefinitions require the exact names of the secrets generated by a resource.
Connection secrets in Compositions
Resources in a Composition that create connection details still create a
secret object containing their connection details.
Crossplane also generates
another secret object for each composite resource,
containing the secrets from all the defined resources.
For example, a Composition defines two
{{}}AccessKey{{}}
objects.
Each {{}}AccessKey{{}} writes a
connection secrets to the {{}}name{{}}
inside the {{}}namespace{{}} defined by
the resource
{{}}writeConnectionSecretToRef{{}}.
Crossplane also creates a secret object for the entire Composition saved in the namespace defined by {{}}writeConnectionSecretsToNamespace{{}} with a Crossplane generated name.
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key1
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1-secret
- name: key2
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key2-secret
# Removed for brevity
After applying a Claim, view the Kubernetes secrets to see three secret objects created.
The secret {{}}key1-secret{{}} is from the resource {{}}key1{{}}, {{}}key2-secret{{}} is from the resource {{}}key2{{}}.
Crossplane creates another secret in the namespace {{}}other-namespace{{}} with the secrets from resource in the Composition.
kubectl get secrets -A
NAMESPACE NAME TYPE DATA AGE
docs key1-secret connection.crossplane.io/v1alpha1 4 4s
docs key2-secret connection.crossplane.io/v1alpha1 4 4s
other-namespace 70975471-c44f-4f6d-bde6-6bbdc9de1eb8 connection.crossplane.io/v1alpha1 0 6s
Although Crossplane creates a secret object, by default, Crossplane doesn't add any data to the object.
kubectl describe secret 70975471-c44f-4f6d-bde6-6bbdc9de1eb8 -n other-namespace
Name: 70975471-c44f-4f6d-bde6-6bbdc9de1eb8
Namespace: other-namespace
Type: connection.crossplane.io/v1alpha1
Data
====
The Composition must list the connection secrets to store for each resource.
Use the
{{}}connectionDetails{{}} object under
each resource and define the secret keys the resource creates.
{{<hint "warning">}}
You can't change the
{{}}connectionDetails{{}}
of a Composition.
You must delete and
recreate the Composition to change the
{{}}connectionDetails{{}}.
{{}}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: password
type: FromConnectionSecretKey
fromConnectionSecretKey: password
- name: key
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.secret
- name: smtp
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.ses_smtp_password_v4
# Removed for brevity
After applying a Claim the composite resource secret object contains the list of keys listed in the {{}}connectionDetails{{}}.
kubectl describe secret -n other-namespace
Name: b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a
Namespace: other-namespace
Type: connection.crossplane.io/v1alpha1
Data
====
username: 20 bytes
attribute.secret: 40 bytes
attribute.ses_smtp_password_v4: 44 bytes
password: 40 bytes
{{<hint "important">}} If a key isn't listed in the {{}}connectionDetails{{}} it isn't stored in the secret object. {{< /hint >}}
Managing conflicting secret keys
If resources produce conflicting keys, create a unique name with a connection details {{}}name{{}}.
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: key2
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key2
connectionDetails:
- name: key2-user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
The secret object contains both keys, {{}}username{{}} and {{}}key2-user{{}}
kubectl describe secret -n other-namespace
Name: b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a
Namespace: other-namespace
Type: connection.crossplane.io/v1alpha1
Data
====
username: 20 bytes
key2-user: 20 bytes
# Removed for brevity.
Connection secrets in Composite Resource Definitions
The CompositeResourceDefinition (XRD
), can restrict which secrets keys are
put in the combined secret and provided to a Claim.
By default an XRD writes all secret keys listed in the composed resource
connectionDetails
to the combined secret object.
Limit the keys passed to the combined secret object and Claims with a {{}}connectionSecretKeys{{}} object.
Inside the {{}}connectionSecretKeys{{}} list the secret key names to create. Crossplane only adds the keys listed to the combined secret.
{{<hint "warning">}} You can't change the {{}}connectionSecretKeys{{}} of an XRD. You must delete and recreate the XRD to change the {{}}connectionSecretKeys{{}}. {{}}
For example, an XRD may restrict the secrets to only the {{}}username{{}}, {{}}password{{}} and custom named {{}}key2-user{{}} keys.
kind: CompositeResourceDefinition
spec:
# Removed for brevity.
connectionSecretKeys:
- username
- password
- key2-user
The secret from an individual resource contains all the resources detailed in
the Composition's connectionDetails
.
kubectl describe secret key1 -n docs
Name: key1
Namespace: docs
Data
====
password: 40 bytes
username: 20 bytes
attribute.secret: 40 bytes
attribute.ses_smtp_password_v4: 44 bytes
The Claim's secret only contains the keys allowed by the XRD {{}}connectionSecretKeys{{}} fields.
kubectl describe secret my-access-key-secret
Name: my-access-key-secret
Data
====
key2-user: 20 bytes
password: 40 bytes
username: 20 bytes
Secret objects
Compositions create a secret object for each resource and an extra secret containing all the secrets from all resources.
Crossplane saves the resource secret objects in the location defined by the resource's {{}}writeConnectionSecretToRef{{}}.
Crossplane saves the combined secret with a Crossplane generated name in the namespace defined in the Composition's {{}}writeConnectionSecretsToNamespace{{}}.
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: key2
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key2
connectionDetails:
- name: key2-user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
If a Claim uses a secret, it's stored in the same namespace as the Claim with the name defined in the Claim's {{}}writeConnectionSecretToRef{{}}.
apiVersion: example.org/v1alpha1
kind: SecretTest
metadata:
name: test-secrets
namespace: default
spec:
writeConnectionSecretToRef:
name: my-access-key-secret
After applying the Claim Crossplane creates the following secrets:
- The Claim's secret, {{}}my-access-key-secret{{}} in the Claim's {{}}namespace{{}}.
- The first resource's secret object, {{}}key1{{}}.
- The second resource's secret object, {{}}key2{{}}.
- The composite resource secret object in the
{{}}other-namespace{{}} defined by the
Composition's
writeConnectionSecretsToNamespace
.
kubectl get secret -A
NAMESPACE NAME TYPE DATA AGE
default my-access-key-secret connection.crossplane.io/v1alpha1 8 29m
docs key1 connection.crossplane.io/v1alpha1 4 31m
docs key2 connection.crossplane.io/v1alpha1 4 31m
other-namespace b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a connection.crossplane.io/v1alpha1 8 31m