From 9b6d35ca213c8e1b7c346a3b5ff51d3b5c9306a6 Mon Sep 17 00:00:00 2001 From: Alex Dellapenta Date: Fri, 12 Jan 2024 15:27:01 -0700 Subject: [PATCH] Add Azure Identity CCO/OLM docs --- _attributes/common-attributes.adoc | 1 + _topic_maps/_topic_map.yml | 11 +- .../cco-short-term-creds.adoc | 7 +- ...installing-from-operatorhub-using-cli.adoc | 43 ++++- ...ng-from-operatorhub-using-web-console.adoc | 11 +- modules/osdk-cco-azure-enabling.adoc | 155 ++++++++++++++++++ operators/operator_sdk/token_auth/_attributes | 1 + operators/operator_sdk/token_auth/images | 1 + operators/operator_sdk/token_auth/modules | 1 + .../token_auth}/osdk-cco-aws-sts.adoc | 24 ++- .../token_auth/osdk-cco-azure.adoc | 51 ++++++ .../{ => token_auth}/osdk-token-auth.adoc | 17 +- operators/operator_sdk/token_auth/snippets | 1 + 13 files changed, 291 insertions(+), 33 deletions(-) create mode 100644 modules/osdk-cco-azure-enabling.adoc create mode 120000 operators/operator_sdk/token_auth/_attributes create mode 120000 operators/operator_sdk/token_auth/images create mode 120000 operators/operator_sdk/token_auth/modules rename {modules => operators/operator_sdk/token_auth}/osdk-cco-aws-sts.adoc (73%) create mode 100644 operators/operator_sdk/token_auth/osdk-cco-azure.adoc rename operators/operator_sdk/{ => token_auth}/osdk-token-auth.adoc (52%) create mode 120000 operators/operator_sdk/token_auth/snippets diff --git a/_attributes/common-attributes.adoc b/_attributes/common-attributes.adoc index 48addc1659..60d5589268 100644 --- a/_attributes/common-attributes.adoc +++ b/_attributes/common-attributes.adoc @@ -240,6 +240,7 @@ endif::[] //Azure :azure-full: Microsoft Azure :azure-short: Azure +:azure-id: Azure AD Workload Identity //vSphere :vmw-full: VMware vSphere :vmw-short: vSphere diff --git a/_topic_maps/_topic_map.yml b/_topic_maps/_topic_map.yml index 8d107cc84b..ff37615f4c 100644 --- a/_topic_maps/_topic_map.yml +++ b/_topic_maps/_topic_map.yml @@ -1884,8 +1884,15 @@ Topics: File: osdk-working-bundle-images - Name: Complying with pod security admission File: osdk-complying-with-psa - - Name: Token authentication for Operators on cloud providers - File: osdk-token-auth + - Name: Token authentication + Dir: token_auth + Topics: + - Name: Token authentication for Operators on cloud providers + File: osdk-token-auth + - Name: CCO-based workflow for OLM-managed Operators with AWS STS + File: osdk-cco-aws-sts + - Name: CCO-based workflow for OLM-managed Operators with Azure AD Workload Identity + File: osdk-cco-azure - Name: Validating Operators using the scorecard File: osdk-scorecard - Name: Validating Operator bundles diff --git a/authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc b/authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc index 0b9f184277..701dab1f6e 100644 --- a/authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc +++ b/authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc @@ -55,7 +55,7 @@ include::modules/cco-short-term-creds-aws-olm.adoc[leveloffset=+2] [role="_additional-resources"] .Additional resources -* xref:../../operators/operator_sdk/osdk-token-auth.adoc#osdk-cco-aws-sts_osdk-token-auth[CCO-based workflow for OLM-managed Operators with AWS STS] +* xref:../../operators/operator_sdk/token_auth/osdk-cco-aws-sts.adoc#osdk-cco-aws-sts[CCO-based workflow for OLM-managed Operators with AWS STS] [id="cco-short-term-creds-gcp_{context}"] == GCP Workload Identity @@ -96,12 +96,9 @@ include::modules/cco-short-term-creds-component-permissions-azure.adoc[leveloffs //OLM-managed Operator support for authentication with Azure AD Workload Identity include::modules/cco-short-term-creds-azure-olm.adoc[leveloffset=+2] -//// -// Azure will need a link off to OLM docs like AWS when ready. [role="_additional-resources"] .Additional resources -* xref:../../operators/operator_sdk/osdk-token-auth.adoc#osdk-cco-aws-sts_osdk-token-auth[CCO-based workflow for OLM-managed Operators with AWS STS] -//// +* xref:../../operators/operator_sdk/token_auth/osdk-cco-azure.adoc#osdk-cco-azure[CCO-based workflow for OLM-managed Operators with {azure-id}] [role="_additional-resources"] [id="additional-resources_{context}"] diff --git a/modules/olm-installing-from-operatorhub-using-cli.adoc b/modules/olm-installing-from-operatorhub-using-cli.adoc index 0b83dce140..9c620c49f9 100644 --- a/modules/olm-installing-from-operatorhub-using-cli.adoc +++ b/modules/olm-installing-from-operatorhub-using-cli.adoc @@ -158,7 +158,9 @@ spec: <11> The `resources` parameter defines resource constraints for all the containers in the pod created by OLM. <12> The `nodeSelector` parameter defines a `NodeSelector` for the pod created by OLM. -. If the cluster is in STS mode, include the following fields in the `Subscription` object: +. For clusters on cloud providers with token authentication enabled: + +.. Ensure the `Subscription` object is set to manual update approvals: + [source,yaml] ---- @@ -166,13 +168,46 @@ kind: Subscription # ... spec: installPlanApproval: Manual <1> +---- +<1> Subscriptions with automatic update approvals are not recommended because there might be permission changes to make prior to updating. Subscriptions with manual update approvals ensure that administrators have the opportunity to verify the permissions of the later version and take any necessary steps prior to update. + +.. Include the relevant cloud provider-specific fields in the `Subscription` object's `config` section: ++ +-- +* If the cluster is in AWS STS mode, include the following fields: ++ +[source,yaml] +---- +kind: Subscription +# ... +spec: config: env: - name: ROLEARN - value: "" <2> + value: "" <1> ---- -<1> Subscriptions with automatic update approvals are not recommended because there might be permission changes to make prior to updating. Subscriptions with manual update approvals ensure that administrators have the opportunity to verify the permissions of the later version and take any necessary steps prior to update. -<2> Include the role ARN details. +<1> Include the role ARN details. + +* If the cluster is in {azure-id} mode, include the following fields: ++ +[source,yaml] +---- +kind: Subscription +# ... +spec: + config: + env: + - name: CLIENTID + value: "" <1> + - name: TENANTID + value: "" <2> + - name: SUBSCRIPTIONID + value: "" <3> +---- +<1> Include the client ID. +<2> Include the tenant ID. +<3> Include the subscription ID. +-- . Create the `Subscription` object: + diff --git a/modules/olm-installing-from-operatorhub-using-web-console.adoc b/modules/olm-installing-from-operatorhub-using-web-console.adoc index 4da2f97d7c..eb60fa20e5 100644 --- a/modules/olm-installing-from-operatorhub-using-web-console.adoc +++ b/modules/olm-installing-from-operatorhub-using-web-console.adoc @@ -77,18 +77,25 @@ endif::[] ifdef::olm-user[] .. Choose a specific, single namespace in which to install the Operator. The Operator will only watch and be made available for use in this single namespace. endif::[] -.. If the cluster is in AWS STS mode, enter the Amazon Resource Name (ARN) of the AWS IAM role of your service account in the *role ARN* field. + +.. For clusters on cloud providers with token authentication enabled: ++ +-- +* If the cluster is in AWS STS mode, enter the Amazon Resource Name (ARN) of the AWS IAM role of your service account in the *role ARN* field. + image::oadp-install-operator-role-arn.png[Entering the ARN] To create the role's ARN, follow the procedure described in link:https://access.redhat.com/documentation/en-us/red_hat_openshift_service_on_aws/4/html/tutorials/cloud-experts-deploy-api-data-protection#prepare-aws-account_cloud-experts-deploy-api-data-protection[Preparing AWS account]. +* If the cluster is in {azure-id} mode, add the client ID, tenant ID, and subscription ID in the appropriate field. +-- + .. If more than one update channel is available, select an *Update channel*. .. Select *Automatic* or *Manual* approval strategy, as described earlier. + [IMPORTANT] ==== -If the web console shows that the cluster is in "STS mode", you must set *Update approval* to *Manual*. +If the web console shows that the cluster is in AWS STS or {azure-id} mode, you must set *Update approval* to *Manual*. Subscriptions with automatic update approvals are not recommended because there might be permission changes to make prior to updating. Subscriptions with manual update approvals ensure that administrators have the opportunity to verify the permissions of the later version and take any necessary steps prior to update. ==== diff --git a/modules/osdk-cco-azure-enabling.adoc b/modules/osdk-cco-azure-enabling.adoc new file mode 100644 index 0000000000..2ba908c114 --- /dev/null +++ b/modules/osdk-cco-azure-enabling.adoc @@ -0,0 +1,155 @@ +// Module included in the following assemblies: +// +// * operators/operator_sdk/token_auth/osdk-cco-azure.adoc + +:_mod-docs-content-type: PROCEDURE +[id="osdk-cco-azure-enabling_{context}"] += Enabling Operators to support CCO-based workflows with {azure-id} + +As an Operator author designing your project to run on Operator Lifecycle Manager (OLM), you can enable your Operator to authenticate against {azure-id}-enabled {product-title} clusters by customizing your project to support the Cloud Credential Operator (CCO). + +With this method, the Operator is responsible for creating the `CredentialsRequest` object, which means the Operator requires RBAC permission to create these objects. Then, the Operator must be able to read the resulting `Secret` object. + +[NOTE] +==== +By default, pods related to the Operator deployment mount a `serviceAccountToken` volume so that the service account token can be referenced in the resulting `Secret` object. +==== + +.Prerequisities + +* {product-title} 4.14 or later +* Cluster in {azure-id} mode +* OLM-based Operator project + +.Procedure + +. Update your Operator project's `ClusterServiceVersion` (CSV) object: + +.. Ensure your Operator has RBAC permission to create `CredentialsRequests` objects: ++ +.Example `clusterPermissions` list +[%collapsible] +==== +[source,yaml] +---- +# ... +install: + spec: + clusterPermissions: + - rules: + - apiGroups: + - "cloudcredential.openshift.io" + resources: + - credentialsrequests + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +---- +==== + +.. Add the following annotation to claim support for this method of CCO-based workflow with {azure-id}: ++ +[source,yaml] +---- +# ... +metadata: + annotations: + features.operators.openshift.io/token-auth-azure: "true" +---- + +. Update your Operator project code: + +.. Get the client ID, tenant ID, and subscription ID from the environment variables set on the pod by the `Subscription` object. For example: ++ +[source,go] +---- +// Get ENV var +clientID := os.Getenv("CLIENTID") +tenantID := os.Getenv("TENANTID") +subscriptionID := os.Getenv("SUBSCRIPTIONID") +azureFederatedTokenFile := "/var/run/secrets/openshift/serviceaccount/token" +---- + +.. Ensure you have a `CredentialsRequest` object ready to be patched and applied. ++ +[NOTE] +==== +Adding a `CredentialsRequest` object to the Operator bundle is not currently supported. +==== + +.. Add the Azure credentials information and web identity token path to the credentials request and apply it during Operator initialization: ++ +.Example applying `CredentialsRequest` object during Operator initialization +[%collapsible] +==== +[source,go] +---- +// apply credentialsRequest on install +credReqTemplate.Spec.AzureProviderSpec.AzureClientID = clientID +credReqTemplate.Spec.AzureProviderSpec.AzureTenantID = tenantID +credReqTemplate.Spec.AzureProviderSpec.AzureRegion = "centralus" +credReqTemplate.Spec.AzureProviderSpec.AzureSubscriptionID = subscriptionID +credReqTemplate.CloudTokenPath = azureFederatedTokenFile + +c := mgr.GetClient() +if err := c.Create(context.TODO(), credReq); err != nil { + if !errors.IsAlreadyExists(err) { + setupLog.Error(err, "unable to create CredRequest") + os.Exit(1) + } +} +---- +==== + +.. Ensure your Operator can wait for a `Secret` object to show up from the CCO, as shown in the following example, which is called along with the other items you are reconciling in your Operator: ++ +.Example wait for `Secret` object +[%collapsible] +==== +[source,go] +---- +// WaitForSecret is a function that takes a Kubernetes client, a namespace, and a v1 "k8s.io/api/core/v1" name as arguments +// It waits until the secret object with the given name exists in the given namespace +// It returns the secret object or an error if the timeout is exceeded +func WaitForSecret(client kubernetes.Interface, namespace, name string) (*v1.Secret, error) { + // set a timeout of 10 minutes + timeout := time.After(10 * time.Minute) <1> + + // set a polling interval of 10 seconds + ticker := time.NewTicker(10 * time.Second) + + // loop until the timeout or the secret is found + for { + select { + case <-timeout: + // timeout is exceeded, return an error + return nil, fmt.Errorf("timed out waiting for secret %s in namespace %s", name, namespace) + // add to this error with a pointer to instructions for following a manual path to a Secret that will work on STS + case <-ticker.C: + // polling interval is reached, try to get the secret + secret, err := client.CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + // secret does not exist yet, continue waiting + continue + } else { + // some other error occurred, return it + return nil, err + } + } else { + // secret is found, return it + return secret, nil + } + } + } +} +---- +<1> The `timeout` value is based on an estimate of how fast the CCO might detect an added `CredentialsRequest` object and generate a `Secret` object. You might consider lowering the time or creating custom feedback for cluster administrators that could be wondering why the Operator is not yet accessing the cloud resources. +==== + +.. Read the secret created by the CCO from the `CredentialsRequest` object to authenticate with Azure and receive the necessary credentials. \ No newline at end of file diff --git a/operators/operator_sdk/token_auth/_attributes b/operators/operator_sdk/token_auth/_attributes new file mode 120000 index 0000000000..20cc1dcb77 --- /dev/null +++ b/operators/operator_sdk/token_auth/_attributes @@ -0,0 +1 @@ +../../_attributes/ \ No newline at end of file diff --git a/operators/operator_sdk/token_auth/images b/operators/operator_sdk/token_auth/images new file mode 120000 index 0000000000..5fa6987088 --- /dev/null +++ b/operators/operator_sdk/token_auth/images @@ -0,0 +1 @@ +../../images \ No newline at end of file diff --git a/operators/operator_sdk/token_auth/modules b/operators/operator_sdk/token_auth/modules new file mode 120000 index 0000000000..8b0e854007 --- /dev/null +++ b/operators/operator_sdk/token_auth/modules @@ -0,0 +1 @@ +../../modules \ No newline at end of file diff --git a/modules/osdk-cco-aws-sts.adoc b/operators/operator_sdk/token_auth/osdk-cco-aws-sts.adoc similarity index 73% rename from modules/osdk-cco-aws-sts.adoc rename to operators/operator_sdk/token_auth/osdk-cco-aws-sts.adoc index c562848d37..4d24f5fef8 100644 --- a/modules/osdk-cco-aws-sts.adoc +++ b/operators/operator_sdk/token_auth/osdk-cco-aws-sts.adoc @@ -1,10 +1,10 @@ -// Module included in the following assemblies: -// -// * operators/operator_sdk/osdk-token-auth.adoc - -:_mod-docs-content-type: CONCEPT -[id="osdk-cco-aws-sts_{context}"] +:_mod-docs-content-type: ASSEMBLY +[id="osdk-cco-aws-sts"] = CCO-based workflow for OLM-managed Operators with AWS STS +include::_attributes/common-attributes.adoc[] +:context: osdk-cco-aws-sts + +toc::[] When an {product-title} cluster running on AWS is in Security Token Service (STS) mode, it means the cluster is utilizing features of AWS and {product-title} to use IAM roles at an application level. STS enables applications to provide a JSON Web Token (JWT) that can assume an IAM role. @@ -32,3 +32,15 @@ If you plan to support {product-title} clusters earlier than version 4.14, consi Your code should check for secrets that never appear and warn users to follow the fallback instructions you have provided. For more information, see the "Alternative method" subsection. ==== + +[role="_additional-resources"] +.Additional resources + +* xref:../../../authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc#cco-short-term-creds-aws-olm_cco-short-term-creds[OLM-managed Operator support for authentication with AWS STS] +* xref:../../../operators/admin/olm-adding-operators-to-cluster.adoc#olm-installing-from-operatorhub-using-web-console_olm-adding-operators-to-a-cluster[Installing from OperatorHub using the web console] +* xref:../../../operators/admin/olm-adding-operators-to-cluster.adoc#olm-installing-operator-from-operatorhub-using-cli_olm-adding-operators-to-a-cluster[Installing from OperatorHub using the CLI] + +include::modules/osdk-cco-aws-sts-enabling.adoc[leveloffset=+1] +include::modules/osdk-cco-aws-sts-role.adoc[leveloffset=+1] +include::modules/osdk-cco-aws-sts-tshooting.adoc[leveloffset=+1] +include::modules/osdk-cco-aws-sts-alt.adoc[leveloffset=+1] \ No newline at end of file diff --git a/operators/operator_sdk/token_auth/osdk-cco-azure.adoc b/operators/operator_sdk/token_auth/osdk-cco-azure.adoc new file mode 100644 index 0000000000..b30a973e2d --- /dev/null +++ b/operators/operator_sdk/token_auth/osdk-cco-azure.adoc @@ -0,0 +1,51 @@ +:_mod-docs-content-type: ASSEMBLY +[id="osdk-cco-azure"] += CCO-based workflow for OLM-managed Operators with {azure-id} +include::_attributes/common-attributes.adoc[] +:context: osdk-cco-azure + +toc::[] + +When an {product-title} cluster running on Azure is in *Workload Identity / Federated Identity* mode, it means the cluster is utilizing features of Azure and {product-title} to apply _user-assigned managed identities_ or _app registrations_ in Microsoft Entra ID at an application level. + +The Cloud Credential Operator (CCO) is a cluster Operator installed by default in {product-title} clusters running on cloud providers. Starting in {product-title} 4.14.8, the CCO supports workflows for OLM-managed Operators with {azure-id}. + +For the purposes of {azure-id}, the CCO provides the following functions: + +* Detects when it is running on an {azure-id}-enabled cluster +* Checks for the presence of fields in the `CredentialsRequest` object that provide the required information for granting Operators access to Azure resources + +The CCO can semi-automate this process through an expanded use of `CredentialsRequest` objects, which can request the creation of `Secrets` that contain the information required for {azure-id} workflows. + +[NOTE] +==== +Subscriptions with automatic update approvals are not recommended because there might be permission changes to make prior to updating. Subscriptions with manual update approvals ensure that administrators have the opportunity to verify the permissions of the later version and take any necessary steps prior to update. +==== + +As an Operator author preparing an Operator for use alongside the updated CCO in {product-title} 4.14 and later, you should instruct users and add code to handle the divergence from earlier CCO versions, in addition to handling {azure-id} token authentication (if your Operator is not already enabled). The recommended method is to provide a `CredentialsRequest` object with correctly filled {azure-id}-related fields and let the CCO create the `Secret` object for you. + +[IMPORTANT] +==== +If you plan to support {product-title} clusters earlier than version 4.14, consider providing users with instructions on how to manually create a secret with the {azure-id}-enabling information by using the CCO utility (`ccoctl`). Earlier CCO versions are unaware of {azure-id} mode on the cluster and cannot create secrets for you. + +Your code should check for secrets that never appear and warn users to follow the fallback instructions you have provided. +==== + +Authentication with {azure-id} requires the following information: + +* `azure_client_id` +* `azure_tenant_id` +* `azure_region` +* `azure_subscription_id` +* `azure_federated_token_file` + +The *Install Operator* page in the web console allows cluster administrators to provide this information at installation time. This information is then propagated to the `Subscription` object as environment variables on the Operator pod. + +[role="_additional-resources"] +.Additional resources + +* xref:../../../authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc#cco-short-term-creds-azure-olm_cco-short-term-creds[OLM-managed Operator support for authentication with {azure-id}] +* xref:../../../operators/admin/olm-adding-operators-to-cluster.adoc#olm-installing-from-operatorhub-using-web-console_olm-adding-operators-to-a-cluster[Installing from OperatorHub using the web console] +* xref:../../../operators/admin/olm-adding-operators-to-cluster.adoc#olm-installing-operator-from-operatorhub-using-cli_olm-adding-operators-to-a-cluster[Installing from OperatorHub using the CLI] + +include::modules/osdk-cco-azure-enabling.adoc[leveloffset=+1] \ No newline at end of file diff --git a/operators/operator_sdk/osdk-token-auth.adoc b/operators/operator_sdk/token_auth/osdk-token-auth.adoc similarity index 52% rename from operators/operator_sdk/osdk-token-auth.adoc rename to operators/operator_sdk/token_auth/osdk-token-auth.adoc index 08e1c1e494..b6024680d3 100644 --- a/operators/operator_sdk/osdk-token-auth.adoc +++ b/operators/operator_sdk/token_auth/osdk-token-auth.adoc @@ -17,17 +17,6 @@ Starting in {product-title} 4.14, the CCO can detect when it is running on clust [role="_additional-resources"] .Additional resources -* xref:../../authentication/managing_cloud_provider_credentials/about-cloud-credential-operator.adoc#about-cloud-credential-operator[About the Cloud Credential Operator] - -include::modules/osdk-cco-aws-sts.adoc[leveloffset=+1] -[role="_additional-resources"] -.Additional resources - -* xref:../../authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc#cco-short-term-creds-aws-olm_cco-short-term-creds[OLM-managed Operator support for authentication with AWS STS] -* xref:../../operators/admin/olm-adding-operators-to-cluster.adoc#olm-installing-from-operatorhub-using-web-console_olm-adding-operators-to-a-cluster[Installing from OperatorHub using the web console] -* xref:../../operators/admin/olm-adding-operators-to-cluster.adoc#olm-installing-operator-from-operatorhub-using-cli_olm-adding-operators-to-a-cluster[Installing from OperatorHub using the CLI] - -include::modules/osdk-cco-aws-sts-enabling.adoc[leveloffset=+2] -include::modules/osdk-cco-aws-sts-role.adoc[leveloffset=+2] -include::modules/osdk-cco-aws-sts-tshooting.adoc[leveloffset=+2] -include::modules/osdk-cco-aws-sts-alt.adoc[leveloffset=+2] \ No newline at end of file +* xref:../../../authentication/managing_cloud_provider_credentials/about-cloud-credential-operator.adoc#about-cloud-credential-operator[About the Cloud Credential Operator] +* xref:../../../operators/operator_sdk/token_auth/osdk-cco-aws-sts.adoc#osdk-cco-aws-sts[CCO-based workflow for OLM-managed Operators with AWS STS] +* xref:../../../operators/operator_sdk/token_auth/osdk-cco-azure.adoc#osdk-cco-azure[CCO-based workflow for OLM-managed Operators with {azure-id}] \ No newline at end of file diff --git a/operators/operator_sdk/token_auth/snippets b/operators/operator_sdk/token_auth/snippets new file mode 120000 index 0000000000..7bf6da9a51 --- /dev/null +++ b/operators/operator_sdk/token_auth/snippets @@ -0,0 +1 @@ +../../snippets \ No newline at end of file