AWS STS Temporary Credentials S3 Access Denied PutObject

0

I am following https://www.2ndwatch.com/blog/use-aws-iam-sts-access-aws-resources/ blog posting and my understanding is the S3 Bucket Policy Principal requesting the temporary credentials, one approach would be to hard code the Id of this User but the post attempts a more elegant approach of evaluating the STS delegated user (when it works).

arn:aws:iam::409812999999999999:policy/fts-assume-role

IAM user policy

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

arn:aws:s3:::finding-taylor-swift

s3 bucket policy

{
    "Version": "2012-10-17",
    "Id": "Policy1581282599999999999",
    "Statement": [
        {
            "Sid": "Stmt158128999999999999",
            "Effect": "Allow",
            "Principal": {
                "Service": "sts.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::finding-taylor-swift/*"
        }
    ]
}

conor@xyz:~$ aws configure --profile finding-taylor-swift
AWS Access Key ID [****************6QNY]: 
AWS Secret Access Key [****************+8kF]: 
Default region name [eu-west-2]: 
Default output format [text]: json
conor@xyz:~$ aws sts get-session-token --profile finding-taylor-swift
{
    "Credentials": {
        "SecretAccessKey": "<some text>", 
        "SessionToken": "<some text>", 
        "Expiration": "2020-02-11T03:31:50Z", 
        "AccessKeyId": "<some text>"
    }
}
conor@xyz:~$ export AWS_SECRET_ACCESS_KEY=<some text>
conor@xyz:~$ export AWS_SESSION_TOKEN=<some text>
conor@xyz:~$ export AWS_ACCESS_KEY_ID=<some text>
conor@xyz:~$ aws s3 cp dreamstime_xxl_concert_profile_w500_q8.jpg s3://finding-taylor-swift
upload failed: ./dreamstime_xxl_concert_profile_w500_q8.jpg to s3://finding-taylor-swift/dreamstime_xxl_concert_profile_w500_q8.jpg An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
conor@xyz:~$

AWS CLI has been setup as described https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html#using-temp-creds-sdk-cli

"When you run AWS CLI commands, the AWS CLI looks for credentials in a specific order—first in environment variables and then in the configuration file. Therefore, after you've put the temporary credentials into environment variables, the AWS CLI uses those credentials by default. (If you specify a profile parameter in the command, the AWS CLI skips the environment variables. Instead, the AWS CLI looks in the configuration file, which lets you override the credentials in the environment variables if you need to.)

The following example shows how you might set the environment variables for temporary security credentials and then call an AWS CLI command. Because no profile parameter is included in the AWS CLI command, the AWS CLI looks for credentials first in environment variables and therefore uses the temporary credentials."

So far SO has only suggested using assume-role

https://stackoverflow.com/questions/60153869/aws-sts-temporary-credentials-s3-access-denied-putobject

C9n7r
asked 4 years ago1345 views
1 Answer
0

kindly answered here https://stackoverflow.com/questions/60153869/aws-sts-temporary-credentials-s3-access-denied-putobject?noredirect=1#comment106405650_60153869

There is no need to use a Bucket Policy for your scenario. A bucket policy is applied to an Amazon S3 bucket and is typically used to grant access that is specific to the bucket (eg public access).

Using an IAM Role

If you wish to provide bucket access to a specific IAM User, IAM Group or IAM Role, then the permissions should be attached to the IAM entity rather than the bucket.

(For get-session-token, see the end of my answer.)

Setup

Let's start by creating an IAM Role similar to what you had. I choose Create role, then for trusted entity I select Another AWS account (since it will be assumed by an IAM User rather than service).

I then create an Inline policy on the IAM Role to permit access to the bucket:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::my-bucket"
        }
    ]
}

(It's normally not a good idea to assign s3:* permissions, since this lets the user delete content and even delete the bucket. Try to restrict it to the minimum permissions that are actually required.)

The Trust Relationship on the IAM Role determines who is allowed to assume the role. It could be one person, or anyone in the account (as long as they have been granted permission to call AssumeRole). In my case, I'll assign it to the whole account:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::MY-ACCOUNT-ID:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Now there are a few different ways to assume the role...

Simple method: IAM Role in credentials file

The AWS CLI has the ability to specify an IAM Role in the credentials file, and it will automatically assume the role for you.

See: Using an IAM Role in the AWS CLI https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html

To use this, I add a section to my .aws/config file:

[profile foo]
role_arn = arn:aws:iam::MY-ACCOUNT-ID:role/MY-ROLE-NAME
source_profile = default

I could then simply use it with:

aws s3 ls s3://my-bucket --profile foo

This successfully lets me access that specific bucket.

Complex method: Assume the role myself

Rather than letting the AWS CLI do all the work, I can also assume the role myself:

aws sts assume-role --role-arn arn:aws:iam::MY-ACCOUNT-ID:role/MY-ROLE-NAME --role-session-name foo

{
    "Credentials": {
        "AccessKeyId": "ASIA...",
        "SecretAccessKey": "...",
        "SessionToken": "...",
        "Expiration": "2020-02-11T00:43:30+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "AROA...:foo",
        "Arn": "arn:aws:sts::MY-ACCOUNT-ID:assumed-role/MY-ROLE-NAME/foo"
    }
}

I then appended this information to the .aws/credentials file:

[foo2]
aws_access_key_id = ASIA...
aws_secret_access_key = ...
aws_security_token= ...

Yes, you could add this to the credentials file by using aws configure --foo2, but it does not prompt for the Security Token. Therefore, you need to edit the credentials file to add that information anyway.

I then used the profile:

aws s3 ls s3://my-bucket --profile foo2

It allowed me to successfully access and use the bucket.

Using GetSessionToken

The above examples use an IAM Role. This is typically used to grant cross-account access or to temporarily assume more-powerful credentials (eg an Admin performing sensitive operations).

Your Question references get-session-token. This provides temporary credentials based on a user's existing credentials and permissions. Thus, they cannot gain additional permissions as part of this API call.

This call is typically used either to supply an MFA token or to provide time-limited credentials for testing purposes. For example, I could give you credentials that effectively let you use my IAM User, but only for a limited time.

C9n7r
answered 4 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions