Skip to content

Instantly share code, notes, and snippets.

@jewelsjacobs
Created August 2, 2019 16:27
Show Gist options
  • Select an option

  • Save jewelsjacobs/3ad1e8025c87b917ea73e4b6fa025489 to your computer and use it in GitHub Desktop.

Select an option

Save jewelsjacobs/3ad1e8025c87b917ea73e4b6fa025489 to your computer and use it in GitHub Desktop.
ssmPutParam lambda
const aws = require('aws-sdk');
const ssm = new aws.SSM();
const https = require('https');
const { URL } = require('url');
/**
* Upload a CloudFormation response object to S3.
*
* @param {object} event the Lambda event payload received by the handler function
* @param {object} context the Lambda context received by the handler function
* @param {string} responseStatus the response status, either 'SUCCESS' or 'FAILED'
* @param {string} physicalResourceId CloudFormation physical resource ID
* @param {object} [responseData] arbitrary response data object
* @param {string} [reason] reason for failure, if any, to convey to the user
* @returns {Promise} Promise that is resolved on success, or rejected on connection error or HTTP error response
*/
const report = (event, context, responseStatus, physicalResourceId, responseData, reason) =>
new Promise((resolve, reject) => {
const responseBody = JSON.stringify({
Status: responseStatus,
Reason: reason,
PhysicalResourceId: physicalResourceId || context.logStreamName,
StackId: event.StackId,
RequestId: event.RequestId,
LogicalResourceId: event.LogicalResourceId,
Data: responseData,
});
const parsedUrl = new URL(event.ResponseURL);
const options = {
hostname: parsedUrl.hostname,
port: 443,
path: parsedUrl.pathname + parsedUrl.search,
method: 'PUT',
headers: {
'Content-Type': '',
'Content-Length': responseBody.length,
},
};
https
.request(options)
.on('error', reject)
.on('response', res => {
res.resume();
if (res.statusCode >= 400) {
reject(new Error(`Server returned error ${res.statusCode}: ${res.statusMessage}`));
} else {
resolve();
}
})
.end(responseBody, 'utf8');
});
/**
* Main handler, invoked by Lambda
*/
exports.handler = async (event, context) => {
const responseData = {};
let physicalResourceId;
try {
switch (event.RequestType) {
case 'Create':
case 'Update':
responseData.Version = await createSecret(event.ResourceProperties.Name, event.ResourceProperties.Value);
physicalResourceId = await getSecret(event.ResourceProperties.Name);
break;
case 'Delete':
physicalResourceId = event.PhysicalResourceId;
// If the resource didn't create correctly, the physical resource ID won't be the
// parameter ARN, so don't try to delete it in that case.
if (physicalResourceId.startsWith('arn:')) {
await deleteSecret(event.ResourceProperties.Name);
}
break;
default:
throw new Error(`Unsupported request type ${event.RequestType}`);
}
console.log(`Uploading SUCCESS response to S3...`);
await report(event, context, 'SUCCESS', physicalResourceId, responseData);
console.log('Done.');
} catch (err) {
console.log(`Caught error ${err}. Uploading FAILED message to S3.`);
await report(event, context, 'FAILED', null, physicalResourceId, err.message);
}
};
/**
* Puts an environment value in the paramater store
*
* @param {*} name name of secret, Ie: '/Development/KhComponents/components/Domain'
* @param {*} value value of secret
* @returns {Promise}
*/
const createSecret = async (name, value) => {
console.log(`Creating secret ${name}`);
try {
const parameterData = await ssm
.putParameter({
Name: name,
Type: 'SecureString',
Value: value,
Overwrite: true,
})
.promise();
return parameterData.Version;
} catch (err) {
if (err) {
throw err;
} else {
return true;
}
}
};
/**
* Deletes parameter
*
* @param {*} name name of secret, Ie: '/Development/KhComponents/components/Domain'
*/
const deleteSecret = async name => {
console.log(`Deleting secret ${name}`);
try {
await ssm.deleteParameter({ Name: name }).promise();
} catch (err) {
if (err.code !== 'ResourceNotFoundException') {
throw err;
}
}
};
/**
* Get parameter information
*
* @param {*} name name of secret, Ie: '/Development/KhComponents/components/Domain'
*/
const getSecret = async name => {
console.log(`Getting secret ${name}`);
try {
const parameterData = await ssm
.getParameter({
Name: name,
})
.promise();
return parameterData.Parameter.ARN;
} catch (err) {
if (err.code !== 'ResourceNotFoundException') {
throw err;
} else {
return true;
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment