This file contains 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
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