Secure In Cloud / Aws_basic_hardening
Created 2020-05-27 Modifyed 2020-05-27

1016 Words

Cloudformation template to enable basic AWS account level security: Cloudtrail, AWS Config, Cloudwatch Alarms on security events, etc.

The very first thing you need to do while building your AWS infrastructure is to enable and configure all AWS account level security features such as CloudTrail, CloudConfig, CloudWatch, IAM, etc.. To do this, you can use mine Amazon AWS Account level security checklist and how-to or any other source. To avoid manual steps and to be aligned with SecuityAsCode concept, I suggest using a set of the CloudFormation templates which will provide the following functionality:

  • configures CloudTrail according to the new best practices (KMS encryption, validation, etc)
  • configures AWS Config service and creates a basic set of the CloudConfig rules to monitor best practices
  • implements Section 3 (Monitoring) of the CIS Amazon Web Services Foundations Benchmark.

Launch template now: CloudFormation_template

Global Security stack template structure:

security.global.yaml - parent template for all nested templates to link them together and control dependency between nested stacks.

cloudtrail.clobal.yaml - nested template for Global configuration of the CloudTrail

awsconfig.global.yaml - nested template for Global AWS Config Service configuration and config rules.

cloudwatchalarms.global.yaml - nested template for Global CloudWatch Logs alarms and security metrics creation. Uses FilterMap to create different security-related filters for ClouTrail LogGroup, corresponding metrics, and notifications for suspicious or dangerous events. You can customize a filter on a per-environment basis.

Input parameters:

  • CFtemplateBucketURL: URL of the CloudFromation templates to use (Normally in the s3 bucket). This parameter will be prepopullated with value: https://s3.amazonaws.com/secureincloud.ca/aws/

  • Bucket4Logs : Name of the new bucket that will be created to collect cloudtrail and config logs

  • LogRetentionDays : Amount of days to store the logs in S3 bucket. Default 365 or 1 year

  • AWSAccountName : AWS Account nickname(purpose). User-Friendly name(purpose) of your AWS account. Will be used in names of the CloudWatch Alarms.

  • InfosecEmail : Email of the infosec team to send security-related alers from the CloudWatch Alerts

  • DevOpsEmail : Email of the DevOps team to send operations-related alers from the CloudWatch Alerts

AWS Managed Config Rules deployed by template:

  • iam-user-no-policies-check Description: Checks that none of your IAM users have policies attached. IAM users must inherit permissions from IAM groups or roles
  • root-account-mfa-enabled Description: Checks whether the root user of your AWS account requires multi-factor authentication for console sign-in.
  • s3-bucket-public-read-prohibited Description: Checks that your S3 buckets do not allow public read access. If an S3 bucket policy or bucket ACL allows public read access, the bucket is noncompliant.
  • s3-bucket-public-write-prohibited Description: Checks that your S3 buckets do not allow public write access. If an S3 bucket policy or bucket ACL allows public write access, the bucket is noncompliant.
  • restricted-ssh Description: Checks whether security groups that are in use disallow unrestricted incoming SSH traffic.
  • iam-password-policy Description: Checks whether the account password policy for IAM users meets the specified requirements.

AWS CIS Checks covered by the template (implemented via CloudWatch Alert mechnism ):

  • AWS CIS 3.01 Ensure a log metric filter and alarm exist for unauthorized API calls
  • AWS CIS 3.02 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA
  • AWS CIS 3.3 Ensure a log metric filter and alarm exist for usage of Root account
  • AWS CIS 3.4 Ensure a log metric filter and alarm exist for IAM policy changes
  • AWS CIS 3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes
  • AWS CIS 3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures
  • AWS CIS 3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs
  • AWS CIS 3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes
  • AWS CIS 3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes
  • AWS CIS 3.10 Ensure a log metric filter and alarm exist for security group changes
  • AWS CIS 3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL)
  • AWS CIS 3.12 Ensure a log metric filter and alarm exist for changes to network gateways
  • AWS CIS 3.13 Ensure a log metric filter and alarm exist for route table changes
  • AWS CIS 3.14 Ensure a log metric filter and alarm exist for VPC changes

Custom checks implemented via CloudWatch Alert mechnism:

  • Custom: Alarms when a large number of sensetive (Start. Stop, Terminate, Reboot Instance) operations are performed in small time period
  • Custom: Alarms when a large number of Instances are being terminated
  • Custom: Alarms when a volume is force detached from an Instance
  • Custom: Alarms when VPC traffic flow is created or deleted

Feel free to extend this list with your custom checks as per examples provided in the template and below:

```
rds-change:
  all: '{$.eventName = CopyDB* || $.eventName = CreateDB* || $.eventName = DeleteDB*}'

srt-instance:
  all: '{($.eventName = StopInstances || $.eventName = TerminateInstances || $.eventName
    = RebootInstances)}'

large-instance:
  all: >-
    { (($.eventName = RunInstances) || ($.eventName = StartInstances)) && (($.requestParameters.instanceType
    = *.2xlarge) || ($.requestParameters.instanceType = *.4xlarge) || ($.requestParameters.instanceType
    = *.8xlarge) || ($.requestParameters.instanceType = *.10xlarge)) }

change-critical-ebs:
  prod: >-
    {($.eventName = DetachVolume || $.eventName = AttachVolume || $.eventName
    = CreateVolume || $.eventName = DeleteVolume || $.eventName = EnableVolumeIO
    || $.eventName = ImportVolume || $.eventName = ModifyVolumeAttribute) && ($.requestParameters.volumeId
    = vol-youvol1ID || $.requestParameters.volumeId = vol-youvol2ID)}

create-delete-secgroup:
  all: >-
    {$.eventName = CreateSecurityGroup || $.eventName = CreateCacheSecurityGroup
    || $.eventName = CreateClusterSecurityGroup || $.eventName = CreateDBSecurityGroup
    || $.eventName = DeleteSecurityGroup || $.eventName = DeleteCacheSecurityGroup
    || $.eventName = DeleteClusterSecurityGroup ||  $.eventName = DeleteDBSecurityGroup}

secgroup-instance:
  all: '{$.eventName = ModifyInstanceAttribute && $.requestParameters.groupSet.items[0].groupId
    = * }'

cloudformation-change:
  all: '{$.eventSource = cloudformation.amazonaws.com && ($.eventName != Validate*
    && $.eventName != Describe* && $.eventName != List* && $.eventName != Get*)}'

critical-instance:
  prod: >-
    {$.requestParameters.instanceId = i-instance1ID || $.requestParameters.instanceId
    = i-instance2ID || $.requestParameters.instanceId = i-instance3ID || $.requestParameters.instanceId
    = i-instance4ID || $.requestParameters.instanceId = i-instance5ID || $.requestParameters.instanceId
    = i-instance6ID|| $.requestParameters.instanceId = i-instance7ID}

eip-change:
  all: '{$.eventName = AssociateAddress || $.eventName = DisassociateAddress ||
    $.eventName = MoveAddressToVpc || $.eventName = ReleaseAddress }'

net-access
all: >-
    {$.sourceIPAddress != 111.222.3* && $.sourceIPAddress != 111.222.4* && $.sourceIPAddress
    != cloud* && $.sourceIPAddress != AWS* && $.sourceIPAddress != 11.22.33.00
    && $.sourceIPAddress != 11.22.33.01 }

```