STS Lite

Ceph Object Gateway provides support for a subset of Amazon Secure Token Service(STS) APIs. STS Lite provides access to a set of temporary credentials forIdentity and Access Management.

STS authentication mechanism has been integrated with Keystone in Ceph ObjectGateway. A set of temporary security credentials is returned after authenticatinga set of AWS credentials with Keystone. These temporary credentials can be usedto make subsequent S3 calls which will be authenticated by the STS engine,resulting in less load on the Keystone server.

STS Lite REST APIs

The following STS Lite REST APIs have been implemented in Ceph Object Gateway:

  1. GetSessionToken: Returns a set of temporary credentials for a set of AWScredentials. This API can be used for initial authentication with Keystoneand the temporary credentials returned can be used to make subsequent S3calls. The temporary credentials will have the same permission as that of theAWS credentials.
  • Parameters:
  • DurationSeconds (Integer/ Optional): The duration in seconds for which thecredentials should remain valid. Its default value is 3600. Its default maxvalue is 43200 which is can be configured using rgw sts max session duration.

SerialNumber (String/ Optional): The Id number of the MFA device associatedwith the user making the GetSessionToken call.

TokenCode (String/ Optional): The value provided by the MFA device, if MFA is required.

An end user needs to attach a policy to allow invocation of GetSessionToken API using its permanentcredentials and to allow subsequent s3 operations invocation using only the temporary credentials returnedby GetSessionToken.The following is an example of attaching the policy to a user ‘TESTER1’:

  1. s3curl.pl --debug --id admin -- -s -v -X POST "http://localhost:8000/?Action=PutUserPolicy&PolicyName=Policy1&UserName=TESTER1&PolicyDocument=\{\"Version\":\"2012-10-17\",\"Statement\":\[\{\"Effect\":\"Deny\",\"Action\":\"s3:*\",\"Resource\":\[\"*\"\],\"Condition\":\{\"BoolIfExists\":\{\"sts:authentication\":\"false\"\}\}\},\{\"Effect\":\"Allow\",\"Action\":\"sts:GetSessionToken\",\"Resource\":\"*\",\"Condition\":\{\"BoolIfExists\":\{\"sts:authentication\":\"false\"\}\}\}\]\}&Version=2010-05-08"

The user attaching the policy needs to have admin caps. For example:

  1. radosgw-admin caps add --uid="TESTER" --caps="user-policy=*"
  1. AssumeRole: Returns a set of temporary credentials that can be used forcross-account access. The temporary credentials will have permissions that areallowed by both - permission policies attached with the Role and policy attachedwith the AssumeRole API.
  • Parameters:
  • RoleArn (String/ Required): ARN of the Role to Assume.

RoleSessionName (String/ Required): An Identifier for the assumed rolesession.

Policy (String/ Optional): An IAM Policy in JSON format.

DurationSeconds (Integer/ Optional): The duration in seconds of the session.Its default value is 3600.

ExternalId (String/ Optional): A unique Id that might be used when a role isassumed in another account.

SerialNumber (String/ Optional): The Id number of the MFA device associatedwith the user making the AssumeRole call.

TokenCode (String/ Optional): The value provided by the MFA device, if thetrust policy of the role being assumed requires MFA.

STS Lite Configuration

The following configurable options are available for STS Lite integration:

  1. [client.radosgw.gateway]
  2. rgw sts key = {sts key for encrypting the session token}
  3. rgw s3 auth use sts = true

The above STS configurables can be used with the Keystone configurables if oneneeds to use STS Lite in conjunction with Keystone. The complete set ofconfigurable options will be:

  1. [client.radosgw.gateway]
  2. rgw sts key = {sts key for encrypting/ decrypting the session token}
  3. rgw s3 auth use sts = true
  4.  
  5. rgw keystone url = {keystone server url:keystone server admin port}
  6. rgw keystone admin project = {keystone admin project name}
  7. rgw keystone admin tenant = {keystone service tenant name}
  8. rgw keystone admin domain = {keystone admin domain name}
  9. rgw keystone api version = {keystone api version}
  10. rgw keystone implicit tenants = {true for private tenant for each new user}
  11. rgw keystone admin password = {keystone service tenant user name}
  12. rgw keystone admin user = keystone service tenant user password}
  13. rgw keystone accepted roles = {accepted user roles}
  14. rgw keystone token cache size = {number of tokens to cache}
  15. rgw s3 auth use keystone = true

Note: By default, STS and S3 APIs co-exist in the same namespace, and both S3and STS APIs can be accessed via the same endpoint in Ceph Object Gateway.

Example showing how to Use STS Lite with Keystone

The following are the steps needed to use STS Lite with Keystone. Boto 3.x hasbeen used to write an example code to show the integration of STS Lite withKeystone.

  • Generate EC2 credentials :
  1. openstack ec2 credentials create
  2. +------------+--------------------------------------------------------+
  3. | Field | Value |
  4. +------------+--------------------------------------------------------+
  5. | access | b924dfc87d454d15896691182fdeb0ef |
  6. | links | {u'self': u'http://192.168.0.15/identity/v3/users/ |
  7. | | 40a7140e424f493d8165abc652dc731c/credentials/ |
  8. | | OS-EC2/b924dfc87d454d15896691182fdeb0ef'} |
  9. | project_id | c703801dccaf4a0aaa39bec8c481e25a |
  10. | secret | 6a2142613c504c42a94ba2b82147dc28 |
  11. | trust_id | None |
  12. | user_id | 40a7140e424f493d8165abc652dc731c |
  13. +------------+--------------------------------------------------------+
  • Use the credentials created in the step 1. to get back a set of temporarycredentials using GetSessionToken API.
  1. import boto3
  2.  
  3. access_key = <ec2 access key>
  4. secret_key = <ec2 secret key>
  5.  
  6. client = boto3.client('sts',
  7. aws_access_key_id=access_key,
  8. aws_secret_access_key=secret_key,
  9. endpoint_url=<STS URL>,
  10. region_name='',
  11. )
  12.  
  13. response = client.get_session_token(
  14. DurationSeconds=43200
  15. )
  • The temporary credentials obtained in step 2. can be used for making S3 calls:
  1. s3client = boto3.client('s3',
  2. aws_access_key_id = response['Credentials']['AccessKeyId'],
  3. aws_secret_access_key = response['Credentials']['SecretAccessKey'],
  4. aws_session_token = response['Credentials']['SessionToken'],
  5. endpoint_url=<S3 URL>,
  6. region_name='')
  7.  
  8. bucket = s3client.create_bucket(Bucket='my-new-shiny-bucket')
  9. response = s3client.list_buckets()
  10. for bucket in response["Buckets"]:
  11. print "{name}\t{created}".format(
  12. name = bucket['Name'],
  13. created = bucket['CreationDate'],
  14. )
  • The following is an example of AssumeRole API call:
  1. import boto3
  2.  
  3. access_key = <ec2 access key>
  4. secret_key = <ec2 secret key>
  5.  
  6. client = boto3.client('sts',
  7. aws_access_key_id=access_key,
  8. aws_secret_access_key=secret_key,
  9. endpoint_url=<STS URL>,
  10. region_name='',
  11. )
  12.  
  13. response = client.assume_role(
  14. RoleArn='arn:aws:iam:::role/application_abc/component_xyz/S3Access',
  15. RoleSessionName='Bob',
  16. DurationSeconds=3600
  17. )

Note: A role ‘S3Access’, needs to be created before calling the AssumeRole API.

Limitations and Workarounds

  1. Keystone currently supports only S3 requests, hence in order to successfullyauthenticate an STS request, the following workaround needs to be added to bototo the following file - botocore/auth.py

Lines 13-16 have been added as a workaround in the code block below:

  1. class SigV4Auth(BaseSigner):
  2. """
  3. Sign a request with Signature V4.
  4. """
  5. REQUIRES_REGION = True
  6.  
  7. def __init__(self, credentials, service_name, region_name):
  8. self.credentials = credentials
  9. # We initialize these value here so the unit tests can have
  10. # valid values. But these will get overridden in ``add_auth``
  11. # later for real requests.
  12. self._region_name = region_name
  13. if service_name == 'sts':
  14. self._service_name = 's3'
  15. else:
  16. self._service_name = service_name