Amazon Web Services and Platform as a Service: IAM and the Secure Token Service

Written by: Hannah Inman

One of the interesting things about the Token Vending Machine architecture is how it interacts with the AWS Identity and Access Management (IAM) infrastructure and the Secure Token Service (STS) in particular. You'll find more detail about both IAM and STS in the Identity and Access Management Documentation . Amazon's documentation for the Anonymous and Identity TVM projects has step-by-step instructions for setting up the IAM user and group accounts: you'll find all the details here (for the Anonymous TVM) and here (for the Identity TVM), although a few screens seem to have evolved slightly since those articles were written. Rather than simply repeat what's described there, I'll try to give an overview of how it all works, to help you explore the examples. First, let's understand the key concepts behind the Token Vending Machine service.

Both the Anonymous and the Identity versions of the TVM have a similar role: they provide services to allow mobile clients to access AWS resources using temporary credentials provided using the Amazon STS service. The difference between the two is that the Anonymous TVM allows anonymous clients to obtain a STS token by registering a device UDID, whereas the Identity TVM requires the mobile user to login with a username/password. The device UDID and user/password information are stored in an Amazon SDB domain.

Token Vending Machine Services

Both the Anonymous and Identity TVMs support a service to allow clients to request an STS token:

< servlet-mapping>
    < servlet-name> GetTokenServlet servlet-name >
     < url-pattern> /gettoken/* url-pattern>
   servlet-mapping>   

The Anonymous TVM supports an additional service to allow clients to register their device UDID:

< servlet-mapping>
    < servlet-name> RegisterDeviceServlet servlet-name >
     < url-pattern> /registerdevice/* url-pattern>
   servlet-mapping>   

The Identity TVM supports the following additional services to allow user registration and login:

< servlet-mapping>
< servlet-name> RegisterUserServlet servlet-name >
< url-pattern> /registeruser/* url-pattern>
servlet-mapping>

< servlet-mapping>
< servlet-name> LoginServlet servlet-name >
< url-pattern> /login/* url-pattern>
servlet-mapping>

Identity Management and Access Permissions

The main idea is to create an AWS user with specific permissions to access your account based on a custom Security Policy Document. This allows you to control the permissions that client applications using the Secure Token Service will inherit; for particular clients, you can limit those permissions still further with their own Policy Documents but these have to be subsets of the Policy you set for the account that is used to issue the STS token.

For this example, you'll need to create a new user account (called TVMUser , following the Amazon documentation) and apply a Policy Document to that user; the TVM service will run the Access Key and Secure Key for TVMUser and so this creates an upper bound on the permissions that any client using the TVM service can inherit. Here's the Policy Document for the TVM demo - it's very open, but of course for real-life applications you would fine-tune this to allow a more restricted set of permissions:

{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:GetFederationToken",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iam:GetUser",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "sdb:*",
      "Resource": "*"
    },
    {
      "Effect":"Allow",
      "Action":"dynamodb:*",
      "Resource":"*"
    },
    {
      "Effect": "Allow",
      "Action": "sqs:*",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    },
    {
      "Action": "sns:*",
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

You can find more detail of how the Policy Documents work in the Key Concepts section of the AWS IAM documentation: this AWS Policy Generator tool is a good place to start exploring these concepts and it has a number of example policies as well.

The Anonymous and Identity TVM servers contain an example of a more restricted policy document (TokenVendingMachinePolicy.json ): it restricts access to the SDB domains used by the TVM servers as well as all IAM resources. To see how it is used to restrict the access permissions associated with the STS token, take a look at the TemporaryCredentialManagement class in the com.amazonaws.tvm package.

IAM User and Group Configuration

To run the TVM examples, follow the instructions in Running the Sample to set up a new IAM Group (TVMProject ) with a user (TVMUser ), using the AWS Management Console. The same user/group configuration can be used for both Identity and Anonymous TVM projects. The Policy Document is set at the group level in this example, as shown below:

TVM Server Configuration Parameters

The following config parameters need to be set for the Anonymous and Identity TVM servers. In each case, the process instance must be restarted in order to pick up the new configuration:

Anonymous TVM

<i>bees config:set -a aws-cb-tvm-anonymous AWS_ACCESS_KEY_ID=<tvmuser_accesskey></tvmuser_accesskey> </i> 
<i>bees config:set -a aws-cb-tvm-anonymous AWS_SECRET_KEY=</i> 

Identity TVM

<i>bees config:set -a aws-cb-tvm-identity AWS_ACCESS_KEY_ID=<tvmuser_accesskey></tvmuser_accesskey> </i> 
<i>bees config:set -a aws-cb-tvm-identity AWS_SECRET_KEY=<tvmuser_secretkey></tvmuser_secretkey> </i> 
<i>bees config:set -a aws-cb-tvm-identity PARAM1=aws-cb-tvm-demo</i> 

CloudBees SDK Commands

<i>bees app:instance:list -a mqprichard/aws-cb-tvm-identity</i> 
<i>bees app:instance:list -a mqprichard/aws-cb-tvm-anonymous</i> 

<i>bees app:hibernate -f -a mqprichard/aws-cb-tvm-anonymous</i> 
<i>bees app:hibernate -f -a mqprichard/aws-cb-tvm-identity</i> 

<i>bees app:restart -f -a mqprichard/aws-cb-tvm-anonymous</i> 
<i>bees app:restart -f -a mqprichard/aws-cb-tvm-identity</i> 

<i>bees app:info -a mqprichard/aws-cb-tvm-anonymous</i> 
<i>bees app:info -a mqprichard/aws-cb-tvm-identity</i> 

Note that you can verify the URL on which the service is running (it will default to port 80, or 443 if you have configured it to run with SSL - I won't do that here) using the bees app:info command.

TVM Client Configuration Parameters

It's important that the URL for the Token Vending Machine service (and the APPNAME if you are using the Identity TVM) are set correctly in the mobile client configuration: these need to match the configuration parameters that the TVM service was started with, as they are used to form a signature sent with requests from the mobile client to the TVM and you will see errors if these don't match. These settings should work with the example TVM service shown above - change the URL to use your CloudBees account name as shown by the _bees app:info command

Anonymous TVM - Android (AwsCredentials.properties)

tokenVendingMachineURL= aws -cb -tvm -anonymous.mqprichard.cloudbees.net
  useSSL= false  

Anonymous TVM - iOS (Constants.h)

#define TOKEN_VENDING_MACHINE_URL     @ "aws-cb-tvm-anonymous.mqprichard.cloudbees.net"
   #define USE_SSL     NO  

Identity TVM - Android (AwsCredentials.properties)

tokenVendingMachineURL=aws - cb - tvm -identity.mqprichard.cloudbees.net
   appName= aws -cb -tvm -demo
  useSSL=false   

Identity TVM - iOS (Constants.h)

#define TOKEN_VENDING_MACHINE_URL     @ "aws-cb-tvm-identity.mqprichard.cloudbees.net"
 #define APP_NAME     @"aws-cb-tvm-demo"
  #define USE_SSL     NO 

Inspecting the TVM Service Requests

In this and the following screenshot, I am using the Eclipse ADT DDMS perspective to view the LogCat output from the Android client. There will be quite a large number of messages, even if you filter with app:com.amazonaws.demo.anonymous , so I have used tag:AmazonClientManager to show the credential checking and renewal process: you will see this when you first use the mobile client and you can easily simulate credential expiry by clearing the emulator state. You can also change the frequency at which a new token must be obtained by editing the STS settings (by default SESSIONDURATION is set to 86400 seconds in _com.amazonaws.tvm.Configuration.java )

Here I'm using the tag:TokenVendingMachineService filter: this shows the "handshake"between the client and the Token Vending Machine service on the CloudBees PaaS. In the LogCat output you can see the registerdevice and gettoken calls to the TVM service.

Finally, let's take a look at the token returned by the STS service: for this, I'll use the Android emulator with the Identity TVM mobile client. The application stores the device ID/key, STS token and access credentials in com.amazonaws.demo.identity.AWSDemo.xml in its Shared Preferences folder. You can easily download the file using the DDMS perspective in Eclipse - open the File Explorer tab as shown and browse to /data/data/com.amazonaws.tvm.identity/shared_prefs and click on the "Pull files from the device button". Here's a screenshot of that from my own system:

If you do that and then take a look at AWSDemo.xml , you'll be able to see the device information for the emulator, as well as the AWS Security Token with its expiration date.

In the next blog, I'll take a quick look at the iOS/Android mobile clients (from the respective Amazon SDKs) that go with the TVMdemo service and then we'll wrap up by looking at some examples of the TVMservice in action.

Mark Prichard, Senior Director of Product Management

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.