Creating STS tokens for federated users from a C# .NET application running on an Amazon EC2 instance that's been assigned an IAM Role

StackOverflow https://stackoverflow.com/questions/19552659

Question

I have an Amazon EC2 instance running a server that needs to provide federated access to S3 resources for its clients (windows 7/8, iPad, among others). So far, I've created the following:

  • An IAM role that limits the access the server has to S3 resources and other Amazon web services.
  • An IAM User with the ability to use STS services, namely GetFederationToken.

Typically, the clients will request access to get or put objects into S3, never delete. So in the case of putting files, rather than having the client upload the file to the server and then forwarding it to S3 from the server, I would like to provide temporary access credentials for the client to put the file into the appropriate S3 bucket directly.

Here is what the EC2 instance IAM role looks like:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": "arn:aws:s3:::devtestbucket/*"
    },
    {
      "Effect": "Allow",
      "Action": [ "sqs:*" ],
      "Resource": "arn:aws:sqs:us-west-2::dev-*"      
    },
    {
      "Effect": "Allow",
      "Action": [ "dynamodb:*" ],
      "Resource": "arn:aws:dynamodb:us-west-2::dev-*"      
    },
    {
      "Effect": "Allow",
      "Action": [ "sts:*" ],
      "Resource": "*"      
    }
  ]
}

And the STS Token Issuer IAM User policy is:

{
  "Statement": [
    {
      "Action": [
        "sts:GetFederationToken"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:sts:::federated-user/*"
      ]
    },
    {
      "Action": [
        "s3:*"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::devtestbucket"
      ]
    }
  ]
}

In my server side code, I create the STS client, federation token request and make the GetFederationToken call as follows:

    var stsClient = new AmazonSecurityTokenServiceClient(stsTokenIssuerAwsAccessKeyId, stsTokenIssuerAwsSecretAccessKey);

    var request = new GetFederationTokenRequest
    {
        Name = GenerateIamFederatedUserName(),  // I know this is correct
        DurationSeconds = (int)TimeSpan.FromHours(6).TotalSeconds,
        Policy = GenerateSTSPolicy(objectPrefix, permittedActions) // This works as expected too
    };


    var fedTokenResponse = stsClient.GetFederationToken(request);

I cannot share the implementations of the Generate* functions, but I know those work.

Here is the strange thing. If I use IAM user credentials that are tied to a user with an access policy that looks exactly like the EC2 instance role shown above, everything works as expected and clients are able to perform all expected S3 actions.

So with all this background, my questions are: Can an application on an EC2 instance that has been given a specific role still provide federated access to its clients? If so, are the above policies correct for granting the application access to those AWS actions, namely requesting and serving sts federated tokens that can access S3 resources? If not, how should they be modified to allow such access?

Was it helpful?

Solution

To get this scenario working, I had to separate the STS GetFederationToken portion of the policy into its own policy. So, there had to be 2 policies, one for STS and one for other AWS services:

STS policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "sts:GetFederationToken"
      ],
      "Sid": "Stmt1382573256000",
      "Resource": [
        "*"
      ],
      "Effect": "Allow"
    }
  ]
}

S3 access policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:List*"
      ],
      "Sid": "Stmt1382573312476",
      "Resource": [
        "arn:aws:s3:::devtestbucket"
      ],
      "Effect": "Allow"
    },
    {
      "Action": [
        "s3:*"
      ],
      "Sid": "Stmt1382573312000",
      "Resource": [
        "arn:aws:s3:::devtestbucket/*"
      ],
      "Effect": "Allow"
    }
  ]
}

Not sure exactly why this is the case. If anyone can explain the reason behind why there needs to be two policies instead of one, it'd be great know.

Hope this helps someone.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top