Last active
February 5, 2019 16:15
-
-
Save talawahtech/4827c773df7d0032f64b1d6be79197d3 to your computer and use it in GitHub Desktop.
Generates a random password using SecretsManager.getRandomPassword() and stores it in the Parameter Store
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
AWSTemplateFormatVersion: '2010-09-09' | |
Description: 'Generates a random password and stores it in the SSM Parameter Store' | |
Resources: | |
PasswordGeneratorRole: | |
Type: 'AWS::IAM::Role' | |
Properties: | |
Path: '/' | |
ManagedPolicyArns: ['arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'] | |
Policies: | |
- PolicyName: 'GeneratePassword' | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: 'secretsmanager:GetRandomPassword' | |
Resource: '*' | |
- PolicyName: 'CreateSsmParams' | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: ['ssm:PutParameter', 'ssm:DeleteParameter', 'kms:Encrypt'] | |
Resource: "*" | |
AssumeRolePolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: 'lambda.amazonaws.com' | |
Action: 'sts:AssumeRole' | |
PasswordGeneratorLambda: | |
Type: 'AWS::Lambda::Function' | |
Properties: | |
Description: 'Generates random password' | |
Handler: 'index.handler' | |
Role: !GetAtt PasswordGeneratorRole.Arn | |
Code: | |
ZipFile: | | |
const response = require('cfn-response'); | |
const AWS = require('aws-sdk'); | |
const ssm = new AWS.SSM(); | |
const secretsManager = new AWS.SecretsManager(); | |
exports.handler = (event, context) => { | |
if (event.RequestType == 'Delete') { | |
// Remove param when CloudFormation deletes the resource. The param name is the PhysicalResourceId | |
ssm.deleteParameter({ Name: event.PhysicalResourceId }).promise() | |
.then((data) => { | |
return response.send(event, context, response.SUCCESS, data); | |
}).catch((err)=> { | |
return response.send(event, context, response.FAILED, err); | |
}); | |
} | |
else{ // Create or Update. Update (only happens when param name changes) will return a new physical id which will cause CF to delete the old one | |
let responseData; | |
secretsManager.getRandomPassword({ PasswordLength: 45, ExcludePunctuation: true }).promise() | |
.then((data) => { | |
const password = data.RandomPassword.substring(0, 32); // We only really wanted 32 chars for the password | |
const randomString = data.RandomPassword.substring(32); // Last 13 used to add randomness to the SSM param name to avoid deletion on replacement | |
const paramName = event.ResourceProperties.ParameterNamePrefix + '-' + randomString; | |
responseData = { | |
ParameterName: paramName, | |
EncodedParameterName: encodeURIComponent(encodeURIComponent(paramName)), // Double encoded to work with AWS console | |
Password: password | |
} | |
const params = { | |
Name: paramName, | |
Type: 'SecureString', | |
Value: password, | |
Overwrite: true | |
}; | |
return ssm.putParameter(params).promise(); | |
}).then(() => { | |
return response.send(event, context, response.SUCCESS, responseData, responseData.ParameterName); // Use param name as PhysicalResourceId | |
}).catch((err)=> { | |
return response.send(event, context, response.FAILED, err); | |
}); | |
} | |
}; | |
Runtime: 'nodejs6.10' | |
Timeout: '30' | |
GeneratedPassword: | |
Type: 'AWS::CloudFormation::CustomResource' | |
Properties: | |
ServiceToken: !GetAtt PasswordGeneratorLambda.Arn | |
ParameterNamePrefix: '/mystack/database/master-password' | |
Outputs: | |
ParameterName: | |
Value: !GetAtt GeneratedPassword.ParameterName | |
Password: | |
Value: !GetAtt GeneratedPassword.Password | |
ConsoleLink: | |
Value: !Sub 'https://console.aws.amazon.com/systems-manager/parameters/${GeneratedPassword.EncodedParameterName}/description?region=${AWS::Region}' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated code to no longer use the backported getRandomPassword(). Lambda has been updated to an SDK version that supports it.