Connection Details
Using connection details in Crossplane requires the following components:
- Defining the
writeConnectionSecretToRef.name
in a Claim. - Defining the
writeConnectionSecretsToNamespace
value in the Composition. - Define the
writeConnectionSecretToRef
name and namespace for each resource in the Composition. - Define the list of secret keys produced by each composed resource with in the Composition.
- Optionally, define the
connectionSecretKeys
in a CompositeResourceDefinition.
This guide discusses creating Kubernetes secrets.
Crossplane also supports using external secret stores like HashiCorp Vault.
Read the external secrets store guide for more information on using Crossplane with an external secret store.
Background
When a Provider 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, the Composition, Composite Resource Definition and optionally, the Claim define what details are visible and where they’re stored.
All the following examples use the same set of Compositions, CompositeResourceDefinitions and Claims.
All examples rely on provider-aws-iam to create resources.
1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3metadata:
4 name: xsecrettest.example.org
5spec:
6 writeConnectionSecretsToNamespace: other-namespace
7 compositeTypeRef:
8 apiVersion: example.org/v1alpha1
9 kind: XSecretTest
10 mode: Pipeline
11 pipeline:
12 - step: patch-and-transform
13 functionRef:
14 name: function-patch-and-transform
15 input:
16 apiVersion: pt.fn.crossplane.io/v1beta1
17 kind: Resources
18 resources:
19 - name: key
20 base:
21 apiVersion: iam.aws.upbound.io/v1beta1
22 kind: AccessKey
23 spec:
24 forProvider:
25 userSelector:
26 matchControllerRef: true
27 writeConnectionSecretToRef:
28 namespace: docs
29 name: key1
30 connectionDetails:
31 - name: user
32 type: FromConnectionSecretKey
33 fromConnectionSecretKey: username
34 - name: password
35 type: FromConnectionSecretKey
36 fromConnectionSecretKey: password
37 - name: key
38 type: FromConnectionSecretKey
39 fromConnectionSecretKey: attribute.secret
40 - name: smtp
41 type: FromConnectionSecretKey
42 fromConnectionSecretKey: attribute.ses_smtp_password_v4
43 patches:
44 - fromFieldPath: "metadata.uid"
45 toFieldPath: "spec.writeConnectionSecretToRef.name"
46 transforms:
47 - type: string
48 string:
49 type: Format
50 fmt: "%s-secret1"
51 - name: user
52 base:
53 apiVersion: iam.aws.upbound.io/v1beta1
54 kind: User
55 spec:
56 forProvider: {}
57 - name: user2
58 base:
59 apiVersion: iam.aws.upbound.io/v1beta1
60 kind: User
61 metadata:
62 labels:
63 docs.crossplane.io: user
64 spec:
65 forProvider: {}
66 - name: key2
67 base:
68 apiVersion: iam.aws.upbound.io/v1beta1
69 kind: AccessKey
70 spec:
71 forProvider:
72 userSelector:
73 matchLabels:
74 docs.crossplane.io: user
75 writeConnectionSecretToRef:
76 namespace: docs
77 name: key2
78 connectionDetails:
79 - name: key2-user
80 type: FromConnectionSecretKey
81 fromConnectionSecretKey: username
82 - name: key2-password
83 type: FromConnectionSecretKey
84 fromConnectionSecretKey: password
85 - name: key2-secret
86 type: FromConnectionSecretKey
87 fromConnectionSecretKey: attribute.secret
88 - name: key2-smtp
89 type: FromConnectionSecretKey
90 fromConnectionSecretKey: attribute.ses_smtp_password_v4
91 patches:
92 - fromFieldPath: "metadata.uid"
93 toFieldPath: "spec.writeConnectionSecretToRef.name"
94 transforms:
95 - type: string
96 string:
97 type: Format
98 fmt: "%s-secret2"
1apiVersion: apiextensions.crossplane.io/v1
2kind: CompositeResourceDefinition
3metadata:
4 name: xsecrettests.example.org
5spec:
6 group: example.org
7 connectionSecretKeys:
8 - username
9 - password
10 - attribute.secret
11 - attribute.ses_smtp_password_v4
12 - key2-user
13 - key2-pass
14 - key2-secret
15 - key2-smtp
16 names:
17 kind: XSecretTest
18 plural: xsecrettests
19 claimNames:
20 kind: SecretTest
21 plural: secrettests
22 versions:
23 - name: v1alpha1
24 served: true
25 referenceable: true
26 schema:
27 openAPIV3Schema:
28 type: object
29 properties:
30 spec:
31 type: object
Connection secrets in a managed resource
When a managed resource creates connection secrets, Crossplane can write the secrets to a Kubernetes secret or an external secret store.
Creating an individual managed resource shows the connection secrets the resource creates.
For example, create an
resource and save the
connection secrets in a Kubernetes secret named
in the
namespace.
1apiVersion: iam.aws.upbound.io/v1beta1
2kind: AccessKey
3metadata:
4 name: test-accesskey
5spec:
6 forProvider:
7 userSelector:
8 matchLabels:
9 docs.crossplane.io: user
10 writeConnectionSecretToRef:
11 namespace: default
12 name: my-accesskey-secret
View the Kubernetes secret to see the connection details from the managed
resource.
This includes an
,
,
and
1kubectl describe secret my-accesskey-secret
2Name: my-accesskey-secret
3Namespace: default
4Labels: <none>
5Annotations: <none>
6
7Type: connection.crossplane.io/v1alpha1
8
9Data
10====
11attribute.secret: 40 bytes
12attribute.ses_smtp_password_v4: 44 bytes
13password: 40 bytes
14username: 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
objects.
Each
writes a
connection secrets to the
inside the
defined by
the resource
.
Crossplane also creates a secret object for the entire Composition
saved in the namespace defined by
with a Crossplane generated name.
1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3spec:
4 writeConnectionSecretsToNamespace: other-namespace
5 mode: Pipeline
6 pipeline:
7 - step: patch-and-transform
8 functionRef:
9 name: function-patch-and-transform
10 input:
11 apiVersion: pt.fn.crossplane.io/v1beta1
12 kind: Resources
13 resources:
14 - name: key1
15 base:
16 apiVersion: iam.aws.upbound.io/v1beta1
17 kind: AccessKey
18 spec:
19 forProvider:
20 # Removed for brevity
21 writeConnectionSecretToRef:
22 namespace: docs
23 name: key1-secret
24 - name: key2
25 base:
26 apiVersion: iam.aws.upbound.io/v1beta1
27 kind: AccessKey
28 spec:
29 forProvider:
30 # Removed for brevity
31 writeConnectionSecretToRef:
32 namespace: docs
33 name: key2-secret
34 # Removed for brevity
After applying a Claim, view the Kubernetes secrets to see three secret objects created.
The secret
is from the resource
,
is from the resource
.
Crossplane creates another secret in the namespace
with the
secrets from resource in the Composition.
1kubectl get secrets -A
2NAMESPACE NAME TYPE DATA AGE
3docs key1-secret connection.crossplane.io/v1alpha1 4 4s
4docs key2-secret connection.crossplane.io/v1alpha1 4 4s
5other-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.
1kubectl describe secret 70975471-c44f-4f6d-bde6-6bbdc9de1eb8 -n other-namespace
2Name: 70975471-c44f-4f6d-bde6-6bbdc9de1eb8
3Namespace: other-namespace
4
5Type: connection.crossplane.io/v1alpha1
6
7Data
8====
The Composition must list the connection secrets to store for each resource.
Use the
object under
each resource and define the secret keys the resource creates.
connectionDetails
of a Composition.You must delete and recreate the Composition to change the
connectionDetails
. 1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3spec:
4 writeConnectionSecretsToNamespace: other-namespace
5 mode: Pipeline
6 pipeline:
7 - step: patch-and-transform
8 functionRef:
9 name: function-patch-and-transform
10 input:
11 apiVersion: pt.fn.crossplane.io/v1beta1
12 kind: Resources
13 resources:
14 - name: key
15 base:
16 apiVersion: iam.aws.upbound.io/v1beta1
17 kind: AccessKey
18 spec:
19 forProvider:
20 # Removed for brevity
21 writeConnectionSecretToRef:
22 namespace: docs
23 name: key1
24 connectionDetails:
25 - name: user
26 type: FromConnectionSecretKey
27 fromConnectionSecretKey: username
28 - name: password
29 type: FromConnectionSecretKey
30 fromConnectionSecretKey: password
31 - name: key
32 type: FromConnectionSecretKey
33 fromConnectionSecretKey: attribute.secret
34 - name: smtp
35 type: FromConnectionSecretKey
36 fromConnectionSecretKey: attribute.ses_smtp_password_v4
37 # Removed for brevity
After applying a Claim the composite resource secret object contains the list of
keys listed in the
.
1kubectl describe secret -n other-namespace
2Name: b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a
3Namespace: other-namespace
4
5Type: connection.crossplane.io/v1alpha1
6
7Data
8====
9username: 20 bytes
10attribute.secret: 40 bytes
11attribute.ses_smtp_password_v4: 44 bytes
12password: 40 bytes
connectionDetails
it isn’t stored in the secret object.Managing conflicting secret keys
If resources produce conflicting keys, create a unique name with a connection
details
.
1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3spec:
4 writeConnectionSecretsToNamespace: other-namespace
5 mode: Pipeline
6 pipeline:
7 - step: patch-and-transform
8 functionRef:
9 name: function-patch-and-transform
10 input:
11 apiVersion: pt.fn.crossplane.io/v1beta1
12 kind: Resources
13 resources:
14 - name: key
15 base:
16 kind: AccessKey
17 spec:
18 # Removed for brevity
19 writeConnectionSecretToRef:
20 namespace: docs
21 name: key1
22 connectionDetails:
23 - name: user
24 type: FromConnectionSecretKey
25 fromConnectionSecretKey: username
26 - name: key2
27 base:
28 kind: AccessKey
29 spec:
30 # Removed for brevity
31 writeConnectionSecretToRef:
32 namespace: docs
33 name: key2
34 connectionDetails:
35 - name: key2-user
36 type: FromConnectionSecretKey
37 fromConnectionSecretKey: username
The secret object contains both keys,
and
1kubectl describe secret -n other-namespace
2Name: b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a
3Namespace: other-namespace
4
5Type: connection.crossplane.io/v1alpha1
6
7Data
8====
9username: 20 bytes
10key2-user: 20 bytes
11# 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
object.
Inside the
list
the secret key names to create. Crossplane only adds the keys listed to the
combined secret.
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
,
and custom named
keys.
1kind: CompositeResourceDefinition
2spec:
3 # Removed for brevity.
4 connectionSecretKeys:
5 - username
6 - password
7 - key2-user
The secret from an individual resource contains all the resources detailed in
the Composition’s connectionDetails
.
1kubectl describe secret key1 -n docs
2Name: key1
3Namespace: docs
4
5Data
6====
7password: 40 bytes
8username: 20 bytes
9attribute.secret: 40 bytes
10attribute.ses_smtp_password_v4: 44 bytes
The Claim’s secret only contains the
keys allowed by the XRD
fields.
1kubectl describe secret my-access-key-secret
2Name: my-access-key-secret
3
4Data
5====
6key2-user: 20 bytes
7password: 40 bytes
8username: 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
.
Crossplane saves the combined secret with a Crossplane generated name in the
namespace defined in the Composition’s
.
1apiVersion: apiextensions.crossplane.io/v1
2kind: Composition
3spec:
4 writeConnectionSecretsToNamespace: other-namespace
5 mode: Pipeline
6 pipeline:
7 - step: patch-and-transform
8 functionRef:
9 name: function-patch-and-transform
10 input:
11 apiVersion: pt.fn.crossplane.io/v1beta1
12 kind: Resources
13 resources:
14 - name: key
15 base:
16 kind: AccessKey
17 spec:
18 # Removed for brevity
19 writeConnectionSecretToRef:
20 namespace: docs
21 name: key1
22 connectionDetails:
23 - name: user
24 type: FromConnectionSecretKey
25 fromConnectionSecretKey: username
26 - name: key2
27 base:
28 kind: AccessKey
29 spec:
30 # Removed for brevity
31 writeConnectionSecretToRef:
32 namespace: docs
33 name: key2
34 connectionDetails:
35 - name: key2-user
36 type: FromConnectionSecretKey
37 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
.
1apiVersion: example.org/v1alpha1
2kind: SecretTest
3metadata:
4 name: test-secrets
5 namespace: default
6spec:
7 writeConnectionSecretToRef:
8 name: my-access-key-secret
After applying the Claim Crossplane creates the following secrets:
- The Claim’s secret,
in the Claim’smy-access-key-secret
.namespace - The first resource’s secret object,
.key1 - The second resource’s secret object,
.key2 - The composite resource secret object in the
defined by the Composition’sother-namespace writeConnectionSecretsToNamespace
.
1 kubectl get secret -A
2NAMESPACE NAME TYPE DATA AGE
3default my-access-key-secret connection.crossplane.io/v1alpha1 8 29m
4docs key1 connection.crossplane.io/v1alpha1 4 31m
5docs key2 connection.crossplane.io/v1alpha1 4 31m
6other-namespace b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a connection.crossplane.io/v1alpha1 8 31m