'How to Create Presigned S3 URL with a 72 Hour TTL

So far, I am only able to create a pre-resigned URL that is valid for 1 hour.

I tried increasing the duration of the presaged URL to 72 hours directly, but the temporary token that is associated with the URL expires after 1 hour. I know that tokens generated through an IAM role have a maximum duration of 12 hours, but I really need this pre-signed URL to last for 72 hours.

I tried implementing something similar to:

https://github.com/aws/aws-sdk-java/issues/2681

but keep getting an InvalidAccessKeyIdThe AWS Access Key Id you provided does not exist in our records error from AWS after I click on the generated pre-signed URL.

I've read about the AWS Signature Version 4 means to allow the credentials to live for up to 7 days, but would preferably like to implement this as done in the GitHub link I sent above.

Here is some of the logic I have so far (condensed into one block for simplicity)

    AWSSecurityTokenServiceClient stsClient = (AWSSecurityTokenServiceClient) AWSSecurityTokenServiceClientBuilder.defaultClient();
    AssumeRoleWithWebIdentityRequest request = new AssumeRoleWithWebIdentityRequest()
        .withDurationSeconds(43200) // 12 hours is the max.
        .withRoleArn(iam)
        .withWebIdentityToken("file://" + System.getenv("AWS_WEB_IDENTITY_TOKEN_FILE")) // Not sure about this logic here
        .withRoleSessionName("aws-sdk-java-" + System.currentTimeMillis());
    AssumeRoleWithWebIdentityResult result = stsClient.assumeRoleWithWebIdentity(request);
    basicSessionCredentials = new    BasicSessionCredentials(result.getCredentials().getAccessKeyId(),
          result.getCredentials().getSecretAccessKey(),
          result.getCredentials().getSessionToken());

    // Calculate expiration date.
    java.util.Date expiration = new java.util.Date();
    long expTimeMillis = Instant.now().toEpochMilli();
    expTimeMillis += 1000 * 60 * 60 * durationHours;
    expiration.setTime(expTimeMillis);

    // Set configurations necessary for S3.
    GeneratePresignedUrlRequest generatePresignedUrlRequest =
        new GeneratePresignedUrlRequest(bucket, key)
            .withMethod(HttpMethod.GET)
            .withExpiration(expiration);

    // Provide custom AWS Credentials that last 72 hours. This means the temporary token is only
    // valid for 72 hours and that the pre-signed URL can't have a TTL longer than 72 hours.
    generatePresignedUrlRequest.withRequestCredentialsProvider(
        new AWSStaticCredentialsProvider(basicSessionCredentials));

    URL presignedURL = amazonS3.generatePresignedUrl(generatePresignedUrlRequest);

I am using Helm Charts to deploy my cluster:

My serviceaccount.yaml file:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ .Release.Name }}
  namespace: {{ .Release.Namespace }}
  labels:
    account: {{ .Release.Name }}
  annotations:
    eks.amazonaws.com/role-arn: {{ .Values.aws.iamRole }}
secrets:
- name: {{ .Release.Name }}-s3-token

deployment.yaml file:

volumes:
...
- name: aws-iam-token
  projected:
    defaultMode: 420
    sources:
    - serviceAccountToken:
      audience: sts.amazonaws.com
      expirationSeconds: 259200
      path: token
...
containers:
  ...
  env:
  - name: AWS_WEB_IDENTITY_TOKEN_FILE
    value: /var/run/secrets/eks.amazonaws.com/sample/token
  volumeMounts:
  - mountPath: /var/run/secrets/eks.amazonaws.com/sample
    name: aws-iam-token
  ...

Supplementary resource:

https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source