Skip to content

Commit 27fe6b6

Browse files
authored
Merge pull request openshift#3151 from ahardin-rh/enj-3092
Add OAuth discovery and SA annotations docs
2 parents a78ae84 + 144af6f commit 27fe6b6

File tree

2 files changed

+212
-16
lines changed

2 files changed

+212
-16
lines changed

architecture/additional_concepts/authentication.adoc

Lines changed: 207 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ It then determines what user that identity maps to, creates an access token for
137137
that user, and returns the token for use.
138138

139139
[[oauth-clients]]
140-
*OAuth Clients*
140+
=== OAuth Clients
141141

142142
Every request for an OAuth token must specify the OAuth client that will
143143
receive and use the token. The following OAuth clients are automatically created
@@ -182,7 +182,7 @@ grantMethod: prompt <4>
182182
====
183183

184184
[[service-accounts-as-oauth-clients]]
185-
*Service Accounts as OAuth Clients*
185+
=== Service Accounts as OAuth Clients
186186

187187
A
188188
xref:../../admin_guide/service_accounts.adoc#admin-guide-service-accounts[service
@@ -194,27 +194,153 @@ service account's own namespace:
194194

195195
* `user:info`
196196
* `user:check-access`
197-
* `role:<any role>:<serviceaccount namespace>`
198-
* `role:<any role>:<serviceaccount namespace>:!`
197+
* `role:<any_role>:<serviceaccount_namespace>`
198+
* `role:<any_role>:<serviceaccount_namespace>:!`
199199

200200
When using a service account as an OAuth client:
201201

202-
* `client_id` is `system:serviceaccount:<serviceaccount namespace>:<serviceaccount name>`.
202+
* `client_id` is `system:serviceaccount:<serviceaccount_namespace>:<serviceaccount_name>`.
203203
* `client_secret` can be any of the API tokens for that service account. For example:
204204
+
205205
----
206-
$ oc sa get-token <serviceaccount name>
206+
$ oc sa get-token <serviceaccount_name>
207207
----
208208

209-
* `redirect_uri` must match an annotation on the service account that has the
210-
prefix `serviceaccounts.openshift.io/oauth-redirecturi`. For example,
211-
`serviceaccounts.openshift.io/oauth-redirecturi.one`.
212209
* To get `WWW-Authenticate` challenges, set an
213210
`serviceaccounts.openshift.io/oauth-want-challenges` annotation on the service
214211
account to *true*.
215212

213+
* `redirect_uri` must match an annotation on the service account.
214+
xref:redirect-uris-for-service-accounts[Redirect URIs for Service Accounts as
215+
OAuth Clients] provides more information.
216+
217+
[[redirect-uris-for-service-accounts]]
218+
==== Redirect URIs for Service Accounts as OAuth Clients
219+
220+
Annotation keys must have the prefix
221+
`serviceaccounts.openshift.io/oauth-redirecturi.` or
222+
`serviceaccounts.openshift.io/oauth-redirectreference.` such as:
223+
224+
----
225+
serviceaccounts.openshift.io/oauth-redirecturi.<name>
226+
----
227+
228+
In its simplest form, the annotation can be used to directly specify valid
229+
redirect URIs. For example:
230+
231+
----
232+
"serviceaccounts.openshift.io/oauth-redirecturi.first": "https://example.com"
233+
"serviceaccounts.openshift.io/oauth-redirecturi.second": "https://other.com"
234+
----
235+
236+
The `first` and `second` postfixes in the above example are used to separate the
237+
two valid redirect URIs.
238+
239+
In more complex configurations, static redirect URIs may not be enough. For
240+
example, perhaps you want all ingresses for a route to be considered valid. This
241+
is where dynamic redirect URIs via the
242+
`serviceaccounts.openshift.io/oauth-redirectreference.` prefix come into play.
243+
244+
For example:
245+
246+
----
247+
"serviceaccounts.openshift.io/oauth-redirectreference.first": "{\"kind\":\"OAuthRedirectReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"Route\",\"name\":\"jenkins\"}}"
248+
----
249+
250+
Since the value for this annotation contains serialized JSON data, it is easier
251+
to see in an expanded format:
252+
253+
----
254+
255+
{
256+
"kind": "OAuthRedirectReference",
257+
"apiVersion": "v1",
258+
"reference": {
259+
"kind": "Route",
260+
"name": "jenkins"
261+
}
262+
}
263+
264+
----
265+
266+
Now you can see that an `OAuthRedirectReference` allows us to reference the
267+
route named `jenkins`. Thus, all ingresses for that route will now be considered
268+
valid. The full specification for an `OAuthRedirectReference` is:
269+
270+
----
271+
272+
{
273+
"kind": "OAuthRedirectReference",
274+
"apiVersion": "v1",
275+
"reference": {
276+
"kind": ..., <1>
277+
"name": ..., <2>
278+
"group": ... <3>
279+
}
280+
}
281+
282+
----
283+
284+
<1> `kind` refers to the type of the object being referenced. Currently, only `route` is supported.
285+
<2> `name` refers to the name of the object. The object must be in the same namespace as the service account.
286+
<3> `group` refers to the group of the object. Leave this blank, as the group for a route is the empty string.
287+
288+
Both annotation prefixes can be combined to override the data provided by the
289+
reference object. For example:
290+
291+
----
292+
"serviceaccounts.openshift.io/oauth-redirecturi.first": "custompath"
293+
"serviceaccounts.openshift.io/oauth-redirectreference.first": "{\"kind\":\"OAuthRedirectReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"Route\",\"name\":\"jenkins\"}}"
294+
----
295+
296+
The `first` postfix is used to tie the annotations together. Assuming that the
297+
`jenkins` route had an ingress of *_\https://example.com_*, now
298+
*_\https://example.com/custompath_* is considered valid, but
299+
*_\https://example.com_* is not. The format for partially supplying override
300+
data is as follows:
301+
302+
[cols="4a,8a",options="header"]
303+
|===
304+
|Type | Syntax
305+
|Scheme| "https://"
306+
|Hostname| "//website.com"
307+
|Port| "//:8000"
308+
|Path| "examplepath"
309+
|===
310+
311+
[NOTE]
312+
====
313+
Specifying a host name override will replace the host name data from the
314+
referenced object, which is not likely to be desired behavior.
315+
====
316+
317+
Any combination of the above syntax can be combined using the following format:
318+
319+
`<scheme:>//<hostname><:port>/<path>`
320+
321+
The same object can be referenced more than once for more flexibility:
322+
323+
----
324+
"serviceaccounts.openshift.io/oauth-redirecturi.first": "custompath"
325+
"serviceaccounts.openshift.io/oauth-redirectreference.first": "{\"kind\":\"OAuthRedirectReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"Route\",\"name\":\"jenkins\"}}"
326+
"serviceaccounts.openshift.io/oauth-redirecturi.second": "//:8000"
327+
"serviceaccounts.openshift.io/oauth-redirectreference.second": "{\"kind\":\"OAuthRedirectReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"Route\",\"name\":\"jenkins\"}}"
328+
----
329+
330+
Assuming that the route named `jenkins` has an ingress of
331+
*_\https://example.com_*, then both *_\https://example.com:8000_* and
332+
*_\https://example.com/custompath_* are considered valid.
333+
334+
Static and dynamic annotations can be used at the same time to achieve the
335+
desired behavior:
336+
337+
----
338+
"serviceaccounts.openshift.io/oauth-redirectreference.first": "{\"kind\":\"OAuthRedirectReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"Route\",\"name\":\"jenkins\"}}"
339+
"serviceaccounts.openshift.io/oauth-redirecturi.second": "https://other.com"
340+
----
341+
216342
[[integrations]]
217-
*Integrations*
343+
=== Integrations
218344

219345
All requests for OAuth tokens involve a request to `_<master>_/oauth/authorize`.
220346
Most authentication integrations place an authenticating proxy in front of this
@@ -248,8 +374,78 @@ WWW-Authenticate challenges, users can visit `_<master>_/oauth/token/request`
248374
using a browser to obtain an access token manually.
249375
====
250376

377+
[[oauth-server-metadata]]
378+
=== OAuth Server Metadata
379+
380+
Applications running in {product-title} may need to discover information about
381+
the built-in OAuth server. For example, they may need to discover what the
382+
address of the `<master>` server is without manual configuration. To aid in
383+
this, {product-title} implements the IETF
384+
link:https://tools.ietf.org/html/draft-ietf-oauth-discovery-04[OAuth 2.0
385+
Authorization Server Metadata] draft specification.
386+
387+
Thus, any application running inside the cluster can issue a `GET` request to
388+
*_\https://openshift.default.svc/.well-known/oauth-authorization-server_* to fetch
389+
the following information:
390+
391+
----
392+
{
393+
"issuer": "https://<master>", <1>
394+
"authorization_endpoint": "https://<master>/oauth/authorize", <2>
395+
"token_endpoint": "https://<master>/oauth/token", <3>
396+
"scopes_supported": [ <4>
397+
"user:full",
398+
"user:info",
399+
"user:check-access",
400+
"user:list-scoped-projects",
401+
"user:list-projects"
402+
],
403+
"response_types_supported": [ <5>
404+
"code",
405+
"token"
406+
],
407+
"grant_types_supported": [ <6>
408+
"authorization_code",
409+
"implicit"
410+
],
411+
"code_challenge_methods_supported": [ <7>
412+
"plain",
413+
"S256"
414+
]
415+
}
416+
----
417+
<1> The authorization server's issuer identifier, which is a URL that uses the
418+
`https` scheme and has no query or fragment components. This is the location
419+
where `.well-known` link:https://tools.ietf.org/html/rfc5785[RFC 5785] resources
420+
containing information about the authorization server are published.
421+
<2> URL of the authorization server's authorization endpoint. See
422+
link:https://tools.ietf.org/html/rfc6749[RFC 6749].
423+
<3> URL of the authorization server's token endpoint. See
424+
link:https://tools.ietf.org/html/rfc6749[RFC 6749].
425+
<4> JSON array containing a list of the OAuth 2.0
426+
link:https://tools.ietf.org/html/rfc6749[RFC 6749] scope values that this
427+
authorization server supports. Note that not all supported scope values are
428+
advertised.
429+
<5> JSON array containing a list of the OAuth 2.0 `response_type` values that this
430+
authorization server supports. The array values used are the same as those used
431+
with the `response_types` parameter defined by "OAuth 2.0 Dynamic Client
432+
Registration Protocol" in link:https://tools.ietf.org/html/rfc7591[RFC 7591].
433+
<6> JSON array containing a list of the OAuth 2.0 grant type values that this
434+
authorization server supports. The array values used are the same as those used
435+
with the `grant_types` parameter defined by *OAuth 2.0 Dynamic Client
436+
Registration Protocol* in link:https://tools.ietf.org/html/rfc7591[RFC 7591].
437+
<7> JSON array containing a list of PKCE
438+
link:https://tools.ietf.org/html/rfc7636[RFC 7636] code challenge methods
439+
supported by this authorization server. Code challenge method values are used in
440+
the `code_challenge_method` parameter defined in
441+
link:https://tools.ietf.org/html/rfc7636#section-4.3[Section 4.3 of RFC 7636].
442+
The valid code challenge method values are those registered in the IANA *PKCE
443+
Code Challenge Methods* registry. See
444+
link:http://www.iana.org/assignments/oauth-parameters[IANA OAuth Parameters].
445+
446+
251447
[[obtaining-oauth-tokens]]
252-
*Obtaining OAuth Tokens*
448+
=== Obtaining OAuth Tokens
253449

254450
The OAuth server supports standard
255451
link:https://tools.ietf.org/html/rfc6749#section-4.1[authorization code grant]

using_images/other_images/jenkins.adoc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ You can manage Jenkins authentication in two ways:
6565
[[jenkins-openshift-oauth-authentication]]
6666
==== {product-title} OAuth authentication
6767

68-
OAuth authentication is activated by configuring the `*Configure Global
69-
Security*` panel in the Jenkins UI, or by setting the `*OPENSHIFT_ENABLE_OAUTH*`
68+
xref:../../architecture/additional_concepts/authentication.adoc#oauth[OAuth
69+
authentication] is activated by configuring the `*Configure Global Security*`
70+
panel in the Jenkins UI, or by setting the `*OPENSHIFT_ENABLE_OAUTH*`
7071
environment variable on the Jenkins `*Deployment Config*` to anything other than
7172
`false`. This activates the OpenShift Login plug-in, which retrieves the
7273
configuration information from pod data or by interacting with the
@@ -76,12 +77,12 @@ Valid user and password combinations are controlled by your identity provider.
7677
For example, if `Allow All` is the default identity provider, you can provide
7778
any non-empty string for both the user name and password. If you have
7879
administrator privileges in the project Jenkins is running in, you will have
79-
administrative privileges within Jenkins.
80+
administrative privileges within Jenkins.
8081

8182
Valid users are automatically added to the Jenkins authorization matrix at log
8283
in, dictated by the permissions within the Jenkins authorization matrix
8384
associated with the user. Users authenticated against {product-title} OAuth are
84-
added to the Jenkins authorization matrix on their first successful log in.
85+
added to the Jenkins authorization matrix on their first successful log in.
8586

8687
The `admin` role maps to the set of permissions traditionally associated with
8788
the `admin` user in the {product-title} Jenkins image:
@@ -399,4 +400,3 @@ Jenkins job] that is pre-configured in the Jenkins image utilizes the
399400
plug-in for creating CI/CD flows for {product-title} in Jenkins.
400401

401402
See the https://github.com/openshift/jenkins-plugin/[the plug-in's README] for a detailed description of what is available.
402-

0 commit comments

Comments
 (0)