aws / aws-sdk-js-v3

Modularized AWS SDK for JavaScript.
Apache License 2.0
3.03k stars 569 forks source link

InvalidSignatureException: Signature expired: 20240820T230143Z is now earlier than 20240820T230302Z (20240820T230802Z - 5 min.) #6400

Open fshuman-a opened 3 weeks ago

fshuman-a commented 3 weeks ago

Checkboxes for prior research

Describe the bug

We recently upgraded to v3 and since then we've seen InvalidSignatureException: Signature expired: 20240820T230143Z is now earlier than 20240820T230302Z (20240820T230802Z - 5 min.) a few times when performing KMS encrypt/decrypt operations. Since the issue is intermittent, it is difficult to replicate it. I noticed another user experienced a similar issue and it appears that using the embedded SDK seems to have worked for that user. However, it is not clear if it's a recommendation from AWS or why we should use the embedded SDK instead.

SDK version number

@aws-sdk/client-kms@3.485.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

18

Reproduction Steps

kmsClient.ts

import { KMS } from '@aws-sdk/client-kms';
const kmsClient = new KMS({})
export const getKMS = (): KMS => {
    return kmsClient
}

encryption.ts

import { getKMS } from './kmsClient.ts'

export const encrypt = async (context: Record<string, string>): Promise<string> => {
    const expiry = 60 * 30;
    const nowSecs = Math.floor(Date.now() / 1000);
    const augmentedContext = {
        ...context,
        exp: nowSecs + expiry
    };
    const response = await getKMS()
        .encrypt({
            KeyId: '<key>',
            Plaintext: Buffer.from(JSON.stringify(augmentedContext))
        });

    if (!response.CiphertextBlob) {
        throw Error('No CiphertextBlob');
    }
    return Buffer.from(response.CiphertextBlob).toString('base64');
};

handler.ts

import { encrypt } from 'encryption';

export const handler = async () => {
    ...
    const encryptedKey = await encrypt({'foo': 'bar'})
    ...
}

Observed Behavior

InvalidSignatureException: Signature expired: 20240820T230143Z is now earlier than 20240820T230302Z (20240820T230802Z - 5 min.)\n at throwDefaultError...

Expected Behavior

No error is thrown

Possible Solution

No response

Additional Information/Context

No response

aBurmeseDev commented 2 weeks ago

Hi @fshuman-a - thanks for reaching out.

The InvalidSignatureException error occurs when the signature used to authenticate the AWS API request has expired. This issue can occur due to a mismatch between the system clocks of the client and the AWS service or if there is a significant delay in the network communication.

Regarding using the embedded SDK, AWS does not explicitly recommend using the embedded SDK over the standalone SDK package. The embedded SDK is a version of the AWS SDK that is bundled with the AWS Lambda execution environment. It is primarily intended for use within Lambda functions, where the Lambda service handles the SDK initialization and configuration.

For applications running outside of the Lambda environment, such as Node.js servers or other compute environments, it is generally recommended to use the standalone SDK package @aws-sdk/client-kmsin your case.


Going back to your specific issue - this occurs exclusively in with AWS Lambda. One recommendation from the SDK team is to incorporate Top Level Await into your application. While this approach is not generally advised, an alternative solution could be to relocate the API calls within the handler function itself.

Here's code example from Using Node.js ES modules and top-level await in AWS Lambda:

import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm"; 

const ssmClient = new SSMClient();
const input = { "Name": "/configItem" }
const command = new GetParameterCommand(input);
const parameter = await ssmClient.send(command); // top-level await

export async function handler() {
    const response = {
        statusCode: 200,
        "body": parameter.Parameter.Value
    };
    return response;
};

Here are related issues reported in this repo, for your reference:

Hope it helps, John