Skip to content

Instantly share code, notes, and snippets.

@iann0036
Created April 21, 2022 12:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iann0036/6e1cab8a55bf0322a86f3ee780292886 to your computer and use it in GitHub Desktop.
Save iann0036/6e1cab8a55bf0322a86f3ee780292886 to your computer and use it in GitHub Desktop.
SecurityHubStandardsConfigurationStackSet:
DependsOn:
- SecurityStackSet
Condition: IsDelegationComplete
Type: AWS::CloudFormation::StackSet
Properties:
StackSetName: securityhub-standards
PermissionModel: SERVICE_MANAGED
CallAs: DELEGATED_ADMIN
Capabilities:
- CAPABILITY_NAMED_IAM
ManagedExecution:
Active: true
AutoDeployment:
Enabled: true
RetainStacksOnAccountRemoval: false
StackInstancesGroup:
- DeploymentTargets:
OrganizationalUnitIds:
- !Ref OrganizationRootId
Regions:
- us-east-1
TemplateBody: |
Resources:
SecurityHubStandardsRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: root
PolicyDocument:
Statement:
- Effect: Allow
Action:
- securityhub:BatchEnableStandards
- securityhub:BatchDisableStandards
- securityhub:UpdateStandardsControl
- securityhub:GetEnabledStandards
- securityhub:DescribeStandardsControls
Resource: '*'
SecurityHubStandardsLambda:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Role: !GetAtt SecurityHubStandardsRole.Arn
Runtime: python3.7
Timeout: 600
Code:
ZipFile: |
import json
import os
import cfnresponse
import boto3
import pprint
import traceback
from botocore.config import Config
def handler(event, context):
pprint.pprint(event)
longretriesconfig = Config(
retries = {
'max_attempts': 10,
'mode': 'standard'
}
)
try:
returndata = {}
regions = ['ap-southeast-2', 'us-east-1', 'ap-southeast-1']
if event['ResourceType'] == 'Custom::SecurityHubStandards' and event['RequestType'] == 'Create':
for region in regions:
client = boto3.client('securityhub', region_name=region, config=longretriesconfig)
client.batch_enable_standards(
StandardsSubscriptionRequests=[
{
'StandardsArn': 'arn:aws:securityhub:' + region + '::standards/pci-dss/v/3.2.1'
}
]
)
if event['ResourceType'] == 'Custom::SecurityHubStandards' and (event['RequestType'] == 'Create' or event['RequestType'] == 'Update'):
for region in regions:
client = boto3.client('securityhub', region_name=region, config=longretriesconfig)
for standard in client.get_enabled_standards()['StandardsSubscriptions']:
paginator = client.get_paginator('describe_standards_controls')
pages = paginator.paginate(
StandardsSubscriptionArn=standard['StandardsSubscriptionArn']
)
for page in pages:
for control in page['Controls']:
for disabledcontrol in event['ResourceProperties']['DisabledControls']:
if control['ControlId'] in disabledcontrol['ControlIDs'] and region not in disabledcontrol['RegionExceptions']:
client.update_standards_control(
StandardsControlArn=control['StandardsControlArn'],
ControlStatus='DISABLED',
DisabledReason=disabledcontrol['Reason']
)
elif event['ResourceType'] == 'Custom::SecurityHubStandards' and event['RequestType'] == 'Delete':
for region in regions:
client = boto3.client('securityhub', region_name=region)
for standard in client.get_enabled_standards()['StandardsSubscriptions']:
if standard['StandardsArn'] == 'arn:aws:securityhub:' + region + '::standards/pci-dss/v/3.2.1':
client.batch_disable_standards(
StandardsSubscriptionArns=[
standard['StandardsSubscriptionArn']
]
)
except Exception as e:
pprint.pprint(e)
traceback.print_stack()
cfnresponse.send(event, context, cfnresponse.FAILED, returndata, "SecurityHubStandardsInvocation")
return
cfnresponse.send(event, context, cfnresponse.SUCCESS, returndata, "SecurityHubStandardsInvocation")
SecurityHubStandards:
Type: Custom::SecurityHubStandards
Properties:
ServiceToken: !GetAtt SecurityHubStandardsLambda.Arn
DisabledControls:
- Reason: Disabled for all regions except us-east-1 due to global-only control.
ControlIDs: ['IAM.3', 'IAM.4', 'IAM.5', 'IAM.8', 'CIS.1.2', 'CIS.1.3', 'CIS.1.4', 'CIS.1.12', 'CIS.1.16', 'CIS.1.20', 'CIS.1.22', 'PCI.IAM.1', 'PCI.IAM.2', 'PCI.IAM.3', 'PCI.IAM.6', 'Config.1', 'CIS.2.5', 'PCI.Config.1']
RegionExceptions: ['us-east-1']
- Reason: Disabled due to SCP in place to prevent IAM user usage.
ControlIDs: ['IAM.7', 'CIS.1.5', 'CIS.1.6', 'CIS.1.7', 'CIS.1.8', 'CIS.1.9', 'CIS.1.10', 'CIS.1.11']
RegionExceptions: []
- Reason: Disabled due to SCP in place to prevent root user usage.
ControlIDs: ['IAM.6', 'CIS.1.13', 'CIS.1.14', 'PCI.IAM.4', 'PCI.IAM.5']
RegionExceptions: []
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment