Skip to content
This repository was archived by the owner on Jan 26, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .remarkrc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
module.exports = {
plugins: ["remark-preset-lint-styleguide", "remark-preset-lint-recommended", ["remark-lint-no-html", false], ["remark-lint-no-tabs", false]]
plugins: [
"remark-preset-lint-style-guide",
"remark-preset-lint-recommended",
[
"remark-lint-no-html",
false
],
[
"remark-lint-no-tabs",
false
]
]
}
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,10 @@ _The logger must be set to be used._

## Middleware

- [JSON Body Parser](./src/middlewares/json-body-parser/README.md)
- [Http Error Handling](./src/middlewares/http-error-handler/README.md)
- [Http Header Normalizer](./src/middlewares/http-error-handler/README.md)
- [JSON Body Parser](./src/middlewares/json-body-parser/json-body-parser.README.md)
- [Http Error Handling](./src/middlewares/http-error-handler/http-error-handler.README.md)
- [Http Header Normalizer](./src/middlewares/http-error-handler/http-error-handler.README.md)
- [SSM Parameter Resolver](./src/middlewares/ssm-param-resolver/ssm-param-resolver.README.md)
- _Content Negotiation_ - [Coming soon...](https://github.com/ChocPanda/mambda/issues/4)
- _Http Query Parser_ - [Coming soon...](https://github.com/ChocPanda/mambda/issues/5)
- [...Your idea here](https://github.com/ChocPanda/mambda/issues/new)
Expand Down
1 change: 1 addition & 0 deletions ava.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default {
sources: ['./src/**'],
files: ['./src/**/__test__/**'],
failFast: false,
failWithoutAssertions: true,
verbose: true
Expand Down
7 changes: 7 additions & 0 deletions ava.integration.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
sources: ['./src/**', './integration-tests/src/**'],
files: ['./integration-tests/src/**'],
failFast: false,
failWithoutAssertions: true,
verbose: true
};
102 changes: 102 additions & 0 deletions integration-tests/integration-test-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const AWS = require('aws-sdk');
const JSZip = require("jszip");
const fs = require('fs');
const util = require('util');
const logger = console;
const iam = new AWS.IAM({ region: process.env.AWS_DEFAULT_REGION });
const readFile = util.promisify(fs.readFile);
const lambda = new AWS.Lambda({ region: process.env.AWS_DEFAULT_REGION });

const lambdaTrust = {
Version: "2012-10-17",
Statement: [
{
Effect: "Allow",
Principal: {
Service: "lambda.amazonaws.com"
},
Action: "sts:AssumeRole"
}
]
}

const withRole = (roleName, policyDoc) => async continuation => {
const fullRoleName = `${roleName}-Role`;
logger.info(`Creating role: ${fullRoleName}`);
const {
Role: {
Arn: arn
}
} = await iam.createRole({
AssumeRolePolicyDocument: JSON.stringify(lambdaTrust),
Path: "/",
RoleName: fullRoleName
}).promise();
try {
logger.info(`Created role with arn: ${arn}`);
await withPolicy(roleName, policyDoc, arn)(continuation);
} finally {
logger.info(`Deleting role`);
await iam.deleteRole({ RoleName: fullRoleName }).promise();
logger.info(`Role deleted`);
}
};

const withPolicy = (roleName, policyDoc, arn) => async continuation => {
const fullRoleName = `${roleName}-Role`;
const policyName = `${roleName}-Policy`;
logger.info(`Creating role policy: ${policyName}`);

await iam.putRolePolicy({
PolicyDocument: JSON.stringify(policyDoc),
PolicyName: policyName,
RoleName: fullRoleName
}).promise();

try {
logger.info(`Created role policy`);
await continuation(arn);
} finally {
logger.info(`Deleting role policy`);
await iam.deleteRolePolicy({
PolicyName: policyName,
RoleName: fullRoleName
}).promise();
logger.info(`Role policy deleted`);
}
};

const withLambda =
(functionName, roleArn, src = `../${functionName}.js`) =>
async continuation => {
logger.info(`Zipping lambda...`);
const zip = new JSZip();
zip.file(
`${functionName}.js`,
await readFile(src)
);
logger.info(`Zipped`);
logger.info(`Creating lambda: ${functionName}`);
const buffer = await zip.generateAsync({ type: "nodebuffer" });
const resp = await lambda.createFunction({
FunctionName: functionName,
Handler: "lambda-with-ssm-param-resolver.handler",
Runtime: "nodejs10.x",
Code: {
ZipFile: buffer
},
Role: roleArn
});
logger.info(`Lambda created ${util.inspect(resp)}`);
try {
await continuation();
} finally {
logger.info(`Deleting lambda`);
await lambda.deleteFunction({
FunctionName: functionName
});
logger.info(`Lambda deleted`);
}
};

module.exports = { withRole, withLambda };
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
const test = require('ninos')(require('ava'));
const AWS = require('aws-sdk');
const logger = console;
const { withRole, withLambda } = require('../../../../integration-test-utils');
const util = require('util');

const lambda = new AWS.Lambda({ region: process.env.AWS_DEFAULT_REGION });
const ssm = new AWS.SSM({ region: process.env.AWS_DEFAULT_REGION });

const functionName = "lambda-with-ssm-param-resolver";
const roleName = "SSM-Int-Test";

const policyDoc = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": `arn:aws:logs:${process.env.AWS_DEFAULT_REGION}:${process.env.AWS_ACCOUNT_ID}:*`
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
`arn:aws:logs:eu-west-2:447213725459:log-group:/aws/lambda/${functionName}:*`
]
},
{
"Effect": "Allow",
"Action": "ssm:GetParameters",
"Resource": "*"
},
]
}

const withSsmParams = params => async continuation => {
try {
for (const param of params) {
await ssm.putParameter(param).promise();
logger.info(`Created param with name: ${param.Name}`);
}

await continuation();
} finally {
logger.info(`Deleting parameters`);
await ssm.deleteParameters({ Names: params.map(p => p.Name) }).promise();
logger.info(`Parameters deleted`);
}
};

test('SSM Parameter Resolving Middleware - Integration test', async t => {
await withRole(
roleName,
policyDoc
)(
async roleArn => withLambda(
functionName,
roleArn,
"integration-tests/dist/index.js"
)(
async () => withSsmParams([
{
Name: "/mambda/test/A",
Type: "String",
Value: "hula"
},
{
Name: "/mambda/test/B",
Type: "StringList",
Value: "[\"hula\"]"
}
])(
async () => {

logger.info(`Invoking lambda`);
const result = await lambda.invoke({
FunctionName: functionName,
InvocationType: "RequestResponse",
Payload: JSON.stringify({})
}).promise();
logger.info(`Result of invoking lambda: ${util.inspect(result)}`);

// TODO assert we read our params back
}
)
)
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// TODO It seems that ava's sources are not added to the node resolution path.
const lambda = require('../../../../dist');
const ssmParamResolver = require('../../../../dist/middlewares/ssm-param-resolver');

const parametersToLoad = [
"/mambda/test/A",
"/mambda/test/B"
]

async function ssmParamConsumer(event) {
return {
A: event._ssmParams["/mambda/test/A"],
B: event._ssmParams["/mambda/test/B"],
};
}

exports.handler = lambda(ssmParamConsumer)
.use(ssmParamResolver({
parameterNames: parametersToLoad
}));
16 changes: 11 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,26 @@
"build": "rollup -c",
"test": "nyc ava",
"test:unit": "nyc ava",
"test:integration": "ava --config ava.integration.config.js",
"test:cov": "nyc ava && nyc report",
"test:report": "nyc ava --tap | tap-junit --output ./reports/ava --name test-results.xml",
"lint": "xo",
"lint:test": "xo",
"lint:fix": "xo --fix",
"lint:report": "xo --reporter junit > ./reports/xo/test-results.xml",
"lint:md": "remark ./README.md src/**/README.md --output",
"release": "semantic-release",
"docs-toc": "node ./scripts/update-toc.js",
"postpublish": "node ../scripts/post-publish.js"
"release": "semantic-release",
"docs-toc": "node ./scripts/update-toc.js",
"postpublish": "node ../scripts/post-publish.js"
},
"files": [
"**/index.js",
"**/*.md"
],
"dependencies": {
"http-errors": "^1.7.2"
"aws-sdk": "^2.494.0",
"http-errors": "^1.7.2",
"rollup-plugin-sourcemaps": "^0.4.2"
},
"devDependencies": {
"@semantic-release/changelog": "^3.0.2",
Expand All @@ -44,18 +47,21 @@
"codacy-coverage": "^3.4.0",
"commitizen": "^3.1.1",
"cz-conventional-changelog": "2.1.0",
"jszip": "^3.2.2",
"markdown-toc": "^1.2.0",
"ninos": "^3.0.0",
"nyc": "^14.0.0",
"path": "^0.12.7",
"remark-cli": "^6.0.1",
"remark-preset-lint-recommended": "^3.0.2",
"remark-preset-lint-styleguide": "^1.0.0",
"rewiremock": "^3.13.7",
"rollup": "^1.17.0",
"rollup-plugin-commonjs": "^10.0.0",
"rollup-plugin-copy": "^3.0.0",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-license": "^0.9.0",
"rollup-plugin-node-resolve": "^5.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"semantic-release": "^15.13.3",
"shelljs": "^0.8.3",
"shx": "^0.3.2",
Expand Down
34 changes: 29 additions & 5 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import license from 'rollup-plugin-license';
import copy from 'rollup-plugin-copy';
import json from 'rollup-plugin-json';
import builtins from 'builtin-modules';
import sourcemaps from 'rollup-plugin-sourcemaps';

const plugins = [
resolve(),
sourcemaps(),
json({}),
resolve({
preferBuiltins: true,
external: ['aws-sdk']
}),
commonjs(),
license({
banner: {
Expand Down Expand Up @@ -37,7 +45,7 @@ export default [
preferConst: true,
exports: 'default'
},
external: ['http-errors'],
external: builtins.concat(["http-errors", "aws-sdk"]),
plugins
},
// Middlewares
Expand All @@ -46,7 +54,9 @@ export default [
'json-body-parser': 'src/middlewares/json-body-parser/middleware.js',
'http-error-handler': 'src/middlewares/http-error-handler/middleware.js',
'http-header-normalizer':
'src/middlewares/http-header-normalizer/middleware.js'
'src/middlewares/http-header-normalizer/middleware.js',
'ssm-param-resolver':
'src/middlewares/ssm-param-resolver/middleware.js'
},
output: {
dir: 'dist/middlewares/',
Expand All @@ -55,7 +65,7 @@ export default [
preferConst: true,
exports: 'named'
},
external: ['http-errors'],
external: builtins.concat(["http-errors", "aws-sdk"]),
plugins
},
{
Expand All @@ -66,7 +76,21 @@ export default [
preferConst: true,
exports: 'named'
},
external: ['http-errors'],
external: builtins.concat(["http-errors", "aws-sdk"]),
plugins
},
// tests
{
input: 'integration-tests/src/middlewares/ssm-param-resolver/lambda-with-ssm-param-resolver.js',
output: {
file: 'integration-tests/dist/index.js',
format: 'cjs',
preferConst: true,
exports: 'named',
sourceMap: true
},
// TODO Their must be a
external: builtins.concat(["aws-sdk"]),
plugins
}
];
Loading