edit-icon download-icon

Mobile Gaming - Security Token Service with Object Storage Service

Last Updated: Apr 23, 2018

Introduction

In mobile gaming, many applications require developers to segregate player resources. This includes a range of things, from saving files to processing user profile information. Using traditional methods, developers can manage this segregation, but must consider many other problems such as security, scalability, and APIs.

As cloud technologies evolve, the need for higher-level usability and features is increasing. With Object Storage Service (OSS), customers can store and manage their objects easily and efficiently. OSS provides real-time image processing service online. Some customers may want additional features such as allowing users to have limited access to a service like OSS, but with the convenience of secure, centralized management.

Security Token Service provides short-term access permission management for Alibaba Cloud accounts or RAM users. Through STS, you can issue federated users, who are managed in your local account system, with an access credential that customizes the expiration duration and access permission. Federated users can use the STS temporary access credential to directly call the Alibaba Cloud service API or to log on to the Alibaba Cloud Management Console to access authenticated resources.

In this scenario, we test the functionality of STS by using OSS.

Prerequisites

It requires the ability to adjust Resource Access Management (RAM) settings and Roles. For more information, see Roles.

The sample code is written in Python. While it is not required, a basic understanding of computer programming is an advantage. The sample code provided in this tutorial can serve as a template which can be modified to meet your specific needs. Many people are currently using the raw API so as to manage an environment, or an application. While an SDK is available in many languages, the raw API provides more flexibility.

Architecture


1>1

In this diagram, a RAM user wants to upload images to a separate folder in an OSS bucket.
The upload process is as follows:

  1. The user assumes a RAM role for Read and Write OSS Access for a specific folder in Alibaba Cloud by calling AssumeRole.

  2. STS returns a set of temporary security credentials.

  3. The user applies the temporary security credentials to access OSS. The user can then make a read or write call on the object.

We take OSS as an example here. However, STS can be used to grant temporary access to a wide range of Alibaba Cloud services. In this tutorial, we use fine-grained STS permission to limit access to a specific OSS bucket.

Implementation

Three files in the sample code are as follows:

  • sts.py
    This is the code for assuming the role and to retrieve essential information such as accessKeyId, accessKeySecret, and securityToken.

    The available functions are as follows:

    • Generate signatures to guarantee request authenticity
    • Get HTTPS requests

The example code for file “sts.py” is as follows:

  1. from base64 import b64encode
  2. from datetime import datetime
  3. from Crypto.Hash import SHA, HMAC
  4. import md5, httplib, urllib, uuid, json
  5. ##### CONFIG MANAGEMENT
  6. accessKeyId = "<access_key_id>"
  7. accessKeySecret = "<access_key_secret>"
  8. ##### FUNCTION MANAGEMENT
  9. def generateSignature(accessKeySecret, stringToSign):
  10. hmac = HMAC.new(accessKeySecret, stringToSign, SHA)
  11. return b64encode(hmac.digest())
  12. def getHttpsRequest(host, verb, path):
  13. conn = httplib.HTTPSConnection(host)
  14. conn.request(verb, path)
  15. return conn.getresponse()
  16. # ###### STS MANAGEMENT
  17. host = "sts.aliyuncs.com"
  18. verb = "GET"
  19. bucketName = "<bucket_name>"
  20. folderName = "1"
  21. policy = '{"Statement": [{"Effect": "Allow","Action": ["oss:*"],"Resource": ["acs:oss:*:*:' + bucketName + '/' + folderName + '","acs:oss:*:*:' + bucketName + '/' + folderName + '/*"]}],"Version": "1"}'
  22. dictionaryParams = {
  23. "AccessKeyId": accessKeyId,
  24. "Action": "AssumeRole",
  25. "DurationSeconds": "3600",
  26. "Format": "JSON",
  27. "Policy": policy,
  28. "RoleArn": "acs:ram::5081099437682835:role/ramtestossreadwrite",
  29. "RoleSessionName": "<session_name>",
  30. "SignatureMethod": "HMAC-SHA1",
  31. "SignatureNonce": str(uuid.uuid1()),
  32. "SignatureVersion": "1.0",
  33. "Timestamp": datetime.strftime(datetime.utcnow(), "%Y-%m-%dT%H:%M:%SZ"),
  34. "Version": "2015-04-01"
  35. }
  36. stringToSign = ""
  37. for key in sorted(dictionaryParams.iterkeys()):
  38. value = urllib.quote(dictionaryParams[key], safe="")
  39. if stringToSign != "":
  40. stringToSign += "&"
  41. stringToSign += key + "=" + value
  42. stringToSign = verb + "&%2F&" + urllib.quote(stringToSign)
  43. signature = generateSignature(accessKeySecret + "&", stringToSign)
  44. dictionaryParams["Signature"] = signature
  45. params = urllib.urlencode(dictionaryParams)
  46. path = "/?" + params
  47. response = getHttpsRequest(host, verb, path)
  48. if response.status == 200:
  49. jsonData = json.loads(response.read())
  50. print "Copy paste the respective information to file ossrest.py\n"
  51. print "accessKeyId: " + jsonData['Credentials']['AccessKeyId']
  52. print "accessKeySecret: " + jsonData['Credentials']['AccessKeySecret']
  53. print "securityToken: " + jsonData['Credentials']['SecurityToken']
  • ossrest.py
    This is the code to upload and delete the object.

    The available functions are as follows:

    • Generate signatures
    • Generate headers
    • Make HTTP requests
    • Upload objects
    • Delete objects

The example code for file “ossrest.py” is as follows:

  1. from base64 import b64encode
  2. from datetime import datetime
  3. from Crypto.Hash import SHA, HMAC
  4. import md5, httplib, urllib, uuid
  5. ##### MAIN CONFIG (STS)
  6. accessKeyId = "<access_key_id>"
  7. accessKeySecret = "<access_key_secret>"
  8. securityToken = "<security_token>"
  9. ##### FUNCTION MANAGEMENT
  10. def generateSignature(accessKeySecret, stringToSign):
  11. hmac = HMAC.new(accessKeySecret, stringToSign, SHA)
  12. return b64encode(hmac.digest())
  13. def generateHeaders(verb, canonicalizedResource = "/", canonicalizedOSSHeaders = {}, signature = {}):
  14. # authorization
  15. stringToSign = verb + "\n"
  16. if "content" in signature:
  17. stringToSign += md5.new(signature["content"]).digest()
  18. stringToSign += "\n"
  19. if "content_type" in signature:
  20. stringToSign += signature["content_type"]
  21. stringToSign += "\n"
  22. date = datetime.strftime(datetime.utcnow(), "%a, %d %b %Y %H:%M:%S GMT")
  23. stringToSign += date + "\n"
  24. if len(canonicalizedOSSHeaders):
  25. for index, value in canonicalizedOSSHeaders.items():
  26. stringToSign += index.lower() + ":" + value + "\n"
  27. stringToSign += canonicalizedResource
  28. signature = generateSignature(accessKeySecret, stringToSign)
  29. # headers
  30. headers = {"Date": date, "Authorization": "OSS " + accessKeyId + ":" + signature}
  31. headers.update(canonicalizedOSSHeaders)
  32. return headers
  33. def sendHttpsRequest(host, verb, headers, path = "/", params = ""):
  34. conn = httplib.HTTPSConnection(host)
  35. conn.request(verb, path, params, headers)
  36. return conn.getresponse()
  37. ##### OBJECT MANAGEMENT
  38. canonicalizedOSSHeaders = {"x-oss-acl": "public-read", "x-oss-security-token": securityToken}
  39. bucketName = "<bucket_name>"
  40. host = bucketName + ".oss-ap-southeast-1.aliyuncs.com"
  41. hostMain = "oss-ap-southeast-1.aliyuncs.com"
  42. folderName = "1"
  43. fileName = "<filename>"
  44. ### UPLOAD OBJECT
  45. verb = "PUT"
  46. canonicalizedResource = "/" + bucketName + "/" + folderName + "/" + fileName
  47. headers = generateHeaders(verb, canonicalizedResource, canonicalizedOSSHeaders)
  48. response = sendHttpsRequest(host, verb, headers, "/" + folderName + "/" + fileName, open(fileName, "rb"))
  49. print "Successfully uploaded " + fileName + " object to " + bucketName + "/" + folderName + " bucket/folder."
  50. print response.status, response.reason
  51. print response.read()
  52. ### DELETE OBJECT
  53. verb = "DELETE"
  54. canonicalizedResource = "/" + bucketName + "/" + folderName + "/" + fileName
  55. headers = generateHeaders(verb, canonicalizedResource, canonicalizedOSSHeaders)
  56. response = sendHttpsRequest(host, verb, headers, "/" + folderName + "/" + fileName)
  57. print "Successfully deleted " + fileName + " object."
  58. print response.status, response.reason
  59. print response.read()
  • other_sample.py
    This is the code for other scenarios. These samples may not be directly applicable to STS, but are provided as examples.

    The available functions are as follows:

    • Create buckets
    • List buckets
    • Upload objects
    • List objects
    • Delete objects
    • Delete buckets

The example code for file “other_sample.py” is as follows:

  1. bucketName = "<bucket_name>"
  2. host = bucketName + ".oss-ap-southeast-1.aliyuncs.com"
  3. fileName = "<file_name>"
  4. ### CREATE BUCKET
  5. verb = "PUT"
  6. signature = {}
  7. canonicalizedResource = "/" + bucketName + "/"
  8. headers = generateHeaders(verb, signature, canonicalizedResource, canonicalizedOSSHeaders)
  9. response = sendRequest(host, verb, headers)
  10. print "Successfully created " + bucketName + " bucket."
  11. print response.status, response.reason
  12. print response.read()
  13. ### LIST BUCKET
  14. host = "oss-ap-southeast-1.aliyuncs.com"
  15. verb = "GET"
  16. signature = {}
  17. canonicalizedResource = "/"
  18. headers = generateHeaders(verb, signature, canonicalizedResource, canonicalizedOSSHeaders)
  19. response = sendRequest(host, verb, headers)
  20. print "Successfully listed buckets."
  21. print response.status, response.reason
  22. print response.read()
  23. ### UPLOAD OBJECT
  24. verb = "PUT"
  25. signature = {}
  26. canonicalizedResource = "/" + bucketName + "/" + fileName
  27. headers = generateHeaders(verb, signature, canonicalizedResource, canonicalizedOSSHeaders)
  28. response = sendRequest(host, verb, headers, "/" + fileName, open(fileName, "rb"))
  29. print "Successfully uploaded " + fileName + " object to " + bucketName + " bucket."
  30. print response.status, response.reason
  31. print response.read()
  32. ### LIST OBJECT
  33. verb = "GET"
  34. signature = {}
  35. canonicalizedResource = "/" + bucketName + "/"
  36. headers = generateHeaders(verb, signature, canonicalizedResource, canonicalizedOSSHeaders)
  37. response = sendRequest(host, verb, headers)
  38. print "Successfully listed objects in " + bucketName + " bucket."
  39. print response.status, response.reason
  40. print response.read()
  41. ### DELETE OBJECT
  42. verb = "DELETE"
  43. signature = {}
  44. canonicalizedResource = "/" + bucketName + "/" + fileName
  45. headers = generateHeaders(verb, signature, canonicalizedResource, canonicalizedOSSHeaders)
  46. response = sendRequest(host, verb, headers, "/" + fileName)
  47. print "Successfully deleted " + fileName + " object."
  48. print response.status, response.reason
  49. print response.read()
  50. ### DELETE BUCKET
  51. verb = "DELETE"
  52. signature = {}
  53. canonicalizedResource = "/" + bucketName + "/"
  54. headers = generateHeaders(verb, signature, canonicalizedResource, canonicalizedOSSHeaders)
  55. response = sendRequest(host, verb, headers)
  56. print "Successfully deleted " + bucketName + " bucket."
  57. print response.status, response.reason
  58. print response.read()

The expected responses are as follows:

  • sts.py
    2
  • ossrest.py
    3

Conclusion

This example focuses on OSS, but the STS service can be used to control access to other Alibaba Cloud services as well. The use case we describe in this tutorial is gaming. Other scenarios or services which require short-term access to OSS may include:

  • Web applications
  • Mobile applications

Additional Information

Thank you! We've received your feedback.