Created
August 2, 2019 16:27
-
-
Save jewelsjacobs/3ad1e8025c87b917ea73e4b6fa025489 to your computer and use it in GitHub Desktop.
ssmPutParam lambda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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