diff --git a/.structignore b/.structignore index f820d242..a864a91e 100644 --- a/.structignore +++ b/.structignore @@ -1 +1,3 @@ test/util/cache-clearer-disabled.spec.js +test/modules/response-healing.spec.js +test/req-header-overwrite.spec.js diff --git a/package.json b/package.json index 54623230..15775d3b 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "object-scan": "19.0.5", "smart-fs": "4.0.1", "timekeeper": "2.3.1", - "tmp": "0.2.1" + "tmp": "0.2.1", + "xml2js": "0.6.2" } } diff --git a/src/modules/request-recorder.js b/src/modules/request-recorder.js index e54f99d8..2732c3b1 100644 --- a/src/modules/request-recorder.js +++ b/src/modules/request-recorder.js @@ -11,7 +11,7 @@ import nockCommon from 'nock/lib/common.js'; import compareUrls from '../util/compare-urls.js'; import nockListener from './request-recorder/nock-listener.js'; import nockMock from './request-recorder/nock-mock.js'; -import healSqsSendMessageBatch from './request-recorder/heal-sqs-send-message-batch.js'; +import healSqs from './request-recorder/heal-sqs.js'; import applyModifiers from './request-recorder/apply-modifiers.js'; import requestInjector from './request-recorder/request-injector.js'; @@ -223,7 +223,7 @@ export default (opts) => { if (anyFlagPresent(['magic', 'response'])) { const responseBody = tryParseJson([ - healSqsSendMessageBatch + healSqs ].reduce( (respBody, fn) => fn(requestBodyString, respBody, scope, req), interceptor.body diff --git a/src/modules/request-recorder/heal-sqs-send-message-batch.js b/src/modules/request-recorder/heal-sqs-send-message-batch.js deleted file mode 100644 index 39c362ec..00000000 --- a/src/modules/request-recorder/heal-sqs-send-message-batch.js +++ /dev/null @@ -1,21 +0,0 @@ -import crypto from 'crypto'; -import { tryParseJson } from './util.js'; - -export default (requestBody, responseBody, scope, req) => { - if ( - scope?.basePath !== 'https://sqs.us-west-2.amazonaws.com:443' - || req?.options?.headers?.['x-amz-target'] !== 'AmazonSQS.SendMessageBatch' - ) { - return responseBody; - } - - const requestJson = tryParseJson(requestBody); - const responseJson = tryParseJson(responseBody); - return { - Successful: requestJson.Entries.map(({ Id, MessageBody }, idx) => ({ - Id, - MessageId: responseJson?.Successful?.[idx]?.MessageId || crypto.randomUUID(), - MD5OfMessageBody: crypto.createHash('md5').update(MessageBody).digest('hex') - })) - }; -}; diff --git a/src/modules/request-recorder/heal-sqs.js b/src/modules/request-recorder/heal-sqs.js new file mode 100644 index 00000000..67e4300b --- /dev/null +++ b/src/modules/request-recorder/heal-sqs.js @@ -0,0 +1,30 @@ +import crypto from 'crypto'; +import { tryParseJson } from './util.js'; +import migration from './heal-sqs/migration.js'; + +export default (requestBody, responseBody, scope, req) => { + if (scope?.basePath !== 'https://sqs.us-west-2.amazonaws.com:443') { + return responseBody; + } + + const header = req?.options?.headers?.['x-amz-target']; + + if (typeof responseBody === 'string' && responseBody.startsWith(' ({ + Id, + MessageId: responseJson?.Successful?.[idx]?.MessageId || crypto.randomUUID(), + MD5OfMessageBody: crypto.createHash('md5').update(MessageBody).digest('hex') + })) + }; + } + + return responseBody; +}; diff --git a/src/modules/request-recorder/heal-sqs/migration.js b/src/modules/request-recorder/heal-sqs/migration.js new file mode 100644 index 00000000..58a06882 --- /dev/null +++ b/src/modules/request-recorder/heal-sqs/migration.js @@ -0,0 +1,106 @@ +// This code logic is used to migrate legacy AWS SQS xml to json +import xml2js from 'xml2js'; +import objectScan from 'object-scan'; + +const tryParseXML = (body) => { + let parsed = body; + try { + xml2js.parseString(body, (err, result) => { + parsed = JSON.parse(JSON.stringify(result)); + }); + } catch (e) { + return null; + } + return parsed; +}; + +export default ({ responseBody, header }) => { + const responseXml = tryParseXML(responseBody); + if (responseXml !== null) { + if (header === 'AmazonSQS.ListQueueTags') { + const scanner = objectScan(['ListQueueTagsResponse.ListQueueTagsResult[0].Tag[*]'], { + rtn: ({ value }) => [value.Key, value.Value[0]], + afterFn: ({ result }) => Object.fromEntries(result) + }); + const Tags = scanner(responseXml); + return { Tags }; + } + if (header === 'AmazonSQS.GetQueueAttributes') { + const scanner = objectScan(['GetQueueAttributesResponse.GetQueueAttributesResult[0].Attribute[*]'], { + rtn: ({ value }) => [value.Name[0], value.Value[0]], + afterFn: ({ result }) => Object.fromEntries(result) + }); + const Attributes = scanner(responseXml); + return { Attributes }; + } + if (header === 'AmazonSQS.GetQueueUrl') { + if (responseXml?.ErrorResponse?.Error?.[0]?.Code?.[0] === 'AWS.SimpleQueueService.NonExistentQueue') { + return { + __type: 'com.amazonaws.sqs#QueueDoesNotExist', + message: 'The specified queue does not exist.' + }; + } + const QueueUrl = responseXml?.GetQueueUrlResponse?.GetQueueUrlResult?.[0]?.QueueUrl?.[0]; + return { QueueUrl }; + } + if (header === 'AmazonSQS.CreateQueue') { + if (responseXml?.ErrorResponse?.Error?.[0]?.Code?.[0] === 'QueueAlreadyExists') { + return { + __type: 'com.amazonaws.sqs#QueueNameExists', + message: 'The specified queue name does exist.' + }; + } + const QueueUrl = responseXml?.CreateQueueResponse?.CreateQueueResult?.[0]?.QueueUrl?.[0]; + return { QueueUrl }; + } + if (header === 'AmazonSQS.ListQueues') { + const scannerQueueUrls = objectScan( + ['ListQueuesResponse.ListQueuesResult[0].QueueUrl[*]'], + { rtn: 'value', reverse: false } + ); + const scannerNextToken = objectScan( + ['ListQueuesResponse.ListQueuesResult[0].NextToken[0]'], + { rtn: 'value', reverse: false, abort: true } + ); + return { + QueueUrls: scannerQueueUrls(responseXml), + NextToken: scannerNextToken(responseXml) + }; + } + if (header === 'AmazonSQS.TagQueue') { + return {}; + } + if (header === 'AmazonSQS.SetQueueAttributes') { + return {}; + } + if (header === 'AmazonSQS.SendMessageBatch') { + const scannerSuccessful = objectScan( + ['SendMessageBatchResponse.SendMessageBatchResult[0].SendMessageBatchResultEntry[*]'], + { + rtn: ({ value }) => ({ + Id: value.Id[0], + MessageId: value.MessageId[0], + MD5OfMessageBody: value.MD5OfMessageBody[0] + }), + reverse: false + } + ); + const scannerFailed = objectScan( + ['SendMessageBatchResponse.SendMessageBatchResult[0].BatchResultErrorEntry[*]'], + { + rtn: ({ value }) => ({ + Id: value.Id[0], + SenderFault: value.SenderFault[0], + Code: value.Code[0] + }), + reverse: false + } + ); + return { + Successful: scannerSuccessful(responseXml), + Failed: scannerFailed(responseXml) + }; + } + } + return responseBody; +}; diff --git a/test/modules/request-recorder.spec.js b/test/modules/request-recorder.spec.js index e475654a..4763c642 100644 --- a/test/modules/request-recorder.spec.js +++ b/test/modules/request-recorder.spec.js @@ -3,26 +3,10 @@ import https from 'https'; import fs from 'smart-fs'; import get from 'lodash.get'; import axios from 'axios'; -import { logger } from 'lambda-monitor-logger'; import { expect } from 'chai'; -import awsSdkWrap from 'aws-sdk-wrap'; -import { - SQSClient, - SendMessageBatchCommand -} from '@aws-sdk/client-sqs'; import { describe } from '../../src/index.js'; import { NockRecord, spawnServer } from '../server.js'; -const aws = awsSdkWrap({ - logger, - services: { - SQS: SQSClient, - 'SQS:CMD': { - SendMessageBatchCommand - } - } -}); - describe('Testing RequestRecorder', { useTmpDir: true, timestamp: 0 }, () => { const cassetteFile = 'file1.json'; let tmpDir; @@ -383,20 +367,6 @@ describe('Testing RequestRecorder', { useTmpDir: true, timestamp: 0 }, () => { await runner('prune,record', { qs: [1], raises: true }); }); - describe('Testing magic healing', { cryptoSeed: 'd28095c6-19f4-4dc2-a7cc-f7640c032967' }, () => { - it('Testing heal SQS response', async ({ fixture }) => { - fs.smartWrite(path.join(tmpDir, cassetteFile), fixture('sqs-cassette-bad')); - const r = await nockRecord(() => aws.sqs.sendMessageBatch({ - messages: [{ k: 1 }, { k: 2 }], - queueUrl: process.env.QUEUE_URL - }), { heal: 'magic' }); - const expected = fixture('sqs-cassette-expected'); - expected[0].reqheaders['user-agent'] = r.expectedCassette[0].reqheaders['user-agent']; - expect(r.expectedCassette[0].reqheaders['user-agent'].startsWith('aws-sdk-js/3.')).to.equal(true); - expect(r.expectedCassette).to.deep.equal(expected); - }); - }); - it('Testing record (with headers)', async () => { await runner('record', { qs: [1, 2, 3], diff --git a/test/modules/request-recorder.spec.js__fixtures/sqs-cassette-bad.json b/test/modules/request-recorder.spec.js__fixtures/sqs-cassette-bad.json deleted file mode 100644 index b6e2b91f..00000000 --- a/test/modules/request-recorder.spec.js__fixtures/sqs-cassette-bad.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "scope": "https://sqs.us-west-2.amazonaws.com:443", - "method": "POST", - "path": "/", - "body": { - "Entries": [ - { - "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", - "MessageBody": "{\"k\":1}" - } - ], - "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" - }, - "status": 200, - "response": { - "Successful": [ - { - "Id": "feabf4c420f7eec1fbd3ad1b74e972af9f879cad", - "MessageId": "e40625e7-e66f-4c6c-8d9b-7bb8944b0108", - "MD5OfMessageBody": "some-bad-hash45be96b2d5b9d22cdc4" - } - ] - } - } -] diff --git a/test/modules/response-healing.spec.js b/test/modules/response-healing.spec.js new file mode 100644 index 00000000..71092b41 --- /dev/null +++ b/test/modules/response-healing.spec.js @@ -0,0 +1,78 @@ +import path from 'path'; +import fs from 'smart-fs'; +import { logger } from 'lambda-monitor-logger'; +import { expect } from 'chai'; +import awsSdkWrap from 'aws-sdk-wrap'; +import { + SQSClient, + SendMessageBatchCommand, + GetQueueUrlCommand, + GetQueueAttributesCommand, + ListQueueTagsCommand, + CreateQueueCommand, + ListQueuesCommand, + TagQueueCommand, + SetQueueAttributesCommand +} from '@aws-sdk/client-sqs'; +import objectScan from 'object-scan'; +import { describe } from '../../src/index.js'; +import { NockRecord } from '../server.js'; +import reqHeaderOverwrite from '../req-header-overwrite.js'; + +const aws = awsSdkWrap({ + logger, + services: { + SQS: SQSClient, + 'SQS:CMD': { + SendMessageBatchCommand, + GetQueueUrlCommand, + GetQueueAttributesCommand, + ListQueueTagsCommand, + CreateQueueCommand, + ListQueuesCommand, + TagQueueCommand, + SetQueueAttributesCommand + } + } +}); + +const fixtureFolder = `${fs.filename(import.meta.url)}__fixtures`; +const files = fs + .walkDir(fixtureFolder) + .filter((f) => !f.endsWith('.json__expected.json')); + +describe('Testing Response Healing', { + useTmpDir: true, + timestamp: 0, + cryptoSeed: 'd28095c6-19f4-4dc2-a7cc-f7640c032967' +}, () => { + const cassetteFile = 'file1.json'; + let tmpDir; + let nockRecord; + + beforeEach(async ({ dir }) => { + tmpDir = dir; + nockRecord = NockRecord(tmpDir, cassetteFile); + }); + + // eslint-disable-next-line mocha/no-setup-in-describe + files.forEach((f) => { + it(`Testing ${f}`, async ({ fixture }) => { + const { fn, params, cassette } = fixture(f); + fs.smartWrite(path.join(tmpDir, cassetteFile), cassette); + const func = fn.split('.').reduce((p, v) => p[v], aws); + objectScan(['**'], { + filterFn: ({ value, parent, property }) => { + if (value === '$queueUrl') { + // eslint-disable-next-line no-param-reassign + parent[property] = process.env.QUEUE_URL; + } + } + })(params); + const r = await nockRecord(() => func(...params), { heal: 'magic', reqHeaderOverwrite }); + const outFile = path.join(fixtureFolder, `${f}__expected.json`); + const overwritten = fs.smartWrite(outFile, r.expectedCassette); + expect(overwritten).to.deep.equal(false); + }); + }); +}); diff --git a/test/modules/response-healing.spec.js.env.yml b/test/modules/response-healing.spec.js.env.yml new file mode 100644 index 00000000..ed49bcef --- /dev/null +++ b/test/modules/response-healing.spec.js.env.yml @@ -0,0 +1,4 @@ +AWS_REGION: "us-west-2" +AWS_ACCESS_KEY_ID: "XXXXXXXXXXXXXXXXXXXX" +AWS_SECRET_ACCESS_KEY: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +QUEUE_URL: "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" diff --git a/test/modules/response-healing.spec.js__fixtures/json_bad-md5.json b/test/modules/response-healing.spec.js__fixtures/json_bad-md5.json new file mode 100644 index 00000000..a9cb8865 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/json_bad-md5.json @@ -0,0 +1,33 @@ +{ + "fn": "sqs.sendMessageBatch", + "params": [{ + "messages": [{ "k": 1 }, { "k": 2 }], + "queueUrl": "$queueUrl" + }], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "Entries": [ + { + "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", + "MessageBody": "{\"k\":1}" + } + ], + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" + }, + "status": 200, + "response": { + "Successful": [ + { + "Id": "feabf4c420f7eec1fbd3ad1b74e972af9f879cad", + "MessageId": "e40625e7-e66f-4c6c-8d9b-7bb8944b0108", + "MD5OfMessageBody": "some-bad-hash45be96b2d5b9d22cdc4" + } + ] + } + } + ] +} diff --git a/test/modules/request-recorder.spec.js__fixtures/sqs-cassette-expected.json b/test/modules/response-healing.spec.js__fixtures/json_bad-md5.json__expected.json similarity index 61% rename from test/modules/request-recorder.spec.js__fixtures/sqs-cassette-expected.json rename to test/modules/response-healing.spec.js__fixtures/json_bad-md5.json__expected.json index 1f0ba1d7..ba6fc64c 100644 --- a/test/modules/request-recorder.spec.js__fixtures/sqs-cassette-expected.json +++ b/test/modules/response-healing.spec.js__fixtures/json_bad-md5.json__expected.json @@ -32,17 +32,17 @@ ] }, "reqheaders": { - "amz-sdk-invocation-id": "e9725510-7b42-4901-b553-969b5a03e7d4", + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", "amz-sdk-request": "attempt=1; max=3", - "authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXXX/19700101/us-west-2/sqs/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target;x-amz-user-agent, Signature=2af4a0ee820b745f53c3313dd7eb7eef53ba8e25b96f79f4f58cc53aedc39000", - "content-length": "261", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", "content-type": "application/x-amz-json-1.0", "host": "sqs.us-west-2.amazonaws.com", - "user-agent": "aws-sdk-js/3.458.0 ua/2.0 os/linux#5.4.0-166-generic lang/js md/nodejs#18.18.2 api/sqs#3.458.0", - "x-amz-content-sha256": "42d9205526e005eece0404131937f30da55578dcb4a17bdd14751d2706474acf", - "x-amz-date": "19700101T000000Z", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", "x-amz-target": "AmazonSQS.SendMessageBatch", - "x-amz-user-agent": "aws-sdk-js/3.458.0" + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" } } ] diff --git a/test/modules/response-healing.spec.js__fixtures/json_get-queue-url.json b/test/modules/response-healing.spec.js__fixtures/json_get-queue-url.json new file mode 100644 index 00000000..27195fbd --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/json_get-queue-url.json @@ -0,0 +1,22 @@ +{ + "fn": "call", + "params": [ + "sqs:GetQueueUrlCommand", + {"QueueName": "some-queue-name"} + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "QueueName": "some-queue-name" + }, + "status": 200, + "response": { + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/012345678910/some-queue-url" + }, + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/json_get-queue-url.json__expected.json b/test/modules/response-healing.spec.js__fixtures/json_get-queue-url.json__expected.json new file mode 100644 index 00000000..865821cc --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/json_get-queue-url.json__expected.json @@ -0,0 +1,28 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "QueueName": "some-queue-name" + }, + "status": 200, + "response": { + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/012345678910/some-queue-url" + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.GetQueueUrl", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_create-queue.json b/test/modules/response-healing.spec.js__fixtures/xml_create-queue.json new file mode 100644 index 00000000..dd712995 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_create-queue.json @@ -0,0 +1,33 @@ +{ + "fn": "call", + "params": [ + "sqs:CreateQueueCommand", + { + "QueueName": "some-queue-name", + "Attributes": { + "DelaySeconds": "0", + "MaximumMessageSize": "262144", + "MessageRetentionPeriod": "345600", + "ReceiveMessageWaitTimeSeconds": "0", + "VisibilityTimeout": "360", + "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-west-2:012345678910:some-queue-arn\",\"maxReceiveCount\":10}" + }, + "tags": { + "tagA": "33a8baaf-6aed-4abc-95eb-95e40a8f4fa9", + "tagB": "92769396-e725-452e-b56c-969b765bb731", + "lastModified": "2022-06-27T21:08:54.033Z" + } + } + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueName=some-queue-name&Tag.1.Key=tagA&Tag.1.Value=33a8baaf-6aed-4abc-95eb-95e40a8f4fa9&Tag.2.Key=tagB&Tag.2.Value=92769396-e725-452e-b56c-969b765bb731&Tag.3.Key=lastModified&Tag.3.Value=2022-06-27T21%3A08%3A54.033Z&Attribute.1.Name=DelaySeconds&Attribute.1.Value=0&Attribute.2.Name=MaximumMessageSize&Attribute.2.Value=262144&Attribute.3.Name=MessageRetentionPeriod&Attribute.3.Value=345600&Attribute.4.Name=ReceiveMessageWaitTimeSeconds&Attribute.4.Value=0&Attribute.5.Name=VisibilityTimeout&Attribute.5.Value=360&Attribute.6.Name=RedrivePolicy&Attribute.6.Value=%7B%22deadLetterTargetArn%22%3A%22arn%3Aaws%3Asqs%3Aus-west-2%3A799715345196%3Asome-queue-arn%22%2C%22maxReceiveCount%22%3A10%7D&Action=CreateQueue&Version=2012-11-05", + "status": 200, + "response": "https://sqs.us-west-2.amazonaws.com/012345678910/some-queue-urlc071ab24-eb4c-5277-8a24-f010f7106a25", + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_create-queue.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_create-queue.json__expected.json new file mode 100644 index 00000000..da56e828 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_create-queue.json__expected.json @@ -0,0 +1,41 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "Attributes": { + "DelaySeconds": "0", + "MaximumMessageSize": "262144", + "MessageRetentionPeriod": "345600", + "ReceiveMessageWaitTimeSeconds": "0", + "VisibilityTimeout": "360", + "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-west-2:012345678910:some-queue-arn\",\"maxReceiveCount\":10}" + }, + "QueueName": "some-queue-name", + "tags": { + "tagA": "33a8baaf-6aed-4abc-95eb-95e40a8f4fa9", + "tagB": "92769396-e725-452e-b56c-969b765bb731", + "lastModified": "2022-06-27T21:08:54.033Z" + } + }, + "status": 200, + "response": { + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/012345678910/some-queue-url" + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.CreateQueue", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_create-queue_bad-xml.json b/test/modules/response-healing.spec.js__fixtures/xml_create-queue_bad-xml.json new file mode 100644 index 00000000..85df9eaa --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_create-queue_bad-xml.json @@ -0,0 +1,36 @@ +{ + "fn": "call", + "params": [ + "sqs:CreateQueueCommand", + { + "QueueName": "some-queue-name", + "Attributes": { + "DelaySeconds": "0", + "MaximumMessageSize": "262144", + "MessageRetentionPeriod": "345600", + "ReceiveMessageWaitTimeSeconds": "0", + "VisibilityTimeout": "360", + "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-west-2:012345678910:some-queue-arn\",\"maxReceiveCount\":10}" + }, + "tags": { + "tagA": "33a8baaf-6aed-4abc-95eb-95e40a8f4fa9", + "tagB": "92769396-e725-452e-b56c-969b765bb731", + "lastModified": "2022-06-27T21:08:54.033Z" + } + }, + { + "expectedErrorCodes": ["SyntaxError"] + } + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueName=some-queue-name&Tag.1.Key=tagA&Tag.1.Value=33a8baaf-6aed-4abc-95eb-95e40a8f4fa9&Tag.2.Key=tagB&Tag.2.Value=92769396-e725-452e-b56c-969b765bb731&Tag.3.Key=lastModified&Tag.3.Value=2022-06-27T21%3A08%3A54.033Z&Attribute.1.Name=DelaySeconds&Attribute.1.Value=0&Attribute.2.Name=MaximumMessageSize&Attribute.2.Value=262144&Attribute.3.Name=MessageRetentionPeriod&Attribute.3.Value=345600&Attribute.4.Name=ReceiveMessageWaitTimeSeconds&Attribute.4.Value=0&Attribute.5.Name=VisibilityTimeout&Attribute.5.Value=360&Attribute.6.Name=RedrivePolicy&Attribute.6.Value=%7B%22deadLetterTargetArn%22%3A%22arn%3Aaws%3Asqs%3Aus-west-2%3A799715345196%3Asome-queue-arn%22%2C%22maxReceiveCount%22%3A10%7D&Action=CreateQueue&Version=2012-11-05", + "status": 200, + "response": "SenderQueueAlreadyExistsA queue already exists with the same name and a different value for tags 3b370f81-ff46-524a-bb5a-552ddc1d9b8b", + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_create-queue_error.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_create-queue_error.json__expected.json new file mode 100644 index 00000000..2825e07a --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_create-queue_error.json__expected.json @@ -0,0 +1,42 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "Attributes": { + "DelaySeconds": "0", + "MaximumMessageSize": "262144", + "MessageRetentionPeriod": "345600", + "ReceiveMessageWaitTimeSeconds": "0", + "VisibilityTimeout": "360", + "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-west-2:012345678910:some-queue-arn\",\"maxReceiveCount\":10}" + }, + "QueueName": "some-queue-name", + "tags": { + "tagA": "33a8baaf-6aed-4abc-95eb-95e40a8f4fa9", + "tagB": "92769396-e725-452e-b56c-969b765bb731", + "lastModified": "2022-06-27T21:08:54.033Z" + } + }, + "status": 400, + "response": { + "__type": "com.amazonaws.sqs#QueueNameExists", + "message": "The specified queue name does exist." + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.CreateQueue", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_get-queue-attributes.json b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-attributes.json new file mode 100644 index 00000000..ed201bd4 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-attributes.json @@ -0,0 +1,25 @@ +{ + "fn": "call", + "params": [ + "sqs:GetQueueAttributesCommand", + { + "QueueUrl": "some-queue-url", + "AttributeNames": [ + "ApproximateNumberOfMessages", + "ApproximateNumberOfMessagesDelayed", + "ApproximateNumberOfMessagesNotVisible" + ] + } + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F012345678910%2Fsome-queue-url&AttributeName.1=ApproximateNumberOfMessages&AttributeName.2=ApproximateNumberOfMessagesDelayed&AttributeName.3=ApproximateNumberOfMessagesNotVisible&AttributeName.4=QueueArn&Action=GetQueueAttributes&Version=2012-11-05", + "status": 200, + "response": "ApproximateNumberOfMessages1ApproximateNumberOfMessagesDelayed0ApproximateNumberOfMessagesNotVisible0QueueArnarn:aws:sqs:us-west-2:012345678910:some-queue-arnb8ca4c86-2fd1-5481-9e72-160c0ef00529", + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_get-queue-attributes.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-attributes.json__expected.json new file mode 100644 index 00000000..eca50730 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-attributes.json__expected.json @@ -0,0 +1,38 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "AttributeNames": [ + "ApproximateNumberOfMessages", + "ApproximateNumberOfMessagesDelayed", + "ApproximateNumberOfMessagesNotVisible" + ], + "QueueUrl": "some-queue-url" + }, + "status": 200, + "response": { + "Attributes": { + "QueueArn": "arn:aws:sqs:us-west-2:012345678910:some-queue-arn", + "ApproximateNumberOfMessagesNotVisible": "0", + "ApproximateNumberOfMessagesDelayed": "0", + "ApproximateNumberOfMessages": "1" + } + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.GetQueueAttributes", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url.json b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url.json new file mode 100644 index 00000000..819e4f75 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url.json @@ -0,0 +1,18 @@ +{ + "fn": "call", + "params": [ + "sqs:GetQueueUrlCommand", + {"QueueName": "some-queue-name"} + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueName=some-queue-url&Action=GetQueueUrl&Version=2012-11-05", + "status": 200, + "response": "https://sqs.us-west-2.amazonaws.com/012345678910/some-queue-urlef534ad7-e2af-594f-b8da-10a86f37deb1", + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url.json__expected.json new file mode 100644 index 00000000..865821cc --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url.json__expected.json @@ -0,0 +1,28 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "QueueName": "some-queue-name" + }, + "status": 200, + "response": { + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/012345678910/some-queue-url" + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.GetQueueUrl", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url_error.json b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url_error.json new file mode 100644 index 00000000..5bae4b9a --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url_error.json @@ -0,0 +1,20 @@ + +{ + "fn": "call", + "params": [ + "sqs:GetQueueUrlCommand", + {"QueueName": "some-queue-name"}, + {"expectedErrorCodes": ["QueueDoesNotExist"]} + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueName=some-queue-name&Action=GetQueueUrl&Version=2012-11-05", + "status": 400, + "response": "SenderAWS.SimpleQueueService.NonExistentQueueThe specified queue does not exist for this wsdl version.7fb23608-cc30-515b-89b2-6c7fbfb18a2c", + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url_error.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url_error.json__expected.json new file mode 100644 index 00000000..00875e0c --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_get-queue-url_error.json__expected.json @@ -0,0 +1,29 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "QueueName": "some-queue-name" + }, + "status": 400, + "response": { + "__type": "com.amazonaws.sqs#QueueDoesNotExist", + "message": "The specified queue does not exist." + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.GetQueueUrl", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_list-queue-tags.json b/test/modules/response-healing.spec.js__fixtures/xml_list-queue-tags.json new file mode 100644 index 00000000..b29d3107 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_list-queue-tags.json @@ -0,0 +1,19 @@ + +{ + "fn": "call", + "params": [ + "sqs:ListQueueTagsCommand", + {"QueueUrl": "$queueUrl"} + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F012345678910%2Fsome-queue-url&Action=ListQueueTags&Version=2012-11-05", + "status": 200, + "response": "tagA4cbc382c-94d0-48fb-b625-f098683afd3dtagBccfc9f9b-5379-4ae7-ba5c-5891a8259f83lastModified2022-02-10T21:54:53.039Zb3fee173-056e-5034-bd15-bbf9244fa0de", + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_list-queue-tags.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_list-queue-tags.json__expected.json new file mode 100644 index 00000000..9db784f5 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_list-queue-tags.json__expected.json @@ -0,0 +1,32 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" + }, + "status": 200, + "response": { + "Tags": { + "lastModified": "2022-02-10T21:54:53.039Z", + "tagB": "ccfc9f9b-5379-4ae7-ba5c-5891a8259f83", + "tagA": "4cbc382c-94d0-48fb-b625-f098683afd3d" + } + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.ListQueueTags", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_list-queues.json b/test/modules/response-healing.spec.js__fixtures/xml_list-queues.json new file mode 100644 index 00000000..4d246d59 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_list-queues.json @@ -0,0 +1,19 @@ +{ + "fn": "call", + "params": [ + "sqs:ListQueuesCommand", + { + "QueueNamePrefix": "queue-na" + } + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueNamePrefix=queue-na&MaxResults=1000&Action=ListQueues&Version=2012-11-05", + "status": 200, + "response": "https://sqs.us-west-2.amazonaws.com/799715345196/queue-nameAAcAAgGAARSS5TwyARjKvEtzRiU9-7SLAAAAAQAET2RpbgAVMgAAAIAAAAAMADV49xkN9M81B1-uACCMSfA4lSikCuU6IfjOm61yC2XRJCgrqG454BMG9s91VQIAAAAADAAAEAAAAAAAAAAAAAAAAACuISguSDtCCtrLIMNdib1c_____wAAAAEAAAAAAAAAAAAAAAEAAACsum_OBChhP2KkJbd8aE8zIxNaJVkyY47PG8XJTtmTYDskzekNdLuLn54pq7hJY3V4xlpzIfVUzrn94lkVzN9M-IvkkJylyF44cVGgMUBQagjjI3v2oKy6aOenskJgvly264lHDjfuIh2XEdgdVW-lvcPZHauFtjY-JtXxIta9iLYDFOonRUWC45jnv6y4ayK8Eu7gtlWa-Jn_ORgsYo9y0tecQVhhlXEswB3M864NnyG6U-6spJQKjogOyB4=93225a9a-fc00-5341-bce5-00e8c6330d6b", + "responseIsBinary": false + } ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_list-queues.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_list-queues.json__expected.json new file mode 100644 index 00000000..d7952e59 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_list-queues.json__expected.json @@ -0,0 +1,31 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "QueueNamePrefix": "queue-na" + }, + "status": 200, + "response": { + "QueueUrls": [ + "https://sqs.us-west-2.amazonaws.com/799715345196/queue-name" + ], + "NextToken": "AAcAAgGAARSS5TwyARjKvEtzRiU9-7SLAAAAAQAET2RpbgAVMgAAAIAAAAAMADV49xkN9M81B1-uACCMSfA4lSikCuU6IfjOm61yC2XRJCgrqG454BMG9s91VQIAAAAADAAAEAAAAAAAAAAAAAAAAACuISguSDtCCtrLIMNdib1c_____wAAAAEAAAAAAAAAAAAAAAEAAACsum_OBChhP2KkJbd8aE8zIxNaJVkyY47PG8XJTtmTYDskzekNdLuLn54pq7hJY3V4xlpzIfVUzrn94lkVzN9M-IvkkJylyF44cVGgMUBQagjjI3v2oKy6aOenskJgvly264lHDjfuIh2XEdgdVW-lvcPZHauFtjY-JtXxIta9iLYDFOonRUWC45jnv6y4ayK8Eu7gtlWa-Jn_ORgsYo9y0tecQVhhlXEswB3M864NnyG6U-6spJQKjogOyB4=" + }, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.ListQueues", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch-with-failures.json b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch-with-failures.json new file mode 100644 index 00000000..c4fd8b04 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch-with-failures.json @@ -0,0 +1,25 @@ +{ + "fn": "sqs.sendMessageBatch", + "params": [{ + "messages": [{ "k": 1 }, { "k": 2 }], + "queueUrl": "$queueUrl" + }], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F123456789101%2Fservice-name-data-local-SomeQueue&SendMessageBatchRequestEntry.1.Id=4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f&SendMessageBatchRequestEntry.1.MessageBody=%7B%22k%22%3A1%7D&SendMessageBatchRequestEntry.2.Id=743966ceb52ce2e8c7a2424f4d652e3b7936f1ee&SendMessageBatchRequestEntry.2.MessageBody=%7B%22k%22%3A2%7D&Action=SendMessageBatch&Version=2012-11-05", + "status": 200, + "response": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530ffalseInternalError743966ceb52ce2e8c7a2424f4d652e3b7936f1eefalseInternalErrorb4f56dbc-037a-5147-8dcd-38068125b74b" + }, + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F123456789101%2Fservice-name-data-local-SomeQueue&SendMessageBatchRequestEntry.1.Id=4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f&SendMessageBatchRequestEntry.1.MessageBody=%7B%22k%22%3A1%7D&SendMessageBatchRequestEntry.2.Id=743966ceb52ce2e8c7a2424f4d652e3b7936f1ee&SendMessageBatchRequestEntry.2.MessageBody=%7B%22k%22%3A2%7D&Action=SendMessageBatch&Version=2012-11-05", + "status": 200, + "response": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530fc0004b0c-ea00-498a-a5a2-362703c0b621e59138f35192e320088b83d28388d6bb743966ceb52ce2e8c7a2424f4d652e3b7936f1eec0004b0c-ea00-498a-a5a2-362703c0b6210dc3f48bc3e78aed8f69f72be8a11087584b2818-1c3b-5bfd-97e0-7d388e494f1e" + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch-with-failures.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch-with-failures.json__expected.json new file mode 100644 index 00000000..7842795c --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch-with-failures.json__expected.json @@ -0,0 +1,96 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "Entries": [ + { + "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", + "MessageBody": "{\"k\":1}" + }, + { + "Id": "743966ceb52ce2e8c7a2424f4d652e3b7936f1ee", + "MessageBody": "{\"k\":2}" + } + ], + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" + }, + "status": 200, + "response": { + "Successful": [], + "Failed": [ + { + "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", + "SenderFault": "false", + "Code": "InternalError" + }, + { + "Id": "743966ceb52ce2e8c7a2424f4d652e3b7936f1ee", + "SenderFault": "false", + "Code": "InternalError" + } + ] + }, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.SendMessageBatch", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + }, + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "Entries": [ + { + "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", + "MessageBody": "{\"k\":1}" + }, + { + "Id": "743966ceb52ce2e8c7a2424f4d652e3b7936f1ee", + "MessageBody": "{\"k\":2}" + } + ], + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" + }, + "status": 200, + "response": { + "Successful": [ + { + "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", + "MessageId": "c0004b0c-ea00-498a-a5a2-362703c0b621", + "MD5OfMessageBody": "e59138f35192e320088b83d28388d6bb" + }, + { + "Id": "743966ceb52ce2e8c7a2424f4d652e3b7936f1ee", + "MessageId": "c0004b0c-ea00-498a-a5a2-362703c0b621", + "MD5OfMessageBody": "0dc3f48bc3e78aed8f69f72be8a11087" + } + ], + "Failed": [] + }, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.SendMessageBatch", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch.json b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch.json new file mode 100644 index 00000000..c9774a46 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch.json @@ -0,0 +1,17 @@ +{ + "fn": "sqs.sendMessageBatch", + "params": [{ + "messages": [{ "k": 1 }, { "k": 2 }], + "queueUrl": "$queueUrl" + }], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F123456789101%2Fservice-name-data-local-SomeQueue&SendMessageBatchRequestEntry.1.Id=4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f&SendMessageBatchRequestEntry.1.MessageBody=%7B%22k%22%3A1%7D&SendMessageBatchRequestEntry.2.Id=743966ceb52ce2e8c7a2424f4d652e3b7936f1ee&SendMessageBatchRequestEntry.2.MessageBody=%7B%22k%22%3A2%7D&Action=SendMessageBatch&Version=2012-11-05", + "status": 200, + "response": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530fc0004b0c-ea00-498a-a5a2-362703c0b621e59138f35192e320088b83d28388d6bb743966ceb52ce2e8c7a2424f4d652e3b7936f1eec0004b0c-ea00-498a-a5a2-362703c0b6210dc3f48bc3e78aed8f69f72be8a11087584b2818-1c3b-5bfd-97e0-7d388e494f1e" + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch.json__expected.json new file mode 100644 index 00000000..18d0fc97 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_send-message-batch.json__expected.json @@ -0,0 +1,49 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "Entries": [ + { + "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", + "MessageBody": "{\"k\":1}" + }, + { + "Id": "743966ceb52ce2e8c7a2424f4d652e3b7936f1ee", + "MessageBody": "{\"k\":2}" + } + ], + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" + }, + "status": 200, + "response": { + "Successful": [ + { + "Id": "4f494d6b422d1e5fbbe6b6d82584ce7f70c1530f", + "MessageId": "c0004b0c-ea00-498a-a5a2-362703c0b621", + "MD5OfMessageBody": "e59138f35192e320088b83d28388d6bb" + }, + { + "Id": "743966ceb52ce2e8c7a2424f4d652e3b7936f1ee", + "MessageId": "c0004b0c-ea00-498a-a5a2-362703c0b621", + "MD5OfMessageBody": "0dc3f48bc3e78aed8f69f72be8a11087" + } + ], + "Failed": [] + }, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.SendMessageBatch", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_set-queue-attributes.json b/test/modules/response-healing.spec.js__fixtures/xml_set-queue-attributes.json new file mode 100644 index 00000000..62b00f39 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_set-queue-attributes.json @@ -0,0 +1,22 @@ +{ + "fn": "call", + "params": [ + "sqs:SetQueueAttributesCommand", + { + "QueueUrl": "$queueUrl", + "Attributes": { + "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-west-2:12345678910:some-queue-arn\",\"maxReceiveCount\":10}" + } + } + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F12345678910%2Fsome-queue-url&Attribute.1.Name=RedrivePolicy&Attribute.1.Value=%7B%22deadLetterTargetArn%22%3A%22arn%3Aaws%3Asqs%3Aus-west-2%3A799715345196%3Asome-queue-arn%22%2C%22maxReceiveCount%22%3A10%7D&Action=SetQueueAttributes&Version=2012-11-05", + "status": 200, + "response": "f6b2708b-5902-5f1c-b06d-2bbc8a19eb95", + "responseIsBinary": false + } ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_set-queue-attributes.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_set-queue-attributes.json__expected.json new file mode 100644 index 00000000..399127e8 --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_set-queue-attributes.json__expected.json @@ -0,0 +1,29 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "Attributes": { + "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-west-2:12345678910:some-queue-arn\",\"maxReceiveCount\":10}" + }, + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" + }, + "status": 200, + "response": {}, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.SetQueueAttributes", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/modules/response-healing.spec.js__fixtures/xml_tag-queue.json b/test/modules/response-healing.spec.js__fixtures/xml_tag-queue.json new file mode 100644 index 00000000..ff0e7dcc --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_tag-queue.json @@ -0,0 +1,20 @@ +{ + "fn": "call", + "params": [ + "sqs:TagQueueCommand", + { + "QueueUrl": "$queueUrl" + } + ], + "cassette": [ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": "QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F012345678910%2Fsome-queue-url&Tag.1.Key=tagA&Tag.1.Value=07fc583e-e634-430c-aeeb-b1d39c3004ef&Tag.2.Key=tagB&Tag.2.Value=272193a4-d7ba-44f9-af56-d4f7e714f9b1&Action=TagQueue&Version=2012-11-05", + "status": 200, + "response": "fa8d0dba-e5a1-50d2-9a2e-568efab22935", + "responseIsBinary": false + } + ] +} diff --git a/test/modules/response-healing.spec.js__fixtures/xml_tag-queue.json__expected.json b/test/modules/response-healing.spec.js__fixtures/xml_tag-queue.json__expected.json new file mode 100644 index 00000000..b678078d --- /dev/null +++ b/test/modules/response-healing.spec.js__fixtures/xml_tag-queue.json__expected.json @@ -0,0 +1,26 @@ +[ + { + "scope": "https://sqs.us-west-2.amazonaws.com:443", + "method": "POST", + "path": "/", + "body": { + "QueueUrl": "https://sqs.us-west-2.amazonaws.com/123456789101/service-name-data-local-SomeQueue" + }, + "status": 200, + "response": {}, + "responseIsBinary": false, + "reqheaders": { + "amz-sdk-invocation-id": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "amz-sdk-request": "attempt=1; max=3", + "authorization": "^AWS4-HMAC-SHA256 Credential=.+$", + "content-length": "^[1-9][0-9]*$", + "content-type": "application/x-amz-json-1.0", + "host": "sqs.us-west-2.amazonaws.com", + "user-agent": "^aws-sdk-js/.+$", + "x-amz-content-sha256": "^[a-f0-9]{64}$", + "x-amz-date": "^[0-9]{8}T[0-9]{6}Z$", + "x-amz-target": "AmazonSQS.TagQueue", + "x-amz-user-agent": "^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$" + } + } +] diff --git a/test/req-header-overwrite.js b/test/req-header-overwrite.js new file mode 100644 index 00000000..7b4ef8c7 --- /dev/null +++ b/test/req-header-overwrite.js @@ -0,0 +1,62 @@ +const transform = (logic) => Object.fromEntries(Object.entries(logic) + .map(([k, v]) => [k, (kwargs) => { + if (typeof v === 'function') { + return v(kwargs); + } + const { headers, value } = kwargs; + const entries = Object.entries(v); + for (let idx = 0; idx < entries.length; idx += 1) { + const [hostMatcher, valueNew] = entries[idx]; + if (typeof headers.host === 'string' && headers.host.endsWith(hostMatcher)) { + return typeof valueNew === 'function' ? valueNew(kwargs) : valueNew; + } + } + return value; + }])); + +export default transform({ + 'content-length': ({ value }) => (String(value) === '0' ? 0 : '^[1-9][0-9]*$'), + 'os-version': { + 'getintheloop-dev-test.chargebee.com': '^linux x64 .+$' + }, + 'lang-version': { + 'getintheloop-dev-test.chargebee.com': '^v[0-9]+\\.[0-9]+\\.[0-9]+$' + }, + 'user-agent': { + 'monitoring.us-west-2.amazonaws.com': '^aws-sdk-js/.+$', + 'lambda.us-west-2.amazonaws.com': '^aws-sdk-js/.+$', + 'sqs.us-west-2.amazonaws.com': '^aws-sdk-js/.+$', + 'ssm.us-west-2.amazonaws.com': '^aws-sdk-js/.+$', + 'dynamodb.us-west-2.amazonaws.com': '^aws-sdk-js/.+$', + 's3.us-west-2.amazonaws.com': '^aws-sdk-js/.+$', + 'execute-api.us-west-2.amazonaws.com': '^service-search via service-discovery-util/[0-9]+\\.[0-9]+\\.[0-9]+$', + 'getintheloop-dev-test.chargebee.com': '^Chargebee-NodeJs-Client v[0-9]+\\.[0-9]+\\.[0-9]+$' + }, + 'x-amz-user-agent': { + 'monitoring.us-west-2.amazonaws.com': '^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$', + 'lambda.us-west-2.amazonaws.com': '^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$', + 'sqs.us-west-2.amazonaws.com': '^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$', + 'ssm.us-west-2.amazonaws.com': '^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$', + 'dynamodb.us-west-2.amazonaws.com': '^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$', + 's3.us-west-2.amazonaws.com': '^aws-sdk-js/[0-9]+.[0-9]+.[0-9]+$' + }, + 'amz-sdk-invocation-id': { + '.us-west-2.amazonaws.com': '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$' + }, + authorization: { + '.us-west-2.amazonaws.com': '^AWS4-HMAC-SHA256 Credential=.+$', + 'opensearch:9200': '^AWS4-HMAC-SHA256 Credential=.+$', + 'getintheloop-dev-test.chargebee.com': '^Basic .+$', + 'org.okta.com': '^(SSWS|Bearer) .+$', + '': '' + }, + 'x-amz-date': { + '.us-west-2.amazonaws.com': '^[0-9]{8}T[0-9]{6}Z$' + }, + 'x-amz-security-token': { + '.us-west-2.amazonaws.com': '^X{368}$' + }, + 'x-amz-content-sha256': { + '.us-west-2.amazonaws.com': ({ value }) => (value === 'UNSIGNED-PAYLOAD' ? value : '^[a-f0-9]{64}$') + } +}); diff --git a/test/req-header-overwrite.spec.js b/test/req-header-overwrite.spec.js new file mode 100644 index 00000000..93018a15 --- /dev/null +++ b/test/req-header-overwrite.spec.js @@ -0,0 +1,51 @@ +import { expect } from 'chai'; +import reqHeaderOverwrite from './req-header-overwrite.js'; + +describe('Testing req-header-overwrite.js', () => { + it('Testing content-length zero', async () => { + expect(reqHeaderOverwrite['content-length']({ value: 0 })).to.equal(0); + }); + + it('Testing content-length not zero', async () => { + expect(reqHeaderOverwrite['content-length']({ value: 100 })).to.not.equal(0); + }); + + it('Testing user-agent by known host', async () => { + expect(reqHeaderOverwrite['user-agent']({ + value: 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', + headers: { + host: 'sqs.us-west-2.amazonaws.com' + } + })).to.equal('^aws-sdk-js/.+$'); + }); + + it('Testing user-agent by unknown host', async () => { + const value = ( + 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36' + ); + expect(reqHeaderOverwrite['user-agent']({ + value, + headers: { + host: 'some.unknown.host' + } + })).to.equal(value); + }); + + it('Testing x-amz-content-sha256 as unsigned payload', async () => { + expect(reqHeaderOverwrite['x-amz-content-sha256']({ + value: 'UNSIGNED-PAYLOAD', + headers: { + host: 's3.us-west-2.amazonaws.com' + } + })).to.equal('UNSIGNED-PAYLOAD'); + }); + + it('Testing x-amz-content-sha256 as hash', async () => { + expect(reqHeaderOverwrite['x-amz-content-sha256']({ + value: '5fd924625f6ab16a19cc9807c7c506ae1813490e4ba675f843d5a10e0baacdb8', + headers: { + host: 's3.us-west-2.amazonaws.com' + } + })).to.equal('^[a-f0-9]{64}$'); + }); +}); diff --git a/yarn.lock b/yarn.lock index 66deac46..7c7ff2bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4780,7 +4780,7 @@ safe-regex-test@^1.0.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@^1.2.4: +sax@>=0.6.0, sax@^1.2.4: version "1.3.0" resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== @@ -5506,6 +5506,19 @@ xml-js@1.6.11: dependencies: sax "^1.2.4" +xml2js@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xtend@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"