diff --git a/docs/docs/40-operator-guide/40-security/60-promotion-pod-identity.md b/docs/docs/40-operator-guide/40-security/60-promotion-pod-identity.md new file mode 100644 index 0000000000..8bb75e89a1 --- /dev/null +++ b/docs/docs/40-operator-guide/40-security/60-promotion-pod-identity.md @@ -0,0 +1,142 @@ +--- +description: Learn how to set up workload identity for promotion pods +sidebar_label: Promotion Pod Identity +--- + + + + +:::info + +This document describes how to set workload identity for promotions run by +Promotion Controller in Kargo versions v1.11 and above. + +Promotion Controller is only available in Kargo on the [Akuity Platform](https://akuity.io/akuity-platform) +and requires use of self-hosted agent. + +::: + +# Promotion Pod identity + +## Background + +Most workload identity tools are using pod serviceaccounts to provision access for tools running in the pod. + +When using Promotion Controller, each promotion is run as a pod with steps running as containers in this pod. +This makes it possible for steps to access workload identity for the promotion pod and have required permissions. + +Promotion pods are assigned `kargo-promotion-orchestrator` serviceaccount by default. +While it is technically possible to assign federated identity (e.g. IRSA) to `kargo-promotion-orchestrator` +serviceaccount, Akuity Platform may override these setting for example when upgrading or configuring Kargo. + +Also using the same serviceaccount to access multiple different roles for different promotions/stages/steps is not the +best approach from security or configuration point of view. + +## Promotion decorator annotation for Stages + +Since version `1.11`, Kargo supports decorator annotations for `Stage` resources, which will change how +Promotion Controller runs promotion pods. + +Supported decorator annotations are: + +- `ee.kargo.akuity.io/promotion-sa` - **overrides** the serviceaccount used to run the promotion pod +- `ee.kargo.akuity.io/promotion-labels` - **extends** the labels used in the promotion pod +- `ee.kargo.akuity.io/promotion-annotations` - **extends** the annotations used in the promotion pod + +Each annotation can be set separately. Empty values have no effect. + +:::warning + +If not empty, `promotion-sa` must be a valid serviceaccount in the agent namespace. +`promotion-labels` must be a JSON string with valid k8s labels. +`promotion-annotations` must be a JSON string with valid k8s annotations. + +Promotion will error if values in these annotations are invalid. + +::: + +## Example using decorators for a stage + +For example if we have a custom step accessing S3: + +``` +apiVersion: ee.kargo.akuity.io/v1alpha1 +kind: CustomPromotionStep +metadata: + name: aws-s3-ls +spec: + image: amazon/aws-cli + command: [ + "sh", + "-c", + "mkdir -p $HOME; aws s3 ls s3://{{ config.bucket }}"] + env: + - name: HOME ## HOME is required to run as non-root + value: /tmp/home +``` + +And we have a serviceaccount configured to access a role with S3 access: +``` +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/access-s3 + labels: + app.kubernetes.io/managed-by: eksctl + name: s3-access + namespace: akuity +``` + +We can configure a stage to use this serviceaccount and access the role: + +``` +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: my-stage + namespace: kargo-demo + annotations: + ee.kargo.akuity.io/promotion-sa: s3-access +spec: + promotionTemplate: + spec: + steps: + - as: list s3 + config: + bucket: my_bucket_name + uses: aws-s3-ls + requestedFreight: + ... +``` + +## Known limitations + +Because entire promotion is running in a single pod, all steps in the pod will have the same identity and will get the same +access provisioned into them. + +This means steps within the same promotion cannot use different serviceaccounts. If they need different permissions, those +need to be attached to the same serviceaccount. + +Some builtin steps require serviceaccount to have specific k8s role bindings. +Namely when running `argocd-update` with incluster ArgoCD (on the same cluster as promotion controller agent), +the serviceaccount used in promotion must be bound to `kargo-promotion-token-manager` role. + +You can create a binding for serviceaccount like this: +``` +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kargo-promotion-token-manager-orchestrator + namespace: akuity ## Promotion namespace +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: "kargo-promotion-token-manager" +subjects: + - kind: ServiceAccount + namespace: akuity ## Promotion namespace + name: +``` + +**NOTE** this only applies to a setup where ArgoCD runs in the same cluster as promotion pods. \ No newline at end of file diff --git a/docs/docs/50-user-guide/60-reference-docs/70-annotations.md b/docs/docs/50-user-guide/60-reference-docs/70-annotations.md index 3e2a6f4642..8c3e4dcd27 100644 --- a/docs/docs/50-user-guide/60-reference-docs/70-annotations.md +++ b/docs/docs/50-user-guide/60-reference-docs/70-annotations.md @@ -27,6 +27,9 @@ programmatically with Kargo. | `rbac.kargo.akuity.io/managed` | `ServiceAccount`, `Role`, `RoleBinding` | `"true"` | Permits the UI or CLI (via the API server) to programmatically manage trios of `ServiceAccount`, `Role`, and `RoleBinding` resources via Kargo's own ["roles" abstraction](../50-security/20-access-controls/index.md#managing-mappings-and-permissions). Omit this annotation if you wish to exclusively manage these resources [declaratively](../50-security/20-access-controls/index.md#managing-kargo-roles-declaratively). | | `kargo.akuity.io/replicate-to` | `Secret`, `ConfigMap` (in the shared resources namespace) | `"*"` | Enables automatic replication of the resource to all Project namespaces. For more details, see the [Replicating Shared Resources](../../40-operator-guide/40-security/40-managing-secrets.md#replicating-shared-resources-to-project-namespaces) section of the Operator Guide. | | `kargo.akuity.io/replicated-at` | `Secret`, `ConfigMap` (replicated copies) | UTC timestamp | Records when the resource was last replicated from the source. Managed by the system. | +| `ee.kargo.akuity.io/promotion-sa` | `Stage` | String `ServiceAccount` name in promotion namespace | Overrides default serviceaccount for promotion pods ran by Promotion Controller (Kargo EE only) | +| `ee.kargo.akuity.io/promotion-labels` | `Stage` | JSON string encoding valid K8s labels | Extends labels for promotion pods ran by Promotion Controller (Kargo EE only) | +| `ee.kargo.akuity.io/promotion-annotations` | `Stage` | JSON string encoding valid K8s annotations | Extends annotations for promotion pods ran by Promotion Controller (Kargo EE only) | ## Labels