Using CloudWatch to Secure Your AWS Account

Search for a command to run...

No comments yet. Be the first to comment.
Before You Begin Before you begin an AWS security assessment, you need to gain access to the customers AWS account and the best way to do that is by setting up a cross-account trust. Cross-account trusts use a role to delegate access to resources th...

Houston, We Have A Problem AWS makes it super easy to SSH into an instance by giving you the option the create a new SSH Key Pair for you on the fly. In fact the very last step in creating an EC2 instance is assigning a Key Pair. So now with your K...

Meat and Potatoes Now that the front facing website is complete its time to turn our attention to the business end. Here's the steps we'll ne doing for Part 3 of this series. Javascript - Your resume webpage should include a visitor counter that di...

The Nuts and Bolts Now that we have the basics of the Cloud Resume Challenge out of the way, let's get down to business. In Part 2 of my journey I'll be covering the first 7 steps of the challenge. Certification - Your resume needs to have at mini...

In my post "AWS Security Assessments - Getting Access", I described how to use a CloudFormation Quick Create-Link to easily setup Cross-Account Trusts to access customer accounts when performing an AWS Security Assessment. Following that post a colleague posed the question if cross-account trusts could be used for phishing to gain access to an account. The short answer to that question is YES!!
However keeping in mind a defense-in-depth strategy and approach to IAM security in AWS, you should follow least privilege access in IAM, periodically review the IAM Credential Report, and turn on IAM Access Analyzer. Another step in the defense in depth approach to securing your account is to use CloudFormation to create a CloudWatch Alarm to respond to CloudTrail API IAM Calls. What that means in simple terms is you'll get an email alert anytime changes are made to IAM users including add, delete, or modify operations.
The power of Infrastructure as Code (IaC) tools like CloudFormation or Terraform comes from its ability to allow you to quickly provision deployments to your infrastructure in an error free repeatable process. This of course is particularly useful when you're working to secure your AWS environment.
It's important to note that some of these steps are optional depending on what controls you already have enabled and you can modify your CloudFormation script as needed. Here's what we'll be doing in a nutshell.
Here's the CloudFormation template written in YAML that you'll want to deploy. You can also update it as needed to include any additional IAM Actions you want to monitor from the full AWS IAM API Reference List.
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudWatch Alarm that detects changes to IAM users and
groups and publishes change events to an SNS topic for notification.'
Resources:
CloudTrail:
Type: 'AWS::CloudTrail::Trail'
Properties:
TrailName: ManagementEventsTrail
IsLogging: true
EnableLogFileValidation: false
EventSelectors:
- IncludeManagementEvents: true
ReadWriteType: All
IsMultiRegionTrail: true
IncludeGlobalServiceEvents: true
S3BucketName:
Ref: S3BucketForCloudTrail
CloudWatchLogsLogGroupArn:
'Fn::GetAtt':
- CloudWatchLogGroup
- Arn
CloudWatchLogsRoleArn:
'Fn::GetAtt':
- IamRoleForCwLogs
- Arn
DependsOn: S3BucketPolicy
S3BucketForCloudTrail:
Type: 'AWS::S3::Bucket'
Properties:
# <CHANGE BELOW AS NEEDED>
BucketName: management-events-trail-bucket-name
S3BucketPolicy:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket:
Ref: S3BucketForCloudTrail
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AWSCloudTrailBucketPermissionsCheck
Effect: Allow
Principal:
Service:
- cloudtrail.amazonaws.com
Action: 's3:GetBucketAcl'
Resource:
'Fn::GetAtt':
- S3BucketForCloudTrail
- Arn
- Sid: ' AWSConfigBucketDelivery'
Effect: Allow
Principal:
Service:
- cloudtrail.amazonaws.com
Action: 's3:PutObject'
Resource:
'Fn::Join':
- ''
- - 'Fn::GetAtt':
- S3BucketForCloudTrail
- Arn
- /AWSLogs/*
Condition:
StringEquals:
's3:x-amz-acl': bucket-owner-full-control
CloudWatchLogGroup:
Type: 'AWS::Logs::LogGroup'
Properties:
# <CHANGE BELOW AS NEEDED>
LogGroupName: CloudTrailLogs
IamRoleForCwLogs:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: ''
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Action: 'sts:AssumeRole'
Policies:
- PolicyName: allow-access-to-cw-logs
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Resource: '*'
RoleName: CloudTrailLogs-to-CloudWatch
SnsTopic:
Type: 'AWS::SNS::Topic'
Properties:
Subscription:
# <CHANGE BELOW AS NEEDED>
- Endpoint: example@example.com
Protocol: email
TopicName: alarm-action
CloudWatchAlarm:
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmName: iam_user_changes
AlarmDescription: >-
A CloudWatch Alarm that triggers when changes are made to IAM users.
MetricName: IAMPolicyEventCount
Namespace: CloudTrailMetrics
Statistic: Sum
Period: '300'
EvaluationPeriods: '1'
Threshold: '1'
ComparisonOperator: GreaterThanOrEqualToThreshold
AlarmActions:
- Ref: SnsTopic
TreatMissingData: notBreaching
MetricFilter:
Type: 'AWS::Logs::MetricFilter'
Properties:
# <CHANGE BELOW AS NEEDED>
LogGroupName: CloudTrailLogs
# <CHANGE BELOW AS NEEDED>
FilterPattern: >-
{($.eventName=AddUserToGroup)||($.eventName=AttachGroupPolicy)||($.eventName=AttachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=ChangePassword)||($.eventName=CreateAccessKey)||($.eventName=CreatePolicy)||($.eventName=CreateRole)||($.eventName=CreateUser)||($.eventName=CreateVirtualMFADevice)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=UpdateAccessKey)||($.eventName=UpdateGroup)||($.eventName=UpdateRole)||($.eventName=UpdateUser)}
MetricTransformations:
- MetricValue: '1'
MetricNamespace: CloudTrailMetrics
MetricName: IAMPolicyEventCount
DependsOn: CloudWatchLogGroup
Parameters: {}
Metadata: {}
Conditions: {}
Now that our code is modified, its time to deploy it to CloudFormation. Start by creating a new Stack.



You'll need check your email to confirm your SNS Subscription.

Now all you need to do is modify an IAM user to make sure it works. It's also important to note that CloudWatch Alarms aren't instantaneous and there is a delay associated with them. In fact one if the controls we specified in the script was Period: '300' which means our CloudWatch Alarm will check every 5 minutes. If everything worked as planned you should have received an alert like this.
