Skip to content

Commit 68a2273

Browse files
authored
Merge pull request #81381 from adellape/olm-cco-gcp
OSDOCS-11905: Add GCP Workload Identity OLM/CCO docs
2 parents 59302c5 + 9e80780 commit 68a2273

11 files changed

+316
-22
lines changed

_topic_maps/_topic_map.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,6 +1960,8 @@ Topics:
19601960
File: osdk-cco-aws-sts
19611961
- Name: CCO-based workflow for OLM-managed Operators with Microsoft Entra Workload ID
19621962
File: osdk-cco-azure
1963+
- Name: CCO-based workflow for OLM-managed Operators with GCP Workload Identity
1964+
File: osdk-cco-gcp
19631965
- Name: Validating Operators using the scorecard
19641966
File: osdk-scorecard
19651967
- Name: Validating Operator bundles

authentication/managing_cloud_provider_credentials/cco-short-term-creds.adoc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,9 @@ include::modules/cco-short-term-creds-format-gcp.adoc[leveloffset=+2]
7878
//OLM-managed Operator support for authentication with GCP Workload Identity
7979
include::modules/cco-short-term-creds-gcp-olm.adoc[leveloffset=+2]
8080

81-
// Placeholder/guess for OLM link
82-
// [role="_additional-resources"]
83-
// .Additional resources
84-
// * xr3f:../../operators/operator_sdk/token_auth/osdk-cco-gcp.adoc#osdk-cco-gcp[CCO-based workflow for OLM-managed Operators with {gcp-wid-first}]
81+
[role="_additional-resources"]
82+
.Additional resources
83+
* xref:../../operators/operator_sdk/token_auth/osdk-cco-gcp.adoc#osdk-cco-gcp[CCO-based workflow for OLM-managed Operators with {gcp-wid-first}]
8584

8685
[id="cco-short-term-creds-azure_{context}"]
8786
== {entra-first}

modules/olm-installing-from-operatorhub-using-cli.adoc

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,24 +265,31 @@ spec:
265265
<2> Set a specific version of an Operator CSV.
266266
====
267267

268-
.. For clusters on cloud providers with token authentication enabled, configure your `Subscription` object by following these steps:
268+
.. For clusters on cloud providers with token authentication enabled, such as {aws-first} {sts-first}, {entra-first}, or {gcp-wid-first}, configure your `Subscription` object by following these steps:
269269

270270
... Ensure the `Subscription` object is set to manual update approvals:
271271
+
272+
.Example `Subscription` object with manual update approvals
273+
[%collapsible]
274+
====
272275
[source,yaml]
273276
----
274277
kind: Subscription
275278
# ...
276279
spec:
277280
installPlanApproval: Manual <1>
278281
----
279-
<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.
282+
<1> Subscriptions with automatic approvals for updates are not recommended because there might be permission changes to make before updating. Subscriptions with manual approvals for updates ensure that administrators have the opportunity to verify the permissions of the later version, take any necessary steps, and then update.
283+
====
280284

281285
... Include the relevant cloud provider-specific fields in the `Subscription` object's `config` section:
282286
+
283287
--
284288
* If the cluster is in AWS STS mode, include the following fields:
285289
+
290+
.Example `Subscription` object with {aws-short} {sts-short} variables
291+
[%collapsible]
292+
====
286293
[source,yaml]
287294
----
288295
kind: Subscription
@@ -294,9 +301,13 @@ spec:
294301
value: "<role_arn>" <1>
295302
----
296303
<1> Include the role ARN details.
304+
====
297305

298-
* If the cluster is in {entra-first} mode, include the following fields:
306+
* If the cluster is in {entra-short} mode, include the following fields:
299307
+
308+
.Example `Subscription` object with {entra-short} variables
309+
[%collapsible]
310+
====
300311
[source,yaml]
301312
----
302313
kind: Subscription
@@ -314,6 +325,41 @@ spec:
314325
<1> Include the client ID.
315326
<2> Include the tenant ID.
316327
<3> Include the subscription ID.
328+
====
329+
330+
* If the cluster is in {gcp-wid-short} mode, include the following fields:
331+
+
332+
.Example `Subscription` object with {gcp-wid-short} variables
333+
[%collapsible]
334+
====
335+
[source,yaml]
336+
----
337+
kind: Subscription
338+
# ...
339+
spec:
340+
config:
341+
env:
342+
- name: AUDIENCE
343+
value: "<audience_url>" <1>
344+
- name: SERVICE_ACCOUNT_EMAIL
345+
value: "<service_account_email>" <2>
346+
----
347+
348+
where:
349+
350+
`<audience>`:: Created in {gcp-short} by the administrator when they set up {gcp-wid-short}, the `AUDIENCE` value must be a preformatted URL in the following format:
351+
+
352+
[source,text]
353+
----
354+
//iam.googleapis.com/projects/<project_number>/locations/global/workloadIdentityPools/<pool_id>/providers/<provider_id>
355+
----
356+
`<service_account_email>`:: The `SERVICE_ACCOUNT_EMAIL` value is a {gcp-short} service account email that is impersonated during Operator operation, for example:
357+
+
358+
[source,text]
359+
----
360+
<service_account_name>@<project_id>.iam.gserviceaccount.com
361+
----
362+
====
317363
--
318364
319365
.. Create the `Subscription` object by running the following command:

modules/olm-installing-from-operatorhub-using-web-console.adoc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,20 @@ endif::[]
9090
.. For clusters on cloud providers with token authentication enabled:
9191
+
9292
--
93-
* If the cluster uses {aws-short} {sts-short} (*STS Mode* in the web console), enter the Amazon Resource Name (ARN) of the AWS IAM role of your service account in the *role ARN* field. 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].
93+
* If the cluster uses {aws-short} {sts-full} (*STS Mode* in the web console), enter the Amazon Resource Name (ARN) of the AWS IAM role of your service account in the *role ARN* field. 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].
9494

95-
* If the cluster uses {entra-first} (*Workload Identity / Federated Identity Mode* in the web console), add the client ID, tenant ID, and subscription ID in the appropriate field.
95+
* If the cluster uses {entra-first} (*Workload Identity / Federated Identity Mode* in the web console), add the client ID, tenant ID, and subscription ID in the appropriate fields.
96+
97+
* If the cluster uses {gcp-wid-first} (*{gcp-wid-short} / Federated Identity Mode* in the web console), add the project number, pool ID, provider ID, and service account email in the appropriate fields.
9698
--
9799
98100
.. For *Update approval*, select either the *Automatic* or *Manual* approval strategy.
99101
+
100102
[IMPORTANT]
101103
====
102-
If the web console shows that the cluster uses {aws-short} {sts-short} or {entra-first}, you must set *Update approval* to *Manual*.
104+
If the web console shows that the cluster uses {aws-short} {sts-short}, {entra-first}, or {gcp-wid-short}, you must set *Update approval* to *Manual*.
103105
104-
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.
106+
Subscriptions with automatic approvals for updates are not recommended because there might be permission changes to make before updating. Subscriptions with manual approvals for updates ensure that administrators have the opportunity to verify the permissions of the later version, take any necessary steps, and then update.
105107
====
106108

107109
. Click *Install* to make the Operator available to the selected namespaces on this {product-title} cluster:

modules/osdk-cco-aws-sts-enabling.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
As an Operator author designing your project to run on Operator Lifecycle Manager (OLM), you can enable your Operator to authenticate against AWS on STS-enabled {product-title} clusters by customizing your project to support the Cloud Credential Operator (CCO).
1111

12-
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.
12+
With this method, the Operator is responsible for and requires RBAC permissions for creating the `CredentialsRequest` object and reading the resulting `Secret` object.
1313

1414
[NOTE]
1515
====
@@ -206,7 +206,7 @@ Adding a `CredentialsRequest` object to the Operator bundle is not currently sup
206206
====
207207
[source,go]
208208
----
209-
// apply credentialsRequest on install
209+
// apply CredentialsRequest on install
210210
credReq := credreq.CredentialsRequestTemplate
211211
credReq.Spec.CloudTokenPath = webIdentityTokenPath
212212

modules/osdk-cco-azure-enabling.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
As an Operator author designing your project to run on Operator Lifecycle Manager (OLM), you can enable your Operator to authenticate against {entra-first}-enabled {product-title} clusters by customizing your project to support the Cloud Credential Operator (CCO).
1010

11-
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.
11+
With this method, the Operator is responsible for and requires RBAC permissions for creating the `CredentialsRequest` object and reading the resulting `Secret` object.
1212

1313
[NOTE]
1414
====
@@ -89,7 +89,7 @@ Adding a `CredentialsRequest` object to the Operator bundle is not currently sup
8989
====
9090
[source,go]
9191
----
92-
// apply credentialsRequest on install
92+
// apply CredentialsRequest on install
9393
credReqTemplate.Spec.AzureProviderSpec.AzureClientID = clientID
9494
credReqTemplate.Spec.AzureProviderSpec.AzureTenantID = tenantID
9595
credReqTemplate.Spec.AzureProviderSpec.AzureRegion = "centralus"

modules/osdk-cco-gcp-enabling.adoc

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Module included in the following assemblies:
2+
//
3+
// * operators/operator_sdk/osdk-token-auth/osdk-cco-gcp.adoc
4+
5+
:_mod-docs-content-type: PROCEDURE
6+
[id="osdk-cco-gcp-enabling_{context}"]
7+
= Enabling Operators to support CCO-based workflows with {gcp-wid-short}
8+
9+
As an Operator author designing your project to run on Operator Lifecycle Manager (OLM), you can enable your Operator to authenticate against {gcp-wid-first} on {product-title} clusters by customizing your project to support the Cloud Credential Operator (CCO).
10+
11+
With this method, the Operator is responsible for and requires RBAC permissions for creating the `CredentialsRequest` object and reading the resulting `Secret` object.
12+
13+
[NOTE]
14+
====
15+
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.
16+
====
17+
18+
.Prerequisities
19+
20+
* {product-title} 4.17 or later
21+
* Cluster in *{gcp-wid-short} / Federated Identity* mode
22+
* OLM-based Operator project
23+
24+
.Procedure
25+
26+
. Update your Operator project's `ClusterServiceVersion` (CSV) object:
27+
28+
.. Ensure Operator deployment in the CSV has the following `volumeMounts` and `volumes` fields so that the Operator can assume the role with web identity:
29+
+
30+
.Example `volumeMounts` and `volumes` fields
31+
[%collapsible]
32+
====
33+
[source,yaml]
34+
----
35+
# ...
36+
volumeMounts:
37+
38+
- name: bound-sa-token
39+
mountPath: /var/run/secrets/openshift/serviceaccount
40+
readOnly: true
41+
volumes:
42+
# This service account token can be used to provide identity outside the cluster.
43+
- name: bound-sa-token
44+
projected:
45+
sources:
46+
- serviceAccountToken:
47+
path: token
48+
audience: openshift
49+
----
50+
====
51+
52+
.. Ensure your Operator has RBAC permission to create `CredentialsRequests` objects:
53+
+
54+
.Example `clusterPermissions` list
55+
[%collapsible]
56+
====
57+
[source,yaml]
58+
----
59+
# ...
60+
install:
61+
spec:
62+
clusterPermissions:
63+
- rules:
64+
- apiGroups:
65+
- "cloudcredential.openshift.io"
66+
resources:
67+
- credentialsrequests
68+
verbs:
69+
- create
70+
- delete
71+
- get
72+
- list
73+
- patch
74+
- update
75+
- watch
76+
----
77+
====
78+
79+
.. Add the following annotation to claim support for this method of CCO-based workflow with {gcp-wid-short}:
80+
+
81+
[source,yaml]
82+
----
83+
# ...
84+
metadata:
85+
annotations:
86+
features.operators.openshift.io/token-auth-gcp: "true"
87+
----
88+
89+
. Update your Operator project code:
90+
91+
.. Get the `audience` and the `serviceAccountEmail` values from the environment variables set on the pod by the subscription config:
92+
+
93+
[source,go]
94+
----
95+
// Get ENV var
96+
audience := os.Getenv("AUDIENCE")
97+
serviceAccountEmail := os.Getenv("SERVICE_ACCOUNT_EMAIL")
98+
gcpIdentityTokenFile := "/var/run/secrets/openshift/serviceaccount/token"
99+
----
100+
101+
.. Ensure you have a `CredentialsRequest` object ready to be patched and applied.
102+
+
103+
[NOTE]
104+
====
105+
Adding a `CredentialsRequest` object to the Operator bundle is not currently supported.
106+
====
107+
108+
.. Add the {gcp-wid-short} variables to the credentials request and apply it during Operator initialization:
109+
+
110+
.Example applying `CredentialsRequest` object during Operator initialization
111+
[%collapsible]
112+
====
113+
[source,go]
114+
----
115+
// apply CredentialsRequest on install
116+
credReqTemplate.Spec.GCPProviderSpec.Audience = audience
117+
credReqTemplate.Spec.GCPProviderSpec.ServiceAccountEmail = serviceAccountEmail
118+
credReqTemplate.CloudTokenPath = gcpIdentityTokenFile
119+
120+
121+
c := mgr.GetClient()
122+
if err := c.Create(context.TODO(), credReq); err != nil {
123+
if !errors.IsAlreadyExists(err) {
124+
setupLog.Error(err, "unable to create CredRequest")
125+
os.Exit(1)
126+
}
127+
}
128+
----
129+
====
130+
131+
.. 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:
132+
+
133+
.Example wait for `Secret` object
134+
[%collapsible]
135+
====
136+
[source,go]
137+
----
138+
// WaitForSecret is a function that takes a Kubernetes client, a namespace, and a v1 "k8s.io/api/core/v1" name as arguments
139+
// It waits until the secret object with the given name exists in the given namespace
140+
// It returns the secret object or an error if the timeout is exceeded
141+
func WaitForSecret(client kubernetes.Interface, namespace, name string) (*v1.Secret, error) {
142+
// set a timeout of 10 minutes
143+
timeout := time.After(10 * time.Minute) <1>
144+
145+
// set a polling interval of 10 seconds
146+
ticker := time.NewTicker(10 * time.Second)
147+
148+
// loop until the timeout or the secret is found
149+
for {
150+
select {
151+
case <-timeout:
152+
// timeout is exceeded, return an error
153+
return nil, fmt.Errorf("timed out waiting for secret %s in namespace %s", name, namespace)
154+
// add to this error with a pointer to instructions for following a manual path to a Secret that will work
155+
case <-ticker.C:
156+
// polling interval is reached, try to get the secret
157+
secret, err := client.CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{})
158+
if err != nil {
159+
if errors.IsNotFound(err) {
160+
// secret does not exist yet, continue waiting
161+
continue
162+
} else {
163+
// some other error occurred, return it
164+
return nil, err
165+
}
166+
} else {
167+
// secret is found, return it
168+
return secret, nil
169+
}
170+
}
171+
}
172+
}
173+
----
174+
<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.
175+
====
176+
177+
.. Read the `service_account.json` field from the secret and use it to authenticate your {gcp-short} client:
178+
+
179+
[source,go]
180+
----
181+
service_account_json := secret.StringData["service_account.json"]
182+
----

operators/operator_sdk/token_auth/osdk-cco-aws-sts.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ The JWT includes an Amazon Resource Name (ARN) for the `sts:AssumeRoleWithWebIde
1313
The Cloud Credential Operator (CCO) is a cluster Operator installed by default in {product-title} clusters running on cloud providers. For the purposes of STS, the CCO provides the following functions:
1414

1515
* Detects when it is running on an STS-enabled cluster
16-
* Checks for the presence of fields in the `CredentialsRequest` object that provide the required information for granting Operators access to AWS resources
16+
* Checks the `CredentialsRequest` object for the presence of fields that provide the required information for granting Operators access to AWS resources
1717
1818
The CCO performs this detection even when in manual mode. When properly configured, the CCO projects a `Secret` object with the required access information into the Operator namespace.
1919

2020
Starting in {product-title} 4.14, the CCO can semi-automate this task through an expanded use of `CredentialsRequest` objects, which can request the creation of `Secrets` that contain the information required for STS workflows. Users can provide a role ARN when installing the Operator from either the web console or CLI.
2121

2222
[NOTE]
2323
====
24-
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.
24+
Subscriptions with automatic approvals for updates are not recommended because there might be permission changes to make before updating. Subscriptions with manual approvals for updates ensure that administrators have the opportunity to verify the permissions of the later version, take any necessary steps, and then update.
2525
====
2626

27-
As an Operator author preparing an Operator for use alongside the updated CCO in {product-title} 4.14 or later, you should instruct users and add code to handle the divergence from earlier CCO versions, in addition to handling STS token authentication (if your Operator is not already STS-enabled). The recommended method is to provide a `CredentialsRequest` object with correctly filled STS-related fields and let the CCO create the `Secret` for you.
27+
As an Operator author preparing an Operator for use alongside the updated CCO in {product-title} 4.14 or later, you should instruct users and add code to handle the divergence from earlier CCO versions, in addition to handling STS token authentication (if your Operator is not already STS-enabled). The recommended method is to provide a `CredentialsRequest` object with the correctly filled {sts-short} fields and let the CCO create the `Secret` for you.
2828

2929
[IMPORTANT]
3030
====

0 commit comments

Comments
 (0)