]> git.proxmox.com Git - ceph.git/blob - ceph/doc/radosgw/STS.rst
Import ceph 15.2.8
[ceph.git] / ceph / doc / radosgw / STS.rst
1 ===========
2 STS in Ceph
3 ===========
4
5 Secure Token Service is a web service in AWS that returns a set of temporary security credentials for authenticating federated users.
6 The link to official AWS documentation can be found here: https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html.
7
8 Ceph Object Gateway implements a subset of STS APIs that provide temporary credentials for identity and access management.
9 These temporary credentials can be used to make subsequent S3 calls which will be authenticated by the STS engine in Ceph Object Gateway.
10 Permissions of the temporary credentials can be further restricted via an IAM policy passed as a parameter to the STS APIs.
11
12 STS REST APIs
13 =============
14
15 The following STS REST APIs have been implemented in Ceph Object Gateway:
16
17 1. AssumeRole: Returns a set of temporary credentials that can be used for
18 cross-account access. The temporary credentials will have permissions that are
19 allowed by both - permission policies attached with the Role and policy attached
20 with the AssumeRole API.
21
22 Parameters:
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
42 2. AssumeRoleWithWebIdentity: Returns a set of temporary credentials for users that
43 have been authenticated by a web/mobile app by an OpenID Connect /OAuth2.0 Identity Provider.
44 Currently Keycloak has been tested and integrated with RGW.
45
46 Parameters:
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
63 Before invoking AssumeRoleWithWebIdentity, an OpenID Connect Provider entity (which the web application
64 authenticates with), needs to be created in RGW.
65
66 The trust between the IDP and the role is created by adding a Condition to the role trust policy, which
67 allows access only to applications with the app id given in the trust policy document. The Condition
68 is of the form::
69
70 "{\"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>\"\}\}\}\]\}"
71
72 The app_id in the condition above must match the 'aud' field of the incoming token.
73
74 STS Configuration
75 =================
76
77 The following configurable options have to be added for STS integration::
78
79 [client.radosgw.gateway]
80 rgw sts key = {sts key for encrypting the session token}
81 rgw s3 auth use sts = true
82
83 Note: By default, STS and S3 APIs co-exist in the same namespace, and both S3
84 and STS APIs can be accessed via the same endpoint in Ceph Object Gateway.
85
86 Examples
87 ========
88
89 1. The following is an example of AssumeRole API call, which shows steps to create a role, assign a policy to it
90 (that allows access to S3 resources), assuming a role to get temporary credentials and accessing s3 resources using
91 those credentials. In this example, TESTER1 assumes a role created by TESTER, to access S3 resources owned by TESTER,
92 according to the permission policy attached to the role.
93
94 .. code-block:: python
95
96 import boto3
97
98 iam_client = boto3.client('iam',
99 aws_access_key_id=<access_key of TESTER>,
100 aws_secret_access_key=<secret_key of TESTER>,
101 endpoint_url=<IAM URL>,
102 region_name=''
103 )
104
105 policy_document = "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"arn:aws:iam:::user/TESTER1\"]},\"Action\":[\"sts:AssumeRole\"]}]}"
106
107 role_response = iam_client.create_role(
108 AssumeRolePolicyDocument=policy_document,
109 Path='/',
110 RoleName='S3Access',
111 )
112
113 role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::*\"}}"
114
115 response = iam_client.put_role_policy(
116 RoleName='S3Access',
117 PolicyName='Policy1',
118 PolicyDocument=role_policy
119 )
120
121 sts_client = boto3.client('sts',
122 aws_access_key_id=<access_key of TESTER1>,
123 aws_secret_access_key=<secret_key of TESTER1>,
124 endpoint_url=<STS URL>,
125 region_name='',
126 )
127
128 response = sts_client.assume_role(
129 RoleArn=role_response['Role']['Arn'],
130 RoleSessionName='Bob',
131 DurationSeconds=3600
132 )
133
134 s3client = boto3.client('s3',
135 aws_access_key_id = response['Credentials']['AccessKeyId'],
136 aws_secret_access_key = response['Credentials']['SecretAccessKey'],
137 aws_session_token = response['Credentials']['SessionToken'],
138 endpoint_url=<S3 URL>,
139 region_name='',)
140
141 bucket_name = 'my-bucket'
142 s3bucket = s3client.create_bucket(Bucket=bucket_name)
143 resp = s3client.list_buckets()
144
145 2. The following is an example of AssumeRoleWithWebIdentity API call, where an external app that has users authenticated with
146 an OpenID Connect/ OAuth2 IDP (Keycloak in this example), assumes a role to get back temporary credentials and access S3 resources
147 according to permission policy of the role.
148
149 .. code-block:: python
150
151 import boto3
152
153 iam_client = boto3.client('iam',
154 aws_access_key_id=<access_key of TESTER>,
155 aws_secret_access_key=<secret_key of TESTER>,
156 endpoint_url=<IAM URL>,
157 region_name=''
158 )
159
160 oidc_response = iam_client.create_open_id_connect_provider(
161 Url=<URL of the OpenID Connect Provider,
162 ClientIDList=[
163 <Client id registered with the IDP>
164 ],
165 ThumbprintList=[
166 <Thumbprint of the IDP>
167 ]
168 )
169
170 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\"}}}]}"
171 role_response = iam_client.create_role(
172 AssumeRolePolicyDocument=policy_document,
173 Path='/',
174 RoleName='S3Access',
175 )
176
177 role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::*\"}}"
178
179 response = iam_client.put_role_policy(
180 RoleName='S3Access',
181 PolicyName='Policy1',
182 PolicyDocument=role_policy
183 )
184
185 sts_client = boto3.client('sts',
186 aws_access_key_id=<access_key of TESTER1>,
187 aws_secret_access_key=<secret_key of TESTER1>,
188 endpoint_url=<STS URL>,
189 region_name='',
190 )
191
192 response = client.assume_role_with_web_identity(
193 RoleArn=role_response['Role']['Arn'],
194 RoleSessionName='Bob',
195 DurationSeconds=3600,
196 WebIdentityToken=<Web Token>
197 )
198
199 s3client = boto3.client('s3',
200 aws_access_key_id = response['Credentials']['AccessKeyId'],
201 aws_secret_access_key = response['Credentials']['SecretAccessKey'],
202 aws_session_token = response['Credentials']['SessionToken'],
203 endpoint_url=<S3 URL>,
204 region_name='',)
205
206 bucket_name = 'my-bucket'
207 s3bucket = s3client.create_bucket(Bucket=bucket_name)
208 resp = s3client.list_buckets()
209
210 How to obtain thumbprint of an OpenID Connect Provider IDP
211 ==========================================================
212 1. Take the OpenID connect provider's URL and add /.well-known/openid-configuration
213 to it to get the URL to get the IDP's configuration document. For example, if the URL
214 of the IDP is http://localhost:8000/auth/realms/quickstart, then the URL to get the
215 document from is http://localhost:8000/auth/realms/quickstart/.well-known/openid-configuration
216
217 2. Use the following curl command to get the configuration document from the URL described
218 in step 1::
219
220 curl -k -v \
221 -X GET \
222 -H "Content-Type: application/x-www-form-urlencoded" \
223 "http://localhost:8000/auth/realms/quickstart/.well-known/openid-configuration" \
224 | jq .
225
226 3. From the response of step 2, use the value of "jwks_uri" to get the certificate of the IDP,
227 using the following code::
228 curl -k -v \
229 -X GET \
230 -H "Content-Type: application/x-www-form-urlencoded" \
231 "http://$KC_SERVER/$KC_CONTEXT/realms/$KC_REALM/protocol/openid-connect/certs" \
232 | jq .
233
234 3. Copy the result of "x5c" in the response above, in a file certificate.crt, and add
235 '-----BEGIN CERTIFICATE-----' at the beginning and "-----END CERTIFICATE-----"
236 at the end.
237
238 4. Use the following OpenSSL command to get the certificate thumbprint::
239
240 openssl x509 -in certificate.crt -fingerprint -noout
241
242 5. The result of the above command in step 4, will be a SHA1 fingerprint, like the following::
243
244 SHA1 Fingerprint=F7:D7:B3:51:5D:D0:D3:19:DD:21:9A:43:A9:EA:72:7A:D6:06:52:87
245
246 6. Remove the colons from the result above to get the final thumbprint which can be as input
247 while creating the OpenID Connect Provider entity in IAM::
248
249 F7D7B3515DD0D319DD219A43A9EA727AD6065287
250
251 Roles in RGW
252 ============
253
254 More information for role manipulation can be found here
255 :doc:`role`.
256
257 OpenID Connect Provider in RGW
258 ==============================
259
260 More information for OpenID Connect Provider entity manipulation
261 can be found here
262 :doc:`oidc`.
263
264 Keycloak integration with Radosgw
265 =================================
266
267 Steps for integrating Radosgw with Keycloak can be found here
268 :doc:`keycloak`.
269
270 STSLite
271 =======
272 STSLite has been built on STS, and documentation for the same can be found here
273 :doc:`STSLite`.