diff --git a/bin/binary-config.js b/bin/binary-config.js index 846272a2..460611a2 100644 --- a/bin/binary-config.js +++ b/bin/binary-config.js @@ -17,8 +17,6 @@ let config = { // Don't manually include runtimes/deno.js in scripts, as it fails on pkg#997 scripts: [ '../node_modules/@architect/inventory/**/*.js', - // Utils now has a child process-executed script for checking credentials - '../node_modules/@architect/utils/**/*.js', '../node_modules/dynalite/**/*.js', // This line is only necessary when testing RC releases of Inventory, do NOT use it in production binary builds of Sandbox: '../node_modules/**/@architect/inventory/**/*.js', diff --git a/package.json b/package.json index f663ec7f..88cf21f1 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@architect/create": "~4.2.3", "@architect/hydrate": "~3.4.1", "@architect/inventory": "~3.6.2", - "@architect/utils": "~4.0.0-RC.0", + "@architect/utils": "~4.0.0-RC.1", "@aws-lite/client": "~0.11.1", "@aws-lite/dynamodb": "~0.2.2", "@begin/hashid": "~1.0.0", diff --git a/src/cli/arc.js b/src/cli/arc.js index 3b266ee5..d0e43861 100644 --- a/src/cli/arc.js +++ b/src/cli/arc.js @@ -6,10 +6,8 @@ let cli = require('./index.js') */ module.exports = function arcCalling ({ inventory }) { cli({ - checkCreds: false, disableBanner: true, inventory, - needsValidCreds: false, runtimeCheck: 'warn', }, function _done (err) { diff --git a/src/http/middleware/_fallback.js b/src/http/middleware/_fallback.js index 9bc39e5c..567f0919 100644 --- a/src/http/middleware/_fallback.js +++ b/src/http/middleware/_fallback.js @@ -12,7 +12,7 @@ let httpProxy = require('http-proxy') * - Error out */ module.exports = function fallback (args, req, res, next) { - let { apiType, cwd, inventory, ports, staticPath, update } = args + let { apiType, creds, cwd, inventory, ports, staticPath, update } = args let { inv, get } = inventory let httpAPI = apiType.startsWith('http') let method = req.method.toLowerCase() @@ -111,6 +111,7 @@ module.exports = function fallback (args, req, res, next) { let name = `${rootParam[0]} /${rootParam[1]}` let lambda = get.http(name) let exec = invoker({ + creds, cwd, lambda, apiType, @@ -144,6 +145,7 @@ module.exports = function fallback (args, req, res, next) { function invokeProxy (src, arcStaticAssetProxy) { let exec = invoker({ apiType, + creds, cwd, lambda: { name: 'get /*', diff --git a/src/invoke-lambda/env/index.js b/src/invoke-lambda/env/index.js index 785b7f1f..8cced7d7 100644 --- a/src/invoke-lambda/env/index.js +++ b/src/invoke-lambda/env/index.js @@ -5,10 +5,11 @@ let { version } = require('../../../package.json') // Assemble Lambda-specific execution environment variables module.exports = function getEnv (params, requestID) { - let { apiType, cwd, lambda, host, inventory, ports, staticPath } = params + let { apiType, creds, cwd, lambda, host, inventory, ports, staticPath } = params + let { accessKeyId, secretAccessKey, sessionToken } = creds let { config, src, build, handlerFile } = lambda let { inv } = inventory - let { AWS_ACCESS_KEY_ID, AWS_PROFILE, AWS_REGION, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, PATH } = process.env + let { AWS_PROFILE, AWS_REGION, PATH } = process.env let lambdaContext = getContext(params) let envVars = userEnvVars(params) @@ -23,7 +24,7 @@ module.exports = function getEnv (params, requestID) { // Runtime environment variables let env = { // AWS-specific - AWS_ACCESS_KEY_ID: AWS_ACCESS_KEY_ID || 'arc_dummy_access_key', + AWS_ACCESS_KEY_ID: accessKeyId, AWS_LAMBDA_FUNCTION_MEMORY_SIZE: lambda.config.memory, AWS_LAMBDA_FUNCTION_NAME: `@${lambda.pragma} ${lambda.name}`, AWS_LAMBDA_FUNCTION_VERSION: '$latest', @@ -31,8 +32,8 @@ module.exports = function getEnv (params, requestID) { AWS_PROFILE, AWS_REGION, AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE: true, // Sigh. - AWS_SECRET_ACCESS_KEY: AWS_SECRET_ACCESS_KEY || 'arc_dummy_secret_key', - AWS_SESSION_TOKEN, + AWS_SECRET_ACCESS_KEY: secretAccessKey, + AWS_SESSION_TOKEN: sessionToken, LAMBDA_TASK_ROOT: src, TZ: 'UTC', // Internal for handler bootstrap diff --git a/src/sandbox/creds.js b/src/sandbox/creds.js new file mode 100644 index 00000000..1a4df1c0 --- /dev/null +++ b/src/sandbox/creds.js @@ -0,0 +1,25 @@ +let awsLite = require('@aws-lite/client') +module.exports = function loadCreds (params, callback) { + let { inventory } = params + awsLite({ + autoloadPlugins: false, + profile: inventory.inv?.aws?.profile, + region: 'us-west-1', + }) + .then(aws => { + params.creds = { + // secretAccessKey + sessionToken are non-enumerable, so we can't just ref or spread + accessKeyId: aws.credentials.accessKeyId, + secretAccessKey: aws.credentials.secretAccessKey, + sessionToken: aws.credentials.sessionToken, + } + callback() + }) + .catch(() => { + params.creds = { + accessKeyId: 'arc_dummy_access_key', + secretAccessKey: 'arc_dummy_secret_key', + } + callback() + }) +} diff --git a/src/sandbox/index.js b/src/sandbox/index.js index 63217126..d330b344 100644 --- a/src/sandbox/index.js +++ b/src/sandbox/index.js @@ -3,6 +3,7 @@ let series = require('run-series') let create = require('@architect/create') let env = require('./env') +let creds = require('./creds') let ports = require('./ports') let checkRuntimes = require('./check-runtimes') let maybeHydrate = require('./maybe-hydrate') @@ -27,6 +28,11 @@ function _start (params, callback) { env(params, callback) }, + // Load credentials + function (callback) { + creds(params, callback) + }, + // Get the ports for services function (callback) { ports(params, callback) diff --git a/src/sandbox/seed.js b/src/sandbox/seed.js index 8da18221..b5f2d8db 100644 --- a/src/sandbox/seed.js +++ b/src/sandbox/seed.js @@ -5,7 +5,7 @@ let getDBClient = require('../tables/_get-db-client') module.exports = function startupSeedData (params, callback) { let { ARC_ENV } = process.env - let { cwd, inventory, update, ports } = params + let { creds, cwd, inventory, update, ports } = params let { inv, get } = inventory let { app, tables } = inv if (!tables || ARC_ENV !== 'testing') return callback() @@ -54,7 +54,7 @@ module.exports = function startupSeedData (params, callback) { }) }).filter(Boolean) - getDBClient(ports, (err, aws) => { + getDBClient({ creds, ports }, (err, aws) => { if (err) callback(err) else { dynamo = aws.DynamoDB diff --git a/src/tables/_get-db-client.js b/src/tables/_get-db-client.js index 72cfd76e..0eafb7a1 100644 --- a/src/tables/_get-db-client.js +++ b/src/tables/_get-db-client.js @@ -1,19 +1,13 @@ let { join } = require('path') let awsLite = require('@aws-lite/client') -module.exports = function initDynamoClient (ports, callback) { - /** - * Final DynamoDB credentials backstop - * - Assumes credentials are loaded via aws-lite - * - Populate AWS-specific env vars necessary to mock Lambda + make SDK calls if not already loaded - * - Only AWS_SECRET_ACCESS_KEY + AWS_ACCESS_KEY_ID are technically required to mock Lambda - */ - let plugins = [] - // Binary dist mode - if (process.pkg) { - plugins.push(join(__dirname, '_aws-lite-dynamodb-vendor.js')) - } - else plugins.push('@aws-lite/dynamodb') +module.exports = function initDynamoClient ({ creds, ports }, callback) { + let plugins = [ + // Binary dist mode + process.pkg + ? join(__dirname, '_aws-lite-dynamodb-vendor.js') + : '@aws-lite/dynamodb' + ] let config = { autoloadPlugins: false, host: 'localhost', @@ -21,24 +15,9 @@ module.exports = function initDynamoClient (ports, callback) { port: ports.tables, protocol: 'http', region: process.env.AWS_REGION || 'us-west-2', - } - function go (aws) { - if (!process.env.AWS_ACCESS_KEY_ID) { - process.env.AWS_ACCESS_KEY_ID = aws.credentials.accessKeyId - } - if (!process.env.AWS_SECRET_ACCESS_KEY) { - process.env.AWS_SECRET_ACCESS_KEY = aws.credentials.secretAccessKey - } - callback(null, aws) + ...creds, } awsLite(config) - .then(go) - .catch(err => { - if (err.message.match(/You must supply AWS credentials/)) { - config.accessKeyId = 'arc_dummy_access_key' - config.secretAccessKey = 'arc_dummy_secret_key' - awsLite(config).then(go).catch(callback) - } - else callback(err) - }) + .then(client => callback(null, client)) + .catch(callback) } diff --git a/src/tables/_init.js b/src/tables/_init.js index b6016fad..a63d5843 100644 --- a/src/tables/_init.js +++ b/src/tables/_init.js @@ -2,8 +2,8 @@ let getDBClient = require('./_get-db-client') let createTables = require('./create-table') // Just a thin passthrough to enable the abstraction of getDBClient (for testing) -module.exports = function init ({ inventory, ports }, callback) { - getDBClient(ports, (err, aws) => { +module.exports = function init ({ creds, inventory, ports }, callback) { + getDBClient({ creds, ports }, (err, aws) => { if (err) return callback(err) createTables({ aws, inventory, ports }, callback) }) diff --git a/test/integration/tables-test.js b/test/integration/tables-test.js index 9c279551..732f246a 100644 --- a/test/integration/tables-test.js +++ b/test/integration/tables-test.js @@ -6,7 +6,7 @@ let getDBClient = require(join(process.cwd(), 'src', 'tables', '_get-db-client') let TableName = 'mockapp-production-accounts' let TableName2 = 'mockapp-production-pets' let mock = join(process.cwd(), 'test', 'mock') -let { run, startup, shutdown } = require('../utils') +let { credentials: creds, run, startup, shutdown } = require('../utils') let str = s => JSON.stringify(s, null, 2) let dynamo let tablesPort = 5555 @@ -45,7 +45,7 @@ function runTests (runType, t) { t.test(`${mode} Get client`, t => { t.plan(1) - getDBClient(ports, function _gotDBClient (err, client) { + getDBClient({ creds, ports }, function _gotDBClient (err, client) { if (err) console.log(err) // Yes, but actually no dynamo = client.DynamoDB t.ok(dynamo, 'Got Dynamo client') @@ -267,7 +267,7 @@ function runTests (runType, t) { t.test(`${mode} Get client (external DB)`, t => { t.plan(1) setup(t, externalDBPort) - getDBClient({ tables: externalDBPort }, function _gotDBClient (err, client) { + getDBClient({ creds, ports: { tables: externalDBPort } }, function _gotDBClient (err, client) { if (err) console.log(err) // Yes, but actually no dynamo = client.DynamoDB t.ok(dynamo, 'Got Dynamo client') diff --git a/test/unit/src/invoke-lambda/index-test.js b/test/unit/src/invoke-lambda/index-test.js index 642280e3..ea4cd1de 100644 --- a/test/unit/src/invoke-lambda/index-test.js +++ b/test/unit/src/invoke-lambda/index-test.js @@ -6,6 +6,7 @@ let update = require('@architect/utils').updater() let cwd = process.cwd() let mock = join(cwd, 'test', 'mock') let { invocations } = require(join(cwd, 'src', 'arc', '_runtime-api')) +let { credentials: creds } = require(join(cwd, 'test', 'utils')) let runtimes = { asap: 0, @@ -36,7 +37,7 @@ let event = { something: 'happened' } let inventory = { inv: { _project: { env: { local: { testing: null, staging: null, production: null } } }, app: 'hi' } } let ports = {} let userEnv = {} -let params = { event, inventory, update, userEnv, ports } +let params = { creds, event, inventory, update, userEnv, ports } let inv let get diff --git a/test/unit/src/sandbox-test.js b/test/unit/src/sandbox-test.js index 08ba6b31..0e2c2066 100644 --- a/test/unit/src/sandbox-test.js +++ b/test/unit/src/sandbox-test.js @@ -83,7 +83,7 @@ test('Sandbox uses continuation passing', t => { ]) }) -// Standard env vars that may be populated during a banner / AWS init +// Nothing should be mutating these, but reset them jic! let envVars = [ 'ARC_APP_NAME', 'ARC_AWS_CREDS',