]> git.proxmox.com Git - ceph.git/blame - ceph/doc/radosgw/STS.rst
import ceph quincy 17.2.4
[ceph.git] / ceph / doc / radosgw / STS.rst
CommitLineData
9f95a23c
TL
1===========
2STS in Ceph
3===========
4
5Secure Token Service is a web service in AWS that returns a set of temporary security credentials for authenticating federated users.
6The link to official AWS documentation can be found here: https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html.
7
8Ceph Object Gateway implements a subset of STS APIs that provide temporary credentials for identity and access management.
9These temporary credentials can be used to make subsequent S3 calls which will be authenticated by the STS engine in Ceph Object Gateway.
10Permissions of the temporary credentials can be further restricted via an IAM policy passed as a parameter to the STS APIs.
11
12STS REST APIs
13=============
14
15The following STS REST APIs have been implemented in Ceph Object Gateway:
16
171. AssumeRole: Returns a set of temporary credentials that can be used for
18cross-account access. The temporary credentials will have permissions that are
19allowed by both - permission policies attached with the Role and policy attached
20with the AssumeRole API.
21
22Parameters:
23 **RoleArn** (String/ Required): ARN of the Role to Assume.
24
25 **RoleSessionName** (String/ Required): An Identifier for the assumed role
26 session.
27
28 **Policy** (String/ Optional): An IAM Policy in JSON format.
29
30 **DurationSeconds** (Integer/ Optional): The duration in seconds of the session.
31 Its default value is 3600.
32
33 **ExternalId** (String/ Optional): A unique Id that might be used when a role is
34 assumed in another account.
35
36 **SerialNumber** (String/ Optional): The Id number of the MFA device associated
37 with the user making the AssumeRole call.
38
39 **TokenCode** (String/ Optional): The value provided by the MFA device, if the
40 trust policy of the role being assumed requires MFA.
41
422. AssumeRoleWithWebIdentity: Returns a set of temporary credentials for users that
43have been authenticated by a web/mobile app by an OpenID Connect /OAuth2.0 Identity Provider.
44Currently Keycloak has been tested and integrated with RGW.
45
46Parameters:
47 **RoleArn** (String/ Required): ARN of the Role to Assume.
48
49 **RoleSessionName** (String/ Required): An Identifier for the assumed role
50 session.
51
52 **Policy** (String/ Optional): An IAM Policy in JSON format.
53
54 **DurationSeconds** (Integer/ Optional): The duration in seconds of the session.
55 Its default value is 3600.
56
57 **ProviderId** (String/ Optional): Fully qualified host component of the domain name
58 of the IDP. Valid only for OAuth2.0 tokens (not for OpenID Connect tokens).
59
60 **WebIdentityToken** (String/ Required): The OpenID Connect/ OAuth2.0 token, which the
61 application gets in return after authenticating its user with an IDP.
62
f91f0fd5
TL
63Before invoking AssumeRoleWithWebIdentity, an OpenID Connect Provider entity (which the web application
64authenticates with), needs to be created in RGW.
65
20effc67
TL
66The trust between the IDP and the role is created by adding a condition to the role's trust policy, which
67allows access only to applications which satisfy the given condition.
68All claims of the JWT are supported in the condition of the role's trust policy.
69An example of a policy that uses the 'aud' claim in the condition is of the form::
f91f0fd5 70
20effc67 71 '''{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":["arn:aws:iam:::oidc-provider/<URL of IDP>"]},"Action":["sts:AssumeRoleWithWebIdentity"],"Condition":{"StringEquals":{"<URL of IDP> :app_id":"<aud>"}}}]}'''
f91f0fd5 72
20effc67
TL
73The app_id in the condition above must match the 'aud' claim of the incoming token.
74
75An example of a policy that uses the 'sub' claim in the condition is of the form::
76
77 "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Federated\":[\"arn:aws:iam:::oidc-provider/<URL of IDP>\"]},\"Action\":[\"sts:AssumeRoleWithWebIdentity\"],\"Condition\":{\"StringEquals\":{\"<URL of IDP> :sub\":\"<sub>\"\}\}\}\]\}"
78
79Similarly, an example of a policy that uses 'azp' claim in the condition is of the form::
80
81 "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Federated\":[\"arn:aws:iam:::oidc-provider/<URL of IDP>\"]},\"Action\":[\"sts:AssumeRoleWithWebIdentity\"],\"Condition\":{\"StringEquals\":{\"<URL of IDP> :azp\":\"<azp>\"\}\}\}\]\}"
f91f0fd5 82
f67539c2
TL
83A shadow user is created corresponding to every federated user. The user id is derived from the 'sub' field of the incoming web token.
84The user is created in a separate namespace - 'oidc' such that the user id doesn't clash with any other user ids in rgw. The format of the user id
85is - <tenant>$<user-namespace>$<sub> where user-namespace is 'oidc' for users that authenticate with oidc providers.
86
20effc67
TL
87RGW now supports Session tags that can be passed in the web token to AssumeRoleWithWebIdentity call. More information related to Session Tags can be found here
88:doc:`session-tags`.
89
9f95a23c
TL
90STS Configuration
91=================
92
93The following configurable options have to be added for STS integration::
94
95 [client.radosgw.gateway]
96 rgw sts key = {sts key for encrypting the session token}
97 rgw s3 auth use sts = true
98
9f95a23c
TL
99Note: By default, STS and S3 APIs co-exist in the same namespace, and both S3
100and STS APIs can be accessed via the same endpoint in Ceph Object Gateway.
101
102Examples
103========
104
1051. The following is an example of AssumeRole API call, which shows steps to create a role, assign a policy to it
106(that allows access to S3 resources), assuming a role to get temporary credentials and accessing s3 resources using
107those credentials. In this example, TESTER1 assumes a role created by TESTER, to access S3 resources owned by TESTER,
108according to the permission policy attached to the role.
109
2a845540
TL
110.. code-block:: console
111
112 radosgw-admin caps add --uid="TESTER" --caps="roles=*"
113
1142. The following is an example of the AssumeRole API call, which shows steps to create a role, assign a policy to it
115 (that allows access to S3 resources), assuming a role to get temporary credentials and accessing S3 resources using
116 those credentials. In this example, TESTER1 assumes a role created by TESTER, to access S3 resources owned by TESTER,
117 according to the permission policy attached to the role.
118
9f95a23c
TL
119.. code-block:: python
120
121 import boto3
122
123 iam_client = boto3.client('iam',
124 aws_access_key_id=<access_key of TESTER>,
125 aws_secret_access_key=<secret_key of TESTER>,
126 endpoint_url=<IAM URL>,
127 region_name=''
128 )
129
20effc67 130 policy_document = '''{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["arn:aws:iam:::user/TESTER1"]},"Action":["sts:AssumeRole"]}]}'''
9f95a23c
TL
131
132 role_response = iam_client.create_role(
133 AssumeRolePolicyDocument=policy_document,
134 Path='/',
135 RoleName='S3Access',
136 )
137
20effc67 138 role_policy = '''{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::*"}}'''
9f95a23c
TL
139
140 response = iam_client.put_role_policy(
141 RoleName='S3Access',
142 PolicyName='Policy1',
143 PolicyDocument=role_policy
144 )
145
146 sts_client = boto3.client('sts',
147 aws_access_key_id=<access_key of TESTER1>,
148 aws_secret_access_key=<secret_key of TESTER1>,
149 endpoint_url=<STS URL>,
150 region_name='',
151 )
152
153 response = sts_client.assume_role(
154 RoleArn=role_response['Role']['Arn'],
155 RoleSessionName='Bob',
156 DurationSeconds=3600
157 )
158
159 s3client = boto3.client('s3',
160 aws_access_key_id = response['Credentials']['AccessKeyId'],
161 aws_secret_access_key = response['Credentials']['SecretAccessKey'],
162 aws_session_token = response['Credentials']['SessionToken'],
163 endpoint_url=<S3 URL>,
164 region_name='',)
165
166 bucket_name = 'my-bucket'
167 s3bucket = s3client.create_bucket(Bucket=bucket_name)
168 resp = s3client.list_buckets()
169
1702. The following is an example of AssumeRoleWithWebIdentity API call, where an external app that has users authenticated with
171an OpenID Connect/ OAuth2 IDP (Keycloak in this example), assumes a role to get back temporary credentials and access S3 resources
172according to permission policy of the role.
173
174.. code-block:: python
175
176 import boto3
177
178 iam_client = boto3.client('iam',
179 aws_access_key_id=<access_key of TESTER>,
180 aws_secret_access_key=<secret_key of TESTER>,
181 endpoint_url=<IAM URL>,
182 region_name=''
183 )
184
f91f0fd5
TL
185 oidc_response = iam_client.create_open_id_connect_provider(
186 Url=<URL of the OpenID Connect Provider,
187 ClientIDList=[
188 <Client id registered with the IDP>
189 ],
190 ThumbprintList=[
191 <Thumbprint of the IDP>
192 ]
193 )
194
20effc67 195 policy_document = '''{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":["arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/demo"]},"Action":["sts:AssumeRoleWithWebIdentity"],"Condition":{"StringEquals":{"localhost:8080/auth/realms/demo:app_id":"customer-portal"}}}]}'''
9f95a23c
TL
196 role_response = iam_client.create_role(
197 AssumeRolePolicyDocument=policy_document,
198 Path='/',
199 RoleName='S3Access',
200 )
201
20effc67 202 role_policy = '''{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::*"}}'''
9f95a23c
TL
203
204 response = iam_client.put_role_policy(
205 RoleName='S3Access',
206 PolicyName='Policy1',
207 PolicyDocument=role_policy
208 )
209
210 sts_client = boto3.client('sts',
211 aws_access_key_id=<access_key of TESTER1>,
212 aws_secret_access_key=<secret_key of TESTER1>,
213 endpoint_url=<STS URL>,
214 region_name='',
215 )
216
217 response = client.assume_role_with_web_identity(
218 RoleArn=role_response['Role']['Arn'],
219 RoleSessionName='Bob',
220 DurationSeconds=3600,
221 WebIdentityToken=<Web Token>
222 )
223
224 s3client = boto3.client('s3',
225 aws_access_key_id = response['Credentials']['AccessKeyId'],
226 aws_secret_access_key = response['Credentials']['SecretAccessKey'],
227 aws_session_token = response['Credentials']['SessionToken'],
228 endpoint_url=<S3 URL>,
229 region_name='',)
230
231 bucket_name = 'my-bucket'
232 s3bucket = s3client.create_bucket(Bucket=bucket_name)
233 resp = s3client.list_buckets()
234
f91f0fd5
TL
235How to obtain thumbprint of an OpenID Connect Provider IDP
236==========================================================
2371. Take the OpenID connect provider's URL and add /.well-known/openid-configuration
238to it to get the URL to get the IDP's configuration document. For example, if the URL
239of the IDP is http://localhost:8000/auth/realms/quickstart, then the URL to get the
240document from is http://localhost:8000/auth/realms/quickstart/.well-known/openid-configuration
241
2422. Use the following curl command to get the configuration document from the URL described
243in step 1::
244
245 curl -k -v \
246 -X GET \
247 -H "Content-Type: application/x-www-form-urlencoded" \
248 "http://localhost:8000/auth/realms/quickstart/.well-known/openid-configuration" \
249 | jq .
250
251 3. From the response of step 2, use the value of "jwks_uri" to get the certificate of the IDP,
252 using the following code::
253 curl -k -v \
254 -X GET \
255 -H "Content-Type: application/x-www-form-urlencoded" \
256 "http://$KC_SERVER/$KC_CONTEXT/realms/$KC_REALM/protocol/openid-connect/certs" \
257 | jq .
258
2593. Copy the result of "x5c" in the response above, in a file certificate.crt, and add
260'-----BEGIN CERTIFICATE-----' at the beginning and "-----END CERTIFICATE-----"
261at the end.
262
2634. Use the following OpenSSL command to get the certificate thumbprint::
264
265 openssl x509 -in certificate.crt -fingerprint -noout
266
2675. The result of the above command in step 4, will be a SHA1 fingerprint, like the following::
268
269 SHA1 Fingerprint=F7:D7:B3:51:5D:D0:D3:19:DD:21:9A:43:A9:EA:72:7A:D6:06:52:87
270
2716. Remove the colons from the result above to get the final thumbprint which can be as input
272while creating the OpenID Connect Provider entity in IAM::
273
274 F7D7B3515DD0D319DD219A43A9EA727AD6065287
275
9f95a23c
TL
276Roles in RGW
277============
278
279More information for role manipulation can be found here
280:doc:`role`.
281
f91f0fd5
TL
282OpenID Connect Provider in RGW
283==============================
284
285More information for OpenID Connect Provider entity manipulation
286can be found here
287:doc:`oidc`.
288
9f95a23c
TL
289Keycloak integration with Radosgw
290=================================
291
292Steps for integrating Radosgw with Keycloak can be found here
293:doc:`keycloak`.
294
295STSLite
296=======
297STSLite has been built on STS, and documentation for the same can be found here
2a845540 298:doc:`STSLite`.