From 415af8e2e32929472665e0a470af1eb4a98ec5e4 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Mon, 8 May 2023 15:54:32 -0400 Subject: [PATCH 1/6] fix(NODE-5260): AWS Lambda metadata detection logic is too permissive --- src/cmap/handshake/client_metadata.ts | 3 ++- .../mongodb-handshake.prose.test.ts | 5 +++++ test/unit/cmap/handshake/client_metadata.test.ts | 15 +++++++++------ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/cmap/handshake/client_metadata.ts b/src/cmap/handshake/client_metadata.ts index ab66328ca5..fb1ba40b14 100644 --- a/src/cmap/handshake/client_metadata.ts +++ b/src/cmap/handshake/client_metadata.ts @@ -176,7 +176,8 @@ export function getFAASEnv(): Map | null { VERCEL_REGION = '' } = process.env; - const isAWSFaaS = AWS_EXECUTION_ENV.length > 0 || AWS_LAMBDA_RUNTIME_API.length > 0; + const isAWSFaaS = + AWS_EXECUTION_ENV.startsWith('AWS_Lambda_') || AWS_LAMBDA_RUNTIME_API.length > 0; const isAzureFaaS = FUNCTIONS_WORKER_RUNTIME.length > 0; const isGCPFaaS = K_SERVICE.length > 0 || FUNCTION_NAME.length > 0; const isVercelFaaS = VERCEL.length > 0; diff --git a/test/integration/mongodb-handshake/mongodb-handshake.prose.test.ts b/test/integration/mongodb-handshake/mongodb-handshake.prose.test.ts index ba4c714f35..f1fe5553f7 100644 --- a/test/integration/mongodb-handshake/mongodb-handshake.prose.test.ts +++ b/test/integration/mongodb-handshake/mongodb-handshake.prose.test.ts @@ -70,6 +70,11 @@ describe('Handshake Prose Tests', function () { ['AWS_EXECUTION_ENV', 'AWS_Lambda_java8'], ['AWS_LAMBDA_FUNCTION_MEMORY_SIZE', 'big'] ] + }, + { + expectedProvider: undefined, + context: '8. Invalid - AWS_EXECUTION_ENV does not start with "AWS_Lambda_"', + env: [['AWS_EXECUTION_ENV', 'EC2']] } ]; diff --git a/test/unit/cmap/handshake/client_metadata.test.ts b/test/unit/cmap/handshake/client_metadata.test.ts index 3e96df7c6f..f21b65ca1e 100644 --- a/test/unit/cmap/handshake/client_metadata.test.ts +++ b/test/unit/cmap/handshake/client_metadata.test.ts @@ -50,6 +50,9 @@ describe('client metadata module', () => { context(`when ${envVariable} is in the environment`, () => { before(() => { process.env[envVariable] = 'non empty string'; + if (envVariable === 'AWS_EXECUTION_ENV') { + process.env[envVariable] = 'AWS_Lambda_non empty string'; + } }); after(() => { delete process.env[envVariable]; @@ -70,7 +73,7 @@ describe('client metadata module', () => { context('unrelated environments', () => { before(() => { // aws - process.env.AWS_EXECUTION_ENV = 'non-empty-string'; + process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_non-empty-string'; // azure process.env.FUNCTIONS_WORKER_RUNTIME = 'non-empty-string'; }); @@ -384,7 +387,7 @@ describe('client metadata module', () => { aws: [ { context: 'no additional metadata', - env: [['AWS_EXECUTION_ENV', 'non-empty string']], + env: [['AWS_EXECUTION_ENV', 'AWS_Lambda_non-empty string']], outcome: { name: 'aws.lambda' } @@ -392,7 +395,7 @@ describe('client metadata module', () => { { context: 'AWS_REGION provided', env: [ - ['AWS_EXECUTION_ENV', 'non-empty string'], + ['AWS_EXECUTION_ENV', 'AWS_Lambda_non-empty string'], ['AWS_REGION', 'non-null'] ], outcome: { @@ -403,7 +406,7 @@ describe('client metadata module', () => { { context: 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE provided', env: [ - ['AWS_EXECUTION_ENV', 'non-empty string'], + ['AWS_EXECUTION_ENV', 'AWS_Lambda_non-empty string'], ['AWS_LAMBDA_FUNCTION_MEMORY_SIZE', '3'] ], outcome: { @@ -526,7 +529,7 @@ describe('client metadata module', () => { context('when faas region is too large', () => { beforeEach('1. Omit fields from `env` except `env.name`.', () => { sinon.stub(process, 'env').get(() => ({ - AWS_EXECUTION_ENV: 'iLoveJavaScript', + AWS_EXECUTION_ENV: 'AWS_Lambda_iLoveJavaScript', AWS_REGION: 'a'.repeat(512) })); }); @@ -543,7 +546,7 @@ describe('client metadata module', () => { context('release too large', () => { beforeEach('2. Omit fields from `os` except `os.type`.', () => { sinon.stub(process, 'env').get(() => ({ - AWS_EXECUTION_ENV: 'iLoveJavaScript', + AWS_EXECUTION_ENV: 'AWS_Lambda_iLoveJavaScript', AWS_REGION: 'abc' })); sinon.stub(os, 'release').returns('a'.repeat(512)); From 6b633bccce4d56dadd452dce5e1b711bd481bafa Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Tue, 9 May 2023 13:10:54 -0400 Subject: [PATCH 2/6] non-empty_string --- .../cmap/handshake/client_metadata.test.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/unit/cmap/handshake/client_metadata.test.ts b/test/unit/cmap/handshake/client_metadata.test.ts index f21b65ca1e..bba3f42b10 100644 --- a/test/unit/cmap/handshake/client_metadata.test.ts +++ b/test/unit/cmap/handshake/client_metadata.test.ts @@ -49,9 +49,9 @@ describe('client metadata module', () => { for (const [envVariable, provider] of tests) { context(`when ${envVariable} is in the environment`, () => { before(() => { - process.env[envVariable] = 'non empty string'; + process.env[envVariable] = 'non_empty_string'; if (envVariable === 'AWS_EXECUTION_ENV') { - process.env[envVariable] = 'AWS_Lambda_non empty string'; + process.env[envVariable] = 'AWS_Lambda_non_empty_string'; } }); after(() => { @@ -73,9 +73,9 @@ describe('client metadata module', () => { context('unrelated environments', () => { before(() => { // aws - process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_non-empty-string'; + process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_non_empty_string'; // azure - process.env.FUNCTIONS_WORKER_RUNTIME = 'non-empty-string'; + process.env.FUNCTIONS_WORKER_RUNTIME = 'non_empty_string'; }); after(() => { delete process.env.AWS_EXECUTION_ENV; @@ -89,10 +89,10 @@ describe('client metadata module', () => { context('vercel and aws which share env variables', () => { before(() => { // vercel - process.env.VERCEL = 'non-empty-string'; + process.env.VERCEL = 'non_empty_string'; // aws - process.env.AWS_EXECUTION_ENV = 'non-empty-string'; - process.env.AWS_LAMBDA_RUNTIME_API = 'non-empty-string'; + process.env.AWS_EXECUTION_ENV = 'non_empty_string'; + process.env.AWS_LAMBDA_RUNTIME_API = 'non_empty_string'; }); after(() => { delete process.env.VERCEL; @@ -387,7 +387,7 @@ describe('client metadata module', () => { aws: [ { context: 'no additional metadata', - env: [['AWS_EXECUTION_ENV', 'AWS_Lambda_non-empty string']], + env: [['AWS_EXECUTION_ENV', 'AWS_Lambda_non_empty_string']], outcome: { name: 'aws.lambda' } @@ -395,7 +395,7 @@ describe('client metadata module', () => { { context: 'AWS_REGION provided', env: [ - ['AWS_EXECUTION_ENV', 'AWS_Lambda_non-empty string'], + ['AWS_EXECUTION_ENV', 'AWS_Lambda_non_empty_string'], ['AWS_REGION', 'non-null'] ], outcome: { @@ -406,7 +406,7 @@ describe('client metadata module', () => { { context: 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE provided', env: [ - ['AWS_EXECUTION_ENV', 'AWS_Lambda_non-empty string'], + ['AWS_EXECUTION_ENV', 'AWS_Lambda_non_empty_string'], ['AWS_LAMBDA_FUNCTION_MEMORY_SIZE', '3'] ], outcome: { @@ -510,7 +510,7 @@ describe('client metadata module', () => { context('when a numeric FAAS env variable is not numerically parsable', () => { before(() => { - process.env.AWS_EXECUTION_ENV = 'non-empty-string'; + process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_non_empty_string'; process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '123not numeric'; }); From af4b167bed18ca01dc1dc7a6fd90cc5be18cd485 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Tue, 9 May 2023 14:05:35 -0400 Subject: [PATCH 3/6] show env value, add unit test for AWS_EXECUTION_ENV startsWith --- .../cmap/handshake/client_metadata.test.ts | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/test/unit/cmap/handshake/client_metadata.test.ts b/test/unit/cmap/handshake/client_metadata.test.ts index bba3f42b10..b60824000d 100644 --- a/test/unit/cmap/handshake/client_metadata.test.ts +++ b/test/unit/cmap/handshake/client_metadata.test.ts @@ -37,22 +37,19 @@ describe('client metadata module', () => { }); }); - describe('getFAASEnv()', function () { - const tests: Array<[string, string]> = [ - ['AWS_EXECUTION_ENV', 'aws.lambda'], - ['AWS_LAMBDA_RUNTIME_API', 'aws.lambda'], - ['FUNCTIONS_WORKER_RUNTIME', 'azure.func'], - ['K_SERVICE', 'gcp.func'], - ['FUNCTION_NAME', 'gcp.func'], - ['VERCEL', 'vercel'] + describe.only('getFAASEnv()', function () { + const tests: Array<[envVariable: string, envValue: string, provider: string]> = [ + ['AWS_EXECUTION_ENV', 'AWS_Lambda_non_empty_string', 'aws.lambda'], + ['AWS_LAMBDA_RUNTIME_API', 'non_empty_string', 'aws.lambda'], + ['FUNCTIONS_WORKER_RUNTIME', 'non_empty_string', 'azure.func'], + ['K_SERVICE', 'non_empty_string', 'gcp.func'], + ['FUNCTION_NAME', 'non_empty_string', 'gcp.func'], + ['VERCEL', 'non_empty_string', 'vercel'] ]; - for (const [envVariable, provider] of tests) { - context(`when ${envVariable} is in the environment`, () => { + for (const [envVariable, envValue, provider] of tests) { + context(`when ${envVariable} is set to "${envValue}" in the environment`, () => { before(() => { - process.env[envVariable] = 'non_empty_string'; - if (envVariable === 'AWS_EXECUTION_ENV') { - process.env[envVariable] = 'AWS_Lambda_non_empty_string'; - } + process.env[envVariable] = envValue; }); after(() => { delete process.env[envVariable]; @@ -63,6 +60,18 @@ describe('client metadata module', () => { }); } + context('when AWS_EXECUTION_ENV does not start with "AWS_Lambda_"', () => { + before(() => { + process.env.AWS_EXECUTION_ENV = 'AWS_LambdaIncorrectStartString'; + }); + after(() => { + delete process.env.AWS_EXECUTION_ENV; + }); + it('returns null', () => { + expect(getFAASEnv()).to.be.null; + }); + }); + context('when there is no FAAS provider data in the env', () => { it('returns null', () => { expect(getFAASEnv()).to.be.null; From 6baa7bbc98635eb00e87e52e862146a9aa31ac6d Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Tue, 9 May 2023 14:05:44 -0400 Subject: [PATCH 4/6] only --- test/unit/cmap/handshake/client_metadata.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/cmap/handshake/client_metadata.test.ts b/test/unit/cmap/handshake/client_metadata.test.ts index b60824000d..7f5af95a1d 100644 --- a/test/unit/cmap/handshake/client_metadata.test.ts +++ b/test/unit/cmap/handshake/client_metadata.test.ts @@ -37,7 +37,7 @@ describe('client metadata module', () => { }); }); - describe.only('getFAASEnv()', function () { + describe('getFAASEnv()', function () { const tests: Array<[envVariable: string, envValue: string, provider: string]> = [ ['AWS_EXECUTION_ENV', 'AWS_Lambda_non_empty_string', 'aws.lambda'], ['AWS_LAMBDA_RUNTIME_API', 'non_empty_string', 'aws.lambda'], From 873ed1767ac53ec37cf269535a3705821d725baf Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Tue, 9 May 2023 16:04:25 -0400 Subject: [PATCH 5/6] tests --- .../cmap/handshake/client_metadata.test.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/test/unit/cmap/handshake/client_metadata.test.ts b/test/unit/cmap/handshake/client_metadata.test.ts index 7f5af95a1d..dbd5e54dea 100644 --- a/test/unit/cmap/handshake/client_metadata.test.ts +++ b/test/unit/cmap/handshake/client_metadata.test.ts @@ -39,7 +39,6 @@ describe('client metadata module', () => { describe('getFAASEnv()', function () { const tests: Array<[envVariable: string, envValue: string, provider: string]> = [ - ['AWS_EXECUTION_ENV', 'AWS_Lambda_non_empty_string', 'aws.lambda'], ['AWS_LAMBDA_RUNTIME_API', 'non_empty_string', 'aws.lambda'], ['FUNCTIONS_WORKER_RUNTIME', 'non_empty_string', 'azure.func'], ['K_SERVICE', 'non_empty_string', 'gcp.func'], @@ -47,7 +46,7 @@ describe('client metadata module', () => { ['VERCEL', 'non_empty_string', 'vercel'] ]; for (const [envVariable, envValue, provider] of tests) { - context(`when ${envVariable} is set to "${envValue}" in the environment`, () => { + context(`when ${envVariable} is set to a non-empty string`, () => { before(() => { process.env[envVariable] = envValue; }); @@ -57,9 +56,33 @@ describe('client metadata module', () => { it('determines the correct provider', () => { expect(getFAASEnv()?.get('name')).to.equal(provider); }); + + context(`when ${envVariable} is set to an empty string`, () => { + before(() => { + process.env[envVariable] = ''; + }); + after(() => { + delete process.env[envVariable]; + }); + it('returns null', () => { + expect(getFAASEnv()).to.be.null; + }); + }); }); } + context('when AWS_EXECUTION_ENV starts with "AWS_Lambda_"', () => { + before(() => { + process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_correctStartString'; + }); + after(() => { + delete process.env.AWS_EXECUTION_ENV; + }); + it('indicates the runtime is aws lambda', () => { + expect(getFAASEnv()?.get('name')).to.equal('aws.lambda'); + }); + }); + context('when AWS_EXECUTION_ENV does not start with "AWS_Lambda_"', () => { before(() => { process.env.AWS_EXECUTION_ENV = 'AWS_LambdaIncorrectStartString'; From 664e9175a34e811300a01b39c4fe2b4e93293d5b Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Tue, 9 May 2023 16:10:13 -0400 Subject: [PATCH 6/6] rm envValue --- test/unit/cmap/handshake/client_metadata.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/unit/cmap/handshake/client_metadata.test.ts b/test/unit/cmap/handshake/client_metadata.test.ts index dbd5e54dea..9ef228c1b9 100644 --- a/test/unit/cmap/handshake/client_metadata.test.ts +++ b/test/unit/cmap/handshake/client_metadata.test.ts @@ -38,17 +38,17 @@ describe('client metadata module', () => { }); describe('getFAASEnv()', function () { - const tests: Array<[envVariable: string, envValue: string, provider: string]> = [ - ['AWS_LAMBDA_RUNTIME_API', 'non_empty_string', 'aws.lambda'], - ['FUNCTIONS_WORKER_RUNTIME', 'non_empty_string', 'azure.func'], - ['K_SERVICE', 'non_empty_string', 'gcp.func'], - ['FUNCTION_NAME', 'non_empty_string', 'gcp.func'], - ['VERCEL', 'non_empty_string', 'vercel'] + const tests: Array<[envVariable: string, provider: string]> = [ + ['AWS_LAMBDA_RUNTIME_API', 'aws.lambda'], + ['FUNCTIONS_WORKER_RUNTIME', 'azure.func'], + ['K_SERVICE', 'gcp.func'], + ['FUNCTION_NAME', 'gcp.func'], + ['VERCEL', 'vercel'] ]; - for (const [envVariable, envValue, provider] of tests) { + for (const [envVariable, provider] of tests) { context(`when ${envVariable} is set to a non-empty string`, () => { before(() => { - process.env[envVariable] = envValue; + process.env[envVariable] = 'non_empty_string'; }); after(() => { delete process.env[envVariable];