Skip to content

Commit d979fe5

Browse files
Add test for Sdk instrumentation patch
1 parent 0640d9f commit d979fe5

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

aws-distro-opentelemetry-node-autoinstrumentation/test/patches/instrumentation-patch.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
TextMapSetter,
1515
INVALID_SPAN_CONTEXT,
1616
SpanStatusCode,
17+
ROOT_CONTEXT,
1718
} from '@opentelemetry/api';
1819
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
1920
import { Instrumentation } from '@opentelemetry/instrumentation';
@@ -692,6 +693,60 @@ describe('InstrumentationPatchTest', () => {
692693
});
693694
});
694695

696+
it('Prevents recursion when credentials provider makes STS calls', async () => {
697+
// Track credentials provider calls and skip flag state
698+
let credentialsProviderCallCount = 0;
699+
let skipCredentialCaptureValue = false;
700+
701+
// Mock span for attribute capture
702+
const mockSpan = { setAttribute: sinon.stub() };
703+
sinon.stub(trace, 'getSpan').returns(mockSpan as unknown as Span);
704+
705+
// Patch ROOT_CONTEXT to capture setValue calls
706+
const originalSetValue = ROOT_CONTEXT.setValue;
707+
ROOT_CONTEXT.setValue = (key: symbol, value: any) => {
708+
if (key.toString().includes('skip-credential-capture')) {
709+
skipCredentialCaptureValue = value;
710+
}
711+
return ROOT_CONTEXT;
712+
};
713+
sinon.stub(context, 'active').returns(ROOT_CONTEXT);
714+
715+
// Capture middleware added to stack
716+
const middlewareStack: any[] = [];
717+
const recursiveSdkSend = extractAwsSdkInstrumentation(PATCHED_INSTRUMENTATIONS)
718+
['_getV3SmithyClientSendPatch'](() => Promise.resolve())
719+
.bind({
720+
middlewareStack: { add: (middleware: any, config: any) => middlewareStack.push([middleware, config]) },
721+
config: {
722+
// Credentials provider that recursively calls SDK (simulates STS)
723+
credentials: async () => {
724+
credentialsProviderCallCount++;
725+
await recursiveSdkSend({}, null);
726+
return { accessKeyId: 'test-access-key' };
727+
},
728+
region: () => Promise.resolve('us-west-2'),
729+
},
730+
});
731+
732+
// Initial SDK call triggers middleware setup
733+
await recursiveSdkSend({}, null);
734+
735+
// Execute credentials extraction middleware
736+
await middlewareStack[1][0](() => Promise.resolve(), null)({});
737+
738+
// Verify recursion prevention: only one credentials call despite recursive setup
739+
expect(credentialsProviderCallCount).toBe(1);
740+
expect(skipCredentialCaptureValue).toBe(true);
741+
expect(
742+
mockSpan.setAttribute.calledWith(AWS_ATTRIBUTE_KEYS.AWS_AUTH_ACCOUNT_ACCESS_KEY, 'test-access-key')
743+
).toBeTruthy();
744+
745+
// Restore original setValue
746+
ROOT_CONTEXT.setValue = originalSetValue;
747+
sinon.restore();
748+
});
749+
695750
it('injects trace context header into request via propagator', async () => {
696751
lambda = new Lambda({
697752
region: region,

0 commit comments

Comments
 (0)