diff --git a/content/master/cli/command-reference.md b/content/master/cli/command-reference.md index 95303420..be56a3ee 100644 --- a/content/master/cli/command-reference.md +++ b/content/master/cli/command-reference.md @@ -108,6 +108,7 @@ spec: | `-c` | `--include-context` | Include the context in the rendered output as a resource of kind: Context. | | `-x` | `--include-full-xr` | Include a copy of the input Composite Resource spec and metadata fields in the rendered output. | | | `--timeout=` | Amount of time to wait for a function to finish. (Default 1 minute) | +| | `--function-credentials=PATH` | A YAML file or directory of YAML files specifying credentials to use for Functions to render the XR. | {{< /table >}} @@ -127,6 +128,11 @@ If a function produces Kubernetes events with statuses use the `--include-function-results` to print them along with the managed resource outputs. +### Use a secret in a function + +If a function needs a secret, use the `--function-credentials=PATH` +where `PATH` is the path to a Kubernetes secret manifest. + ### Include the composite resource Composition functions can only change the `status` field of a composite diff --git a/content/master/guides/write-a-composition-function-in-python.md b/content/master/guides/write-a-composition-function-in-python.md index 58aad756..d54276cc 100644 --- a/content/master/guides/write-a-composition-function-in-python.md +++ b/content/master/guides/write-a-composition-function-in-python.md @@ -733,3 +733,72 @@ up continuous integration (CI) using lint, test, and build your function. You can see how the template configures CI by reading `.github/workflows/ci.yaml`. {{}} + +## Using credentials in the function + +To access a secret, the `composition.yaml` step declares it with: + +```yaml +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: create-buckets +spec: + compositeTypeRef: + apiVersion: example.crossplane.io/v1 + kind: XBuckets + mode: Pipeline + pipeline: + - step: create-buckets + credentials: + - name: function-credentials + secretRef: + name: secret-name + namespace: crossplane-system + source: Secret + functionRef: + name: function-xbuckets +``` + +Where `secret-name` is the kubernetes secret name. + +Edit the `RunFunction` method to read the credentials using `req.credentials`: + +{{}} +See [apiextensions.fn.proto.v1.RunFunctionRequest](https://buf.build/crossplane/crossplane/docs/main:apiextensions.fn.proto.v1#apiextensions.fn.proto.v1.RunFunctionRequest) +and [protobuf generated Python code ](https://protobuf.dev/reference/python/python-generated/) +to understand what kind of Python code is generated from the protobuf +and how to access the request content +{{}} + +```python +async def RunFunction(self, req: fnv1.RunFunctionRequest, _: grpc.aio.ServicerContext) -> fnv1.RunFunctionResponse: + log = self.log.bind(tag=req.meta.tag) + log.info("Running function") + + rsp = response.to(req) + + credentials = req.credentials + + username = credentials["secret-name"].credential_data.data["username"].decode("utf-8") + password = credentials["secret-name"].credential_data.data["password"].decode("utf-8") +``` + +To test the function with `crossplane render`, use: + +`crossplane render --function-credentials=secret.yaml xr.yaml composition.yaml functions.yaml` + +Where `secret.yaml` is a Kubernetes secret manifest: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: secret-name + namespace: crossplane-system +data: + username: bb..bb + password: aa..aa +type: Opaque +``` +