Closed FabulousGinger closed 6 months ago
more details:
updated code
const signedRequest = aws4.sign({
method: request.method,
path: path,
host: hostname,
service: 'lambda',
region: region,
body: request.body.data || '',
headers: {
'Content-Type': 'application/json'
},
extraHeadersToIgnore: {
'content-length': true
}
}, credentials);
This works with no body, fails with body. below are the scrapped results from signedRequest
works with empty body:
{
"method": "POST",
"path": "/log",
"host": "MYLAMBDA.lambda-url.us-west-2.on.aws",
"service": "lambda",
"region": "us-west-2",
"body": "",
"headers": {
"Content-Type": "application/json",
"Host": "MYLAMBDA.lambda-url.us-west-2.on.aws",
"X-Amz-Security-Token": "TOKEN",
"X-Amz-Date": "20240418T173656Z",
"Authorization": "AWS4-HMAC-SHA256 Credential=CREDS/20240418/us-west-2/lambda/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token, Signature=SIGNATURE"
},
"extraHeadersToIgnore": {
"content-length": true
}
}
fails with body:
{
"method": "POST",
"path": "/log",
"host": "MYLAMBDA.lambda-url.us-west-2.on.aws",
"service": "lambda",
"region": "us-west-2",
"body": "eyJjYXQiOiB7ImN1ZGRsZXMiOiAieWVzIiwibGF6eSI6ICJ5ZXMifX0=",
"headers": {
"Content-Type": "application/json",
"Host": "MYLAMBDA.lambda-url.us-west-2.on.aws",
"X-Amz-Security-Token": "TOKEN",
"X-Amz-Date": "20240418T173700Z",
"Authorization": "AWS4-HMAC-SHA256 Credential=CREDS/20240418/us-west-2/lambda/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token, Signature=SIGNATURE"
},
"extraHeadersToIgnore": {
"content-length": true
}
}
I have also added the following, which both fail signature with body and without:
headers: {
'Content-Type': 'application/json',
'X-Amz-Content-Sha256': 'UNSIGNED-PAYLOAD'
},
here is a successful PodMan request, received from the origin bypassing aws4
{
version: '2.0',
routeKey: '$default',
rawPath: '/v1/log',
rawQueryString: '',
headers: {
'x-amz-content-sha256': 'SHA',
'content-length': '15',
'x-amzn-tls-version': 'TLSv1.2',
'x-amz-date': '20240417T171826Z',
'x-forwarded-proto': 'https',
'postman-token': 'TOKEN',
'x-amz-source-account': 'ACCOUNT',
'x-forwarded-port': '443',
'x-forwarded-for': 'IP',
'x-amz-security-token': 'TOKEN',
via: 'NUMBER.cloudfront.net (CloudFront)',
'x-amz-source-arn': 'ARN',
'x-amzn-tls-cipher-suite': 'ECDHE-RSA-AES128-GCM-SHA256',
'x-amzn-trace-id': 'Root=ID',
host: 'MYLAMBDA.lambda-url.us-west-2.on.aws',
'content-type': 'application/json',
'x-amz-cf-id': 'ID',
'user-agent': 'Amazon CloudFront'
},
requestContext: {
accountId: 'ACCOUNT',
apiId: 'ID',
authorizer: { iam: [Object] },
domainName: 'MYLAMBDA.lambda-url.us-west-2.on.aws',
domainPrefix: 'mylambda',
http: {
method: 'POST',
path: '/v1/log',
protocol: 'HTTP/1.1',
sourceIp: 'IP',
userAgent: 'Amazon CloudFront'
},
requestId: '7744eb78-b726-440d-9767-1e8a7789ace3',
routeKey: '$default',
stage: '$default',
time: '17/Apr/2024:17:18:26 +0000',
timeEpoch: 1713374306283
},
body: '{"cat": "lazy"}',
isBase64Encoded: false
}
successful request received from origin with no body using aws4
{
version: '2.0',
routeKey: '$default',
rawPath: '/log',
rawQueryString: '',
headers: {
'content-length': '0',
'x-amzn-tls-version': 'TLSv1.2',
'x-amz-date': '20240418T173656Z',
'x-forwarded-proto': 'https',
'postman-token': 'TOKEN',
'x-forwarded-port': '443',
'x-forwarded-for': 'IP',
'x-amz-security-token': 'TOKEN',
via: 'NUMBER.cloudfront.net (CloudFront)',
'x-amzn-tls-cipher-suite': 'ECDHE-RSA-AES128-GCM-SHA256',
'x-amzn-trace-id': 'Root=ID',
host: 'MYLAMBDA.lambda-url.us-west-2.on.aws',
'content-type': 'application/json',
'x-amz-cf-id': 'ID',
'user-agent': 'Amazon CloudFront'
},
requestContext: {
accountId: 'ACCOUNT',
apiId: 'ID',
authorizer: { iam: [Object] },
domainName: 'MYLAMBDA.lambda-url.us-west-2.on.aws',
domainPrefix: 'mylambda',
http: {
method: 'POST',
path: '/log',
protocol: 'HTTP/1.1',
sourceIp: 'IP',
userAgent: 'Amazon CloudFront'
},
requestId: 'd6db08b7-9d2c-4c03-9c7f-0efa800c74bd',
routeKey: '$default',
stage: '$default',
time: '18/Apr/2024:17:36:56 +0000',
timeEpoch: 1713461816462
},
isBase64Encoded: false
}
content-length
I notice in a few of your examples you're not adding content-length
to the headers list when you have a body – you're just adding content-type
I've looked all through the issues here, however haven't seen something to that quite fits. I have a Lambda@Edge function with an origin request on CloudFront. This will sign the request, return it, and continue to the origin, which is a Lambda function URL. AWS recently released OAC for Lambda, However it still needs a signed payload for
PUT
andPOST
. I was able to sign the request with a JSON body using PodMan without issue, which leads me to believe I'm doing something wrong with aws4. Below are some examples.Lamnda@Edge code
The request:
the signed request:
error message:
{ "message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details." }
What I've tried so far:
request.body.data
which is the message of the body in base64request.body.data
curl --location --request POST 'https://example.com/v1/log?jwt=TOKEN' \ --header 'X-Amz-Date: 20240417T170851Z' \ --header 'Authorization: AWS4-HMAC-SHA256 Credential=CREDS/20240417/us-west-2/lambda/aws4_request, SignedHeaders=host;x-amz-date, Signature=SIGNATURE' \ --data '{"cat": "lazy"}'
Any help would be appreciated. For now, I will leave the OAC on and figure out a way to sign the payload and bypass aws4.