Description: AWS Security Hub FSBP Remediations Security Hub Custom Actions AWSTemplateFormatVersion: "2010-09-09" # @author Kanishk Mahajan # ## License: ## This code is made available under the MIT-0 license. See the LICENSE file. Resources: CreateSecurityHubCustomActionTargetLambda: Type: AWS::Lambda::Function Properties: FunctionName: FSBP-CreateSecurityHubCustomActionTargetLambda Description: Custom resource to create an action target in Security Hub Handler: index.lambda_handler MemorySize: 256 Role: !GetAtt CreateSecurityHubCustomActionTargetLambdaRole.Arn Runtime: python3.7 Timeout: 60 Code: ZipFile: | import boto3 import cfnresponse import os def lambda_handler(event, context): try: properties = event['ResourceProperties'] region = os.environ['AWS_REGION'] client = boto3.client('securityhub', region_name=region) responseData = {} if event['RequestType'] == 'Create': response = client.create_action_target( Name=properties['Name'], Description=properties['Description'], Id=properties['Id'] ) responseData['Arn'] = response['ActionTargetArn'] elif event['RequestType'] == 'Delete': account_id = context.invoked_function_arn.split(":")[4] client.delete_action_target( ActionTargetArn=f"arn:aws:securityhub:{region}:{account_id}:action/custom/{properties['Id']}" ) cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData) except Exception as e: print(e) cfnresponse.send(event, context, cfnresponse.FAILED, {}) CreateSecurityHubCustomActionTargetLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: CreateActionTarget-LambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData Resource: '*' - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: '*' - Effect: Allow Action: - securityhub:CreateActionTarget - securityhub:DeleteActionTarget Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole #[IAM.3] IAMRotate90daysEnabledRule: Type: AWS::Events::Rule Properties: Name: FSBP-IAMRotate90daysEnabledRule Description: "IAM3 – Disable and Rotate IAM Access Key that is older than 90 days" EventPattern: source: - aws.securityhub detail-type: - Security Hub Findings - Custom Action resources: - !GetAtt IAMRotate90daysEnabledActionTarget.Arn State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "IAMRotate90daysEnabledLambda" - "Arn" Id: "IAM3" IAMRotate90daysEnabledActionTarget: Type: Custom::ActionTarget Version: 1.0 Properties: ServiceToken: !GetAtt CreateSecurityHubCustomActionTargetLambda.Arn Name: IAM3 Description: IAM.3 Events from Security Hub Id: IAM3 IAMRotate90daysEnabledPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "IAMRotate90daysEnabledLambda" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "IAMRotate90daysEnabledRule" - "Arn" IAMRotate90daysEnabledLambda: Type: AWS::Lambda::Function DependsOn: IAMRotate90daysEnabledLambdaRole Properties: FunctionName: FSBP-IAMRotate90daysEnabledLambda Description: IAM3 Remediation using Custom SSM Document Handler: index.lambda_handler MemorySize: 256 Role: !GetAtt IAMRotate90daysEnabledLambdaRole.Arn Runtime: python3.6 Timeout: 60 Code: ZipFile: | import boto3 import json import os def lambda_handler(event, context): userArn = str(event['detail']['findings'][0]['Resources'][0]['Id']) userArn_1 = userArn.split(':')[-1] username = userArn_1.replace("user/","") ssm = boto3.client('ssm') try: response = ssm.start_automation_execution( DocumentName='FSBPIAM3Automation', DocumentVersion='1', # default Parameters={ 'username': [ username ] } ) except Exception as e: print(e) print("SSM automation execution error") raise IAMRotate90daysEnabledLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: IAMRotate90daysEnabledLambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData - iam:* Resource: '*' - Effect: Allow Action: - ssm:StartAutomationExecution - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - iam:PassRole Resource: '*' - Effect: Allow Action: - cloudtrail:UpdateTrail - securityhub:UpdateFindings Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole #[SSM.1] SSMQuickSetupEnabledRule: Type: AWS::Events::Rule Properties: Name: FSBP-SSMQuickSetupEnabledRule Description: "[SSM.1] EC2 instances should be managed by AWS Systems Manager" EventPattern: source: - aws.securityhub detail-type: - Security Hub Findings - Custom Action resources: - !GetAtt SSMQuickSetupEnabledActionTarget.Arn State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "SSMQuickSetupEnabledLambda" - "Arn" Id: "SSM1" SSMQuickSetupEnabledActionTarget: Type: Custom::ActionTarget Version: 1.0 Properties: ServiceToken: !GetAtt CreateSecurityHubCustomActionTargetLambda.Arn Name: SSM1 Description: "SSM.1 EC2 instances should be managed by AWS Systems Manager" Id: SSM1 SSMQuickSetupEnabledPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "SSMQuickSetupEnabledLambda" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "SSMQuickSetupEnabledRule" - "Arn" SSMQuickSetupEnabledLambda: Type: AWS::Lambda::Function Properties: FunctionName: FSBP-SSMQuickSetupEnabledLambda Description: "[SSM.1] EC2 instances should be managed by AWS Systems Manager " Handler: index.lambda_handler MemorySize: 256 Role: !GetAtt SSMQuickSetupEnabledLambdaRole.Arn Runtime: python3.7 Timeout: 60 Environment: Variables: SSMInstanceProfileRoleArn : !ImportValue FSBP-SSMInstanceProfileRoleArn Code: ZipFile: | import boto3 import json import os def lambda_handler(event, context): InstanceId = str(event['detail']['findings'][0]['ProductFields']['attributes:5/value']) ssminstanceprofilerole_arn = os.environ['SSMInstanceProfileRoleArn'] roleArn_1 = ssminstanceprofilerole_arn.split(':')[-1] rolename = roleArn_1.replace("role/","") iam = boto3.client('iam') ssm = boto3.client('ssm') ec2 = boto3.client('ec2') try: response_iam_1 = iam.create_instance_profile( InstanceProfileName='EC2ManagedInstanceProfile', ) InstanceProfileArn = response_iam_1['InstanceProfile']['Arn'] response_iam_2 = iam.add_role_to_instance_profile( InstanceProfileName='EC2ManagedInstanceProfile', RoleName=rolename ) response_ec2 = ec2.associate_iam_instance_profile( IamInstanceProfile={ 'Name': 'EC2ManagedInstanceProfile' 'Arn': InstanceProfileArn }, InstanceId=InstanceId ) response = ssm.create_association( Name='AWS-UpdateSSMAgent', Targets=[ { 'Key': 'InstanceIds', 'Value': InstanceId } ] ) except Exception as e: print(e) print("SSM automation execution error") raise SSMQuickSetupEnabledLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: FSBP-SSMQuickSetupEnabledLambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData Resource: '*' - Effect: Allow Action: - ssm:StartAutomationExecution - ssm:* - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - iam:PassRole - ec2:* - iam:* Resource: '*' - Effect: Allow Action: - cloudtrail:UpdateTrail - securityhub:UpdateFindings Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole #[Lambda.1] RestrictPublicAccessLambdaEnabledRule: Type: AWS::Events::Rule Properties: Name: FSBP-RestrictPublicAccessLambdaEnabledRule Description: "[Lambda.1] Lambda functions should prohibit public access" EventPattern: source: - aws.securityhub detail-type: - Security Hub Findings - Custom Action resources: - !GetAtt RestrictPublicAccessLambdaEnabledActionTarget.Arn State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "RestrictPublicAccessLambdaEnabledLambda" - "Arn" Id: "Lambda1" RestrictPublicAccessLambdaEnabledActionTarget: Type: Custom::ActionTarget Version: 1.0 Properties: ServiceToken: !GetAtt CreateSecurityHubCustomActionTargetLambda.Arn Name: Lambda1 Description: "[Lambda.1] Lambda functions should prohibit public access" Id: Lambda1 RestrictPublicAccessLambdaEnabledPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "RestrictPublicAccessLambdaEnabledLambda" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "RestrictPublicAccessLambdaEnabledRule" - "Arn" RestrictPublicAccessLambdaEnabledLambda: Type: AWS::Lambda::Function Properties: FunctionName: FSBP-RestrictPublicAccessLambdaEnabledLambda Description: "[PCI.Lambda.1] Lambda functions should prohibit public access" Handler: index.lambda_handler MemorySize: 256 Role: !GetAtt RestrictPublicAccessLambdaEnabledLambdaRole.Arn Runtime: python3.7 Timeout: 60 Environment: Variables: accountID : !Ref 'AWS::AccountId' Code: ZipFile: | import boto3 import json import os def lambda_handler(event, context): functionname = str(event['detail']['findings'][0]['Resources'][0]['Details']['AwsLambdaFunction']['FunctionName']) Id = str(event['detail']['findings'][0]['Id']) accountID = os.environ['accountID'] ssm = boto3.client('ssm') try: response = ssm.start_automation_execution( DocumentName='FSBPLambda1Automation', DocumentVersion='1', # default Parameters={ 'functionname': [ functionname ], 'accountID': [accountID] } ) except Exception as e: print(e) print("SSM automation execution error") raise RestrictPublicAccessLambdaEnabledLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: RestrictPublicAccessLambdaEnabledLambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData Resource: '*' - Effect: Allow Action: - ssm:StartAutomationExecution - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - iam:PassRole - lambda:* Resource: '*' - Effect: Allow Action: - cloudtrail:UpdateTrail - securityhub:UpdateFindings Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole #[GuardDuty.1] GuardDutyEnabledRule: Type: AWS::Events::Rule Properties: Name: FSBP-GuardDutyEnabledRule Description: "[GuardDuty.1] GuardDuty should be enabled" EventPattern: source: - aws.securityhub detail-type: - Security Hub Findings - Custom Action resources: - !GetAtt GuardDutyEnabledActionTarget.Arn State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "GuardDutyEnabledLambda" - "Arn" Id: "GuardDuty1" GuardDutyEnabledActionTarget: Type: Custom::ActionTarget Version: 1.0 Properties: ServiceToken: !GetAtt CreateSecurityHubCustomActionTargetLambda.Arn Name: GuardDuty1 Description: "[GuardDuty.1] GuardDuty should be enabled" Id: GuardDuty1 GuardDutyEnabledPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "GuardDutyEnabledLambda" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "GuardDutyEnabledRule" - "Arn" GuardDutyEnabledLambda: Type: AWS::Lambda::Function Properties: FunctionName: FSBP-GuardDutyEnabledLambda Description: "GuardDuty.1 GuardDuty should be enabled" Handler: index.lambda_handler MemorySize: 256 Role: !GetAtt GuardDutyEnabledLambdaRole.Arn Runtime: python3.7 Timeout: 60 Code: ZipFile: | import boto3 import json import os def lambda_handler(event, context): findingpublishingfrequency='FIFTEEN_MINUTES' ssm = boto3.client('ssm') try: response = ssm.start_automation_execution( DocumentName='FSBPGuardDuty1Automation', DocumentVersion='1', # default Parameters={ 'findingpublishingfrequency': [ findingpublishingfrequency ] } ) except Exception as e: print(e) print("SSM automation execution error") raise GuardDutyEnabledLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: FSBP-GuardDutyEnabledLambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData Resource: '*' - Effect: Allow Action: - ssm:StartAutomationExecution - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - iam:PassRole Resource: '*' - Effect: Allow Action: - cloudtrail:UpdateTrail - securityhub:UpdateFindings Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole #[Lambda.2] LatestRuntimeLambdaEnabledRule: Type: AWS::Events::Rule Properties: Name: FSBP-LatestRuntimeLambdaEnabledRule Description: "[Lambda.2] Lambda functions should use latest runtimes" EventPattern: source: - aws.securityhub detail-type: - Security Hub Findings - Custom Action resources: - !GetAtt LatestRuntimeLambdaEnabledActionTarget.Arn State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "LatestRuntimeLambdaEnabledLambda" - "Arn" Id: "Lambda2" LatestRuntimeLambdaEnabledActionTarget: Type: Custom::ActionTarget Version: 1.0 Properties: ServiceToken: !GetAtt CreateSecurityHubCustomActionTargetLambda.Arn Name: Lambda2 Description: "[Lambda.2] Lambda functions should use latest runtimes" Id: Lambda2 LatestRuntimeLambdaEnabledPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "LatestRuntimeLambdaEnabledLambda" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "LatestRuntimeLambdaEnabledRule" - "Arn" LatestRuntimeLambdaEnabledLambda: Type: AWS::Lambda::Function Properties: FunctionName: FSBP-LatestRuntimeLambdaEnabledLambda Description: "[Lambda.2] Lambda functions should use latest runtimes" Handler: index.lambda_handler MemorySize: 256 Role: !GetAtt LatestRuntimeLambdaEnabledLambdaRole.Arn Runtime: python3.7 Timeout: 60 Code: ZipFile: | import boto3 import json import os def lambda_handler(event, context): functionname = str(event['detail']['findings'][0]['Resources'][0]['Details']['AwsLambdaFunction']['FunctionName']) Id = str(event['detail']['findings'][0]['Id']) ssm = boto3.client('ssm') try: response = ssm.start_automation_execution( DocumentName='FSBPLambda2Automation', DocumentVersion='1', # default Parameters={ 'functionname': [ functionname ] } ) except Exception as e: print(e) print("SSM automation execution error") raise LatestRuntimeLambdaEnabledLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: FSBP-LatestRuntimeLambdaEnabledLambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData Resource: '*' - Effect: Allow Action: - ssm:StartAutomationExecution - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - iam:PassRole - lambda:* Resource: '*' - Effect: Allow Action: - cloudtrail:UpdateTrail - securityhub:UpdateFindings Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole #[EC2.3] EBSVolumeEncryptionEnabledRule: Type: AWS::Events::Rule Properties: Name: FSBP-EBSVolumeEncryptionEnabledRule Description: "[EC2.3] Attached EBS volumes should be encrypted at-rest" EventPattern: source: - aws.securityhub detail-type: - Security Hub Findings - Custom Action resources: - !GetAtt EBSVolumeEncryptionEnabledActionTarget.Arn State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "EBSVolumeEncryptionEnabledLambda" - "Arn" Id: "EC23" EBSVolumeEncryptionEnabledActionTarget: Type: Custom::ActionTarget Version: 1.0 Properties: ServiceToken: !GetAtt CreateSecurityHubCustomActionTargetLambda.Arn Name: EC23 Description: "[EC2.3] Attached EBS volumes should be encrypted at-rest" Id: EC23 EBSVolumeEncryptionEnabledPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "EBSVolumeEncryptionEnabledLambda" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "EBSVolumeEncryptionEnabledRule" - "Arn" EBSVolumeEncryptionEnabledLambda: Type: AWS::Lambda::Function Properties: FunctionName: FSBP-EBSVolumeEncryptionEnabledLambda Description: "[EC2.3] Attached EBS volumes should be encrypted at-rest" Handler: index.lambda_handler MemorySize: 768 Role: !GetAtt EBSVolumeEncryptionEnabledLambdaRole.Arn Runtime: python3.7 Timeout: 875 Environment: Variables: kmskeyArn : !ImportValue FSBP-KMSKeyArn sourceregion: !Ref "AWS::Region" Code: ZipFile: | import boto3 import json import os def lambda_handler(event, context): ebsvolumeArn = str(event['detail']['findings'][0]['Resources'][0]['Id']) ebsvolumeId = ebsvolumeArn.split(':')[-1] kmskeyArn = os.environ['kmskeyArn'] sourceregion = os.environ['sourceregion'] ssm = boto3.client('ssm') try: response = ssm.start_automation_execution( DocumentName='FSBPEC23Automation', DocumentVersion='1', # default Parameters={ 'ebsvolumeId': [ ebsvolumeId ] 'kmskeyArn': [kmskeyArn] 'sourceregion': [sourceregion] } ) except Exception as e: print(e) print("SSM automation execution error") raise EBSVolumeEncryptionEnabledLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: FSBP-EBSVolumeEncryptionEnabledLambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData Resource: '*' - Effect: Allow Action: - ssm:StartAutomationExecution - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - iam:PassRole Resource: '*' - Effect: Allow Action: - cloudtrail:UpdateTrail - securityhub:UpdateFindings Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole # ------------------------------------------------------------------------------------------------------------------------------------------------------- # [RDS.3] RDS DB instances should have encryption at-rest enabled # ------------------------------------------------------------------------------------------------------------------------------------------------------- RDSInstanceEncryptionEnabledRule: Type: AWS::Events::Rule Properties: Name: FSBP-RDSInstanceEncryptionEnabledRule Description: "[RDS.2] RDS instances should have encryption at rest enabled" EventPattern: source: - aws.securityhub detail-type: - Security Hub Findings - Custom Action resources: - !GetAtt RDSInstanceEncryptionEnabledActionTarget.Arn State: "ENABLED" Targets: - Arn: Fn::GetAtt: - "RDSInstanceEncryptionEnabledLambda" - "Arn" Id: "RDS3" RDSInstanceEncryptionEnabledActionTarget: Type: Custom::ActionTarget Version: 1.0 Properties: ServiceToken: !GetAtt CreateSecurityHubCustomActionTargetLambda.Arn Name: RDS3 Description: "[RDS.3] RDS DB instances should have encryption at-rest enabled" Id: RDS3 RDSInstanceEncryptionEnabledPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: "RDSInstanceEncryptionEnabledLambda" Action: "lambda:InvokeFunction" Principal: "events.amazonaws.com" SourceArn: Fn::GetAtt: - "RDSInstanceEncryptionEnabledRule" - "Arn" RDSInstanceEncryptionEnabledLambda: Type: AWS::Lambda::Function Properties: FunctionName: FSBP-RDSInstanceEncryptionEnabledLambda Description: "[RDS.3] RDS DB instances should have encryption at-rest enabled" Handler: index.lambda_handler MemorySize: 768 Role: !GetAtt RDSInstanceEncryptionEnabledLambdaRole.Arn Runtime: python3.7 Timeout: 875 Environment: Variables: kmskeyArn : !ImportValue FSBP-KMSKeyArn Code: ZipFile: | import boto3 import json import os def lambda_handler(event, context): dbinstanceArn = str(event['detail']['findings'][0]['Resources'][0]['Id']) dbinstanceId = dbinstanceArn.split(':')[-1] kmskeyArn = os.environ['kmskeyArn'] ssm = boto3.client('ssm') try: response = ssm.start_automation_execution( DocumentName='FSBPRDS3Automation', DocumentVersion='1', # default Parameters={ 'dbinstanceId': [ dbinstanceId ] 'kmskeyArn': [kmskeyArn] } ) except Exception as e: print(e) print("SSM automation execution error") raise RDSInstanceEncryptionEnabledLambdaRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: FSBP-RDSInstanceEncryptionEnabledLambdaPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - cloudwatch:PutMetricData Resource: '*' - Effect: Allow Action: - ssm:StartAutomationExecution - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - iam:PassRole Resource: '*' - Effect: Allow Action: - cloudtrail:UpdateTrail - securityhub:UpdateFindings Resource: '*' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: { Service: lambda.amazonaws.com } Action: - sts:AssumeRole