AWSTemplateFormatVersion: '2010-09-09' Conditions: cApprovedAMIsRule: Fn::Not: - Fn::Equals: - '' - '' cRequiredTagsRule: Fn::Not: - Fn::Equals: - Ref: pRequiredTagKey - '' Description: Sets up AWS Config Rules Metadata: Identifier: Value: template-config-rules Input: Description: optional tag key Output: Description: Outputs ID of all deployed resources RegionSupport: Value: NOTGOVCLOUD Stack: Value: '0' VersionDate: Value: '04012016' Parameters: pRequiredTagKey: Description: Tag key to check for with EC2/EBS REQUIRED_TAGS rule (optional, leave blank to ignore) Type: String Resources: rAMIComplianceFunction: Condition: cApprovedAMIsRule DependsOn: rConfigRulesLambdaRole Properties: Code: ZipFile: Fn::Join: - ' ' - - var aws = require('aws-sdk'); - var config = new aws.ConfigService(); - // Custom rule for evaluating pre-approved AMI use - function evaluateCompliance(configurationItem, ruleParameters, context) { - if(configurationItem.resourceType !== 'AWS::EC2::Instance') - return 'NOT_APPLICABLE'; - var amiIDs = ruleParameters.amiList.split(','); - if (amiIDs.indexOf(configurationItem.configuration.imageId) > -1) { - return 'COMPLIANT'; - '}' - else return 'NON_COMPLIANT'; - '}' - function isApplicable(configurationItem, event) { - var status = configurationItem.configurationItemStatus; - var eventLeftScope = event.eventLeftScope; - return (status === 'OK' || status === 'ResourceDiscovered') && eventLeftScope === false; - '}' - exports.handler = function(event, context) { - var invokingEvent = JSON.parse(event.invokingEvent); - var ruleParameters = JSON.parse(event.ruleParameters); - var compliance = 'NOT_APPLICABLE'; - if (isApplicable(invokingEvent.configurationItem, event)) - compliance = evaluateCompliance(invokingEvent.configurationItem, ruleParameters, context); // Invoke the compliance checking function. - var putEvaluationsRequest = { - 'Evaluations: [' - '{' - 'ComplianceResourceType: invokingEvent.configurationItem.resourceType,' - 'ComplianceResourceId: invokingEvent.configurationItem.resourceId,' - 'ComplianceType: compliance,' - 'OrderingTimestamp: invokingEvent.configurationItem.configurationItemCaptureTime' - '}' - '],' - 'ResultToken: event.resultToken' - '};' - config.putEvaluations(putEvaluationsRequest, function (err, data) { - if (err) { - context.fail(err); - '} else {' - context.succeed(data); - '}' - '});' - '};' - '' Handler: index.handler Role: Fn::GetAtt: - rConfigRulesLambdaRole - Arn Runtime: nodejs Timeout: '30' Type: AWS::Lambda::Function rCloudTrailValidationFunction: DependsOn: rConfigRulesLambdaRole Properties: Code: ZipFile: Fn::Join: - ' ' - - var aws = require('aws-sdk'); - var config = new aws.ConfigService(); - // Custom rule for evaluating CloudTrail configuration compliance - '// 3 config parameters for Trail must be true: Multi-Region, Global Services Events, and Log File Validation' - function evaluateCompliance(configurationItem, ruleParameters, context) { - if(configurationItem.resourceType !== 'AWS::CloudTrail::Trail') - return 'NOT_APPLICABLE'; - if((configurationItem.configuration.logFileValidationEnabled) && (configurationItem.configuration.includeGlobalServiceEvents) && (configurationItem.configuration.isMultiRegionTrail)) { - return 'COMPLIANT'; - '}' - else return 'NON_COMPLIANT'; - '}' - function isApplicable(configurationItem, event) { - var status = configurationItem.configurationItemStatus; - var eventLeftScope = event.eventLeftScope; - return (status === 'OK' || status === 'ResourceDiscovered') && eventLeftScope === false; - '}' - exports.handler = function(event, context) { - var invokingEvent = JSON.parse(event.invokingEvent); - var ruleParameters = JSON.parse(event.ruleParameters); - var compliance = 'NOT_APPLICABLE'; - if (isApplicable(invokingEvent.configurationItem, event)) - compliance = evaluateCompliance(invokingEvent.configurationItem, ruleParameters, context); // Invoke the compliance checking function. - var putEvaluationsRequest = { - 'Evaluations: [' - '{' - 'ComplianceResourceType: invokingEvent.configurationItem.resourceType,' - 'ComplianceResourceId: invokingEvent.configurationItem.resourceId,' - 'ComplianceType: compliance,' - 'OrderingTimestamp: invokingEvent.configurationItem.configurationItemCaptureTime' - '}' - '],' - 'ResultToken: event.resultToken' - '};' - config.putEvaluations(putEvaluationsRequest, function (err, data) { - if (err) { - context.fail(err); - '} else {' - context.succeed(data); - '}' - '});' - '};' - '' Handler: index.handler Role: Fn::GetAtt: - rConfigRulesLambdaRole - Arn Runtime: nodejs Timeout: '30' Type: AWS::Lambda::Function rConfigPermissionToCallLambdaAMICompliance: Condition: cApprovedAMIsRule Properties: Action: lambda:InvokeFunction FunctionName: Fn::GetAtt: - rAMIComplianceFunction - Arn Principal: config.amazonaws.com Type: AWS::Lambda::Permission rConfigPermissionToCallLambdaCloudTrail: Properties: Action: lambda:InvokeFunction FunctionName: Fn::GetAtt: - rCloudTrailValidationFunction - Arn Principal: config.amazonaws.com Type: AWS::Lambda::Permission rConfigRuleForAMICompliance: Condition: cApprovedAMIsRule DependsOn: rConfigPermissionToCallLambdaAMICompliance Properties: ConfigRuleName: check-for-ami-compliance Description: Checks whether approved AMIs are used. InputParameters: amiList: '' Scope: ComplianceResourceTypes: - AWS::EC2::Instance Source: Owner: CUSTOM_LAMBDA SourceDetails: - EventSource: aws.config MessageType: ConfigurationItemChangeNotification SourceIdentifier: Fn::GetAtt: - rAMIComplianceFunction - Arn Type: AWS::Config::ConfigRule rConfigRuleForCloudTrail: DependsOn: rConfigPermissionToCallLambdaCloudTrail Properties: ConfigRuleName: check-whether-cloudtrail-is-enabled Description: Checks whether CloudTrail is enabled in this region. Scope: ComplianceResourceTypes: - AWS::EC2::Instance Source: Owner: CUSTOM_LAMBDA SourceDetails: - EventSource: aws.config MessageType: ConfigurationItemChangeNotification SourceIdentifier: Fn::GetAtt: - rCloudTrailValidationFunction - Arn Type: AWS::Config::ConfigRule rConfigRuleForRequiredTags: Condition: cRequiredTagsRule Properties: ConfigRuleName: check-ec2-for-required-tag Description: Checks whether EC2 instances and volumes use the required tag. InputParameters: tag1Key: Ref: pRequiredTagKey Scope: ComplianceResourceTypes: - AWS::EC2::Volume - AWS::EC2::Instance Source: Owner: AWS SourceIdentifier: REQUIRED_TAGS Type: AWS::Config::ConfigRule rConfigRuleForSSH: Properties: ConfigRuleName: check-for-unrestricted-ssh-access Description: Checks whether security groups that are in use disallow unrestricted incoming SSH traffic. Scope: ComplianceResourceTypes: - AWS::EC2::SecurityGroup Source: Owner: AWS SourceIdentifier: INCOMING_SSH_DISABLED Type: AWS::Config::ConfigRule rConfigRuleForUnrestrictedPorts: Condition: cRequiredTagsRule Properties: ConfigRuleName: check-for-unrestricted-ports Description: Checks whether security groups that are in use disallow unrestricted incoming TCP traffic to the specified ports. InputParameters: blockedPort1: '3389' Scope: ComplianceResourceTypes: - AWS::EC2::SecurityGroup Source: Owner: AWS SourceIdentifier: RESTRICTED_INCOMING_TRAFFIC Type: AWS::Config::ConfigRule rConfigRulesLambdaPolicy: Properties: PolicyDocument: Statement: - Action: '*' Effect: Allow Resource: '*' Version: '2012-10-17' PolicyName: configrules Roles: - Ref: rConfigRulesLambdaRole Type: AWS::IAM::Policy rConfigRulesLambdaProfile: Properties: Path: / Roles: - Ref: rConfigRulesLambdaRole Type: AWS::IAM::InstanceProfile rConfigRulesLambdaRole: Properties: AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com Version: '2012-10-17' Path: / Type: AWS::IAM::Role