skip to Main Content

I am tried enabling the snapstart for my lambda function which just uses a simple java AWS SDK to connect to just a put a message to the queue. Without the snapstart the code works fine, however when its enabled, I get this error

Error while submitting the message with exception :Unable to load AWS credentials from any provider in the chain

I have attached the full access policy for the SQS and its working fine without the snapstart.

final Map<String, MessageAttributeValue> messageAttributes = new HashMap<>();
messageAttributes.put("testID", new MessageAttributeValue().withStringValue("id123").withDataType("String"));
final AmazonSQS sqs = AmazonSQSClientBuilder.standard().withRegion(Regions.EU_WEST_1).build();
final SendMessageRequest sendMessageStandardQueue = new SendMessageRequest().withQueueUrl("https://sqs.eu-west-1.amazonaws.com/111111/my-queue")
        .withMessageBody("Test message from lambda")
        .withMessageAttributes(messageAttributes);
sqs.sendMessage(sendMessageStandardQueue);

This code works fine without enabling snapstart on the lambda function. After enabling snapstart, I just added the following on the code.

 @Override
    public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception {
        System.out.println("Before Checkpoint");
    }

    @Override
    public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception {
        System.out.println("After Restore");
    }

Would you please help me to understand why exactly is it unable to load the credentials. ?

3

Answers


  1. If you are relying on the AWS SDK’s Environment Credentials Provider, then a rehydrated SnapStart Lambda Function will not find the AWS credentials. Per Using SnapStart with the AWS SDKs:

    When SnapStart is activated, the Java runtime automatically uses the container credentials (AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN) instead of the access key environment variables. This prevents credentials from expiring before the function is restored.

    So, I think this means:

    1. always provide IAM credentials to your Lambda function via an IAM role
    2. ensure that your code uses the default credentials provider chain

    If that isn’t the issue, then try to determine if your Lambda function relies on state that is not resilient to snapshot and restore operations. Consider using the AWS Lambda SnapStart Bug Scanner to investigate further.

    In particular, the compatibility considerations include:

    Temporary data

    Some functions download or initialize ephemeral data, such as temporary credentials or cached timestamps, during the initialization phase. Refresh ephemeral data in the function handler before using it, even when not using SnapStart.

    Also, a few restrictions at launch per the blog post:

    • it currently supports Java only and specifically the Corretto (java11) runtime
    • you cannot use Lambda SnapStart with larger ephemeral storage, Elastic File Systems, Provisioned Concurrency, or Graviton2
    • cached snapshots are removed after 14 days of inactivity
    Login or Signup to reply.
  2. For Snapstart environment, we will be using Container Credentials for SDK; for a normal Lambda environment, we can use Environment Credentials for SDK. One way to figure out which environment we are in is to check the container URI:

    public AwsCredentialsProvider provideAwsCredentials()
    return System.getenv("AWS_CONTAINER_CREDENTIALS_FULL_URI") == null ?
                    EnvironmentVariableCredentialsProvider.create() : ContainerCredentialsProvider.builder().build();
    
    Login or Signup to reply.
  3. How to place it working?

    Using AWS SDK v2:

    SqsClient sqs = SqsClient.builder()
        .credentialsProvider(SdkSystemSetting.AWS_CONTAINER_CREDENTIALS_FULL_URI
                                             .getStringValue()
                                             .isPresent()
            ? ContainerCredentialsProvider.builder().build()
            : EnvironmentVariableCredentialsProvider.create())
        .region(Region.of(SdkSystemSetting.AWS_REGION.getStringValueOrThrow()))
        .build();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search