2

I am trying to upload a file in S3 by AWS Assume Role. When I am trying to access it from CLI it works fine but from .Net SDK it gives me Access Denied error.

Here are the steps I followed in CLI -

  1. Setup the access key/secret key for user using aws configure
  2. Assume the Role - “aws sts assume-role --role-arn "arn:aws:iam::1010101010:role/Test-Account-Role" --role-session-name AWSCLI-Session”
  3. Take the access key / secret key / session token from the assumed role and setup an AWS profile. The credentials are printed out/returned from the assumed role.
  4. Switch to the assume role profile: “set AWS_PROFILE=”
  5. Verify that the user has the role: “aws sts get-caller-identity”
  6. Access the bucket using ls or cp or rm command - Works Successfully.

Now I am trying to access it from .Net core App -

Here is the code snippet- Note that I am using same Access and Secret key as CLI from my local.

        try
        {
            var region = RegionEndpoint.GetBySystemName(awsRegion);

            SessionAWSCredentials tempCredentials = await GetTemporaryCredentialsAsync(awsAccessKey, awsSecretKey, region, roleARN);

            //Use the temp credentials received to create the new client
            IAmazonS3 client = new AmazonS3Client(tempCredentials, region);
            
            TransferUtility utility = new TransferUtility(client);
            // making a TransferUtilityUploadRequest instance
            TransferUtilityUploadRequest request = new TransferUtilityUploadRequest
            {
                BucketName = bucketName, 
                Key = $"{subFolder}/{fileName}", 
                FilePath = localFilePath 
            utility.Upload(request); //transfer
            fileUploadedSuccessfully = true;

        }
        catch (AmazonS3Exception ex)
        {
            // HandleException
        }
        catch (Exception ex)
        {
             // HandleException
        }

The method to get temp credentials is as follow - GetTemporaryCredentialsAsync

  private static async Task<SessionAWSCredentials> GetTemporaryCredentialsAsync(string awsAccessKey, string awsSecretKey, RegionEndpoint region, string roleARN)
        {
            using (var stsClient = new AmazonSecurityTokenServiceClient(awsAccessKey, awsSecretKey, region))
            {

                var getSessionTokenRequest = new GetSessionTokenRequest
                {
                    DurationSeconds = 7200
                };

                await stsClient.AssumeRoleAsync(
                    new AssumeRoleRequest()
                    {
                        RoleArn = roleARN,
                        RoleSessionName = "mySession"
                    });

                GetSessionTokenResponse sessionTokenResponse =
                              await stsClient.GetSessionTokenAsync(getSessionTokenRequest);

                Credentials credentials = sessionTokenResponse.Credentials;

                var sessionCredentials =
                    new SessionAWSCredentials(credentials.AccessKeyId,
                                              credentials.SecretAccessKey,
                                              credentials.SessionToken);
                return sessionCredentials;
            }
        }

I am getting back the temp credentials but it gives me Access Denied while uploading the file. Not sure if I am missing anything here.

Also noted that the token generated via SDK is shorter than that from CLI. I tried pasting these temp credentials to local profile and then tried to access the bucket and getting the Access Denied error then too.

mahesh_ing
  • 419
  • 1
  • 3
  • 10

1 Answers1

3

There is an AWS .NET V3 example that shows this exact use case. To assume a role, you use an AmazonSecurityTokenServiceClient. In this example, the user assumes the role that allows the role to be used to list all S3 buckets. See this .NET scenario here.

https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/dotnetv3/IAM/Scenarios/IAMBasics/IAMBasics.cs

Foggzie
  • 9,691
  • 1
  • 31
  • 48
smac2020
  • 9,637
  • 4
  • 24
  • 38
  • Thanks. The above article is suggesting to create all the resources on each request and clean them once we are done with it. Is this mandatory to do the same? Or we can have already created user, role, policy and just assume the role. If you look at the question I am doing the same. – mahesh_ing Jun 14 '22 at 04:56
  • Look at the code that assume a roles. Other code is optional – smac2020 Jun 14 '22 at 11:43
  • I have a same code. But it gives me Access Denied. It generates temp credentials but looks like they are not valid. Do you see any issue with my code? – mahesh_ing Jun 14 '22 at 12:04
  • The code examples clean up all resources to avoid incurring charges on the account of anyone who implements the code. – Irene Jun 14 '22 at 13:50
  • 2
    I noticed, by the way, that you are not using the Credentials in the response to the AssumeRoleAsync call. In the example, the Credentials are used to create the S3 client object. Try that and see if it works for you. – Irene Jun 14 '22 at 13:59
  • 1
    You are right. I did mess up that. Thanks for pointing out that. – mahesh_ing Jun 15 '22 at 18:38
  • @mahesh_ing Did you find a resolution to your issue through the .NET scenario example? – Ben BearFish Aug 09 '23 at 23:47