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 connectionDetails in the Composition.
  • Optionally, define the connectionSecretKeys in a CompositeResourceDefinition.
Note

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.

Note

All the following examples use the same set of Compositions, CompositeResourceDefinitions and Claims.

All examples rely on Upbound 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  resources:
11    - name: key
12      base:
13        apiVersion: iam.aws.upbound.io/v1beta1
14        kind: AccessKey
15        spec:
16          forProvider:
17            userSelector:
18              matchControllerRef: true
19          writeConnectionSecretToRef:
20            namespace: docs
21            name: key1
22      connectionDetails:
23        - fromConnectionSecretKey: username
24        - fromConnectionSecretKey: password
25        - fromConnectionSecretKey: attribute.secret
26        - fromConnectionSecretKey: attribute.ses_smtp_password_v4
27      patches:
28        - fromFieldPath: "metadata.uid"
29          toFieldPath: "spec.writeConnectionSecretToRef.name"
30          transforms:
31            - type: string
32              string:
33                fmt: "%s-secret1"
34    - name: user
35      base:
36        apiVersion: iam.aws.upbound.io/v1beta1
37        kind: User
38        spec:
39          forProvider: {}
40    - name: user2
41      base:
42        apiVersion: iam.aws.upbound.io/v1beta1
43        kind: User
44        metadata:
45          labels:
46            docs.crossplane.io: user
47        spec:
48          forProvider: {}
49    - name: key2
50      base:
51        apiVersion: iam.aws.upbound.io/v1beta1
52        kind: AccessKey
53        spec:
54          forProvider:
55            userSelector:
56              matchLabels:
57                docs.crossplane.io: user
58          writeConnectionSecretToRef:
59            namespace: docs
60            name: key2
61      connectionDetails:
62        - name: key2-user
63          fromConnectionSecretKey: username
64        - name: key2-password
65          fromConnectionSecretKey: password
66        - name: key2-secret
67          fromConnectionSecretKey: attribute.secret
68        - name: key2-smtp
69          fromConnectionSecretKey: attribute.ses_smtp_password_v4
70      patches:
71        - fromFieldPath: "metadata.uid"
72          toFieldPath: "spec.writeConnectionSecretToRef.name"
73          transforms:
74            - type: string
75              string:
76                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

1apiVersion: example.org/v1alpha1
2kind: SecretTest
3metadata:
4  name: test-secrets
5  namespace: default
6spec:
7  writeConnectionSecretToRef:
8    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 or an external secret store.

Creating an individual managed resource shows the connection secrets the resource creates.

Note
Read the managed resources documentation for more information on configuring resources and storing connection secrets for individual resources.

For example, create an AccessKey resource and save the connection secrets in a Kubernetes secret named my-accesskey-secret in the default 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 attribute.secret, attribute.ses_smtp_password_v4, password and username

 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 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.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3spec:
 4  writeConnectionSecretsToNamespace: other-namespace
 5  resources:
 6    - name: key1
 7      base:
 8        apiVersion: iam.aws.upbound.io/v1beta1
 9        kind: AccessKey
10        spec:
11          forProvider:
12            # Removed for brevity
13          writeConnectionSecretToRef:
14            namespace: docs
15            name: key1-secret
16    - name: key2
17      base:
18        apiVersion: iam.aws.upbound.io/v1beta1
19        kind: AccessKey
20        spec:
21          forProvider:
22            # Removed for brevity
23          writeConnectionSecretToRef:
24            namespace: docs
25            name: key2-secret
26    # 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.

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 connectionDetails object under each resource and define the secret keys the resource creates.

Warning
You can’t change the 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  resources:
 6    - name: key
 7      base:
 8        apiVersion: iam.aws.upbound.io/v1beta1
 9        kind: AccessKey
10        spec:
11          forProvider:
12            # Removed for brevity
13          writeConnectionSecretToRef:
14            namespace: docs
15            name: key1
16      connectionDetails:
17        - fromConnectionSecretKey: username
18        - fromConnectionSecretKey: password
19        - fromConnectionSecretKey: attribute.secret
20        - fromConnectionSecretKey: attribute.ses_smtp_password_v4
21    # Removed for brevity

After applying a Claim the composite resource secret object contains the list of keys listed in the connectionDetails.

 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
Important
If a key isn’t listed in the 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 name.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3spec:
 4  writeConnectionSecretsToNamespace: other-namespace
 5  resources:
 6    - name: key
 7      base:
 8        kind: AccessKey
 9        spec:
10          # Removed for brevity
11          writeConnectionSecretToRef:
12            namespace: docs
13            name: key1
14      connectionDetails:
15        - fromConnectionSecretKey: username
16    - name: key2
17      base:
18        kind: AccessKey
19        spec:
20          # Removed for brevity
21          writeConnectionSecretToRef:
22            namespace: docs
23            name: key2
24      connectionDetails:
25        - name: key2-user
26          fromConnectionSecretKey: username

The secret object contains both keys, username and key2-user

 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 connectionSecretKeys object.

Inside the connectionSecretKeys list the secret key names to create. Crossplane only adds the keys listed to the combined secret.

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.

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 connectionSecretKeys 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 writeConnectionSecretToRef.

Crossplane saves the combined secret with a Crossplane generated name in the namespace defined in the Composition’s writeConnectionSecretsToNamespace.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3spec:
 4  writeConnectionSecretsToNamespace: other-namespace
 5  resources:
 6    - name: key
 7      base:
 8        kind: AccessKey
 9        spec:
10          # Removed for brevity
11          writeConnectionSecretToRef:
12            namespace: docs
13            name: key1
14      connectionDetails:
15        - fromConnectionSecretKey: username
16    - name: key2
17      base:
18        kind: AccessKey
19        spec:
20          # Removed for brevity
21          writeConnectionSecretToRef:
22            namespace: docs
23            name: key2
24      connectionDetails:
25        - name: key2-user
26          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.

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, 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.
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