├── LICENSE ├── README.md ├── cheatsheet.txt ├── cleancache.sh ├── cron ├── crontab.txt └── mfa-audit.sh ├── custom-site-packages ├── README.md └── iam.py ├── examples ├── cheatsheet.txt ├── cleancache.sh ├── event-pattern-for-aws-health-event-issue └── example-output-from-health-event-issues ├── images ├── custom_offhours.png ├── maid_hours.png └── singlenodedeploy.png ├── msg-templates ├── acm-certificate-audit.html.j2 ├── cfn-garbage-collection-audit.html.j2 ├── cheatsheet ├── ebs-garbage-collection.html.j2 ├── ec2-garbage-collection-audit.html.j2 ├── ec2-public-whitelist.html.j2 ├── elasticsearch-security-audit.html.j2 ├── iam-policy-account-audit-summary.html.j2 ├── iam-policy-account-audit.html.j2 ├── iam-user-UpdateAccessKey-audit.html.j2 ├── iam-user-audit.html.j2 ├── mfa-audit-disable-access.html.j2 ├── mfa-audit-reminder.html.j2 ├── phd-issue.html.j2 ├── public-instance-audit.html.j2 ├── s3-prevent-bucket-creation.html.j2 ├── s3-public-audit.html.j2 ├── s3-service-limit-audit.html.j2 ├── s3-service-limit-audit.j2 ├── s3-target-bucket-audit.html.j2 ├── sgroup-delete-marked.html.j2 ├── slack-acm-certificate-audit.j2 ├── slack-cfn-garbage-collection-audit.j2 ├── slack-ebs-garbage-collection.j2 ├── slack-ec2-garbage-collection-audit.j2 ├── slack-elasticsearch-security-audit.j2 ├── slack-iam-policy-account-audit-summary.j2 ├── slack-iam-policy-account-audit.j2 ├── slack-iam-user-DeleteAccessKey-audit.j2 ├── slack-iam-user-DeleteLoginProfile-offboarding-audit ├── slack-iam-user-UpdateAccessKey-audit.j2 ├── slack-iam-user-UpdateAccessKey-offboarding-audit.j2 ├── slack-iam-user-audit.j2 ├── slack-jinja2-filter-template.j2 ├── slack-mfa-audit-disable-access.j2 ├── slack-mfa-audit-reminder.j2 ├── slack-mfa-audit.yml ├── slack-mfa-unused-audit.j2 ├── slack-phd-issue.j2 ├── slack-phd-notifications.j2 ├── slack-public-instance-audit.j2 ├── slack-s3-prevent-bucket-creation.j2 ├── slack-s3-public-audit.j2 ├── slack-s3-service-limit-audit.j2 ├── slack-s3-target-bucket-audit.j2 ├── slack-subnet-ip-address-usage-audit.j2 ├── slack-team-tag-ec2-audit.j2 ├── slack-team-tag-s3-audit.j2 ├── slack-termination-protection-audit.j2 ├── slack-unused-sgroup-audit.j2 ├── slack_delete-marked.html.j2 ├── slack_ec2-public-whitelist.j2 ├── subnet-ip-address-usage-audit.html.j2 ├── team-tag-ec2-audit.html.j2 ├── team-tag-s3-audit.html.j2 ├── termination-protection-audit.html.j2 └── unused-sgroup-audit.html.j2 ├── policies ├── acm-certificate-audit.yml ├── admin-group.yml ├── auto-team-tag.yml ├── autotag-owner.yml ├── c7n-org │ ├── CustomAccount │ │ ├── README.md │ │ ├── iam-user-CreateLoginProfile.yml │ │ └── iam-user-UpdateAccessKey-audit.yml │ ├── acm-certificate-cross-account-audit.yml │ ├── all-accounts.yml │ ├── app-elb.yml │ ├── cfn-garbage-collection-audit.yml │ ├── cheatsheet.txt │ ├── copy-instance-tags.yml │ ├── dynamodb-table.yml │ ├── ebs.yml │ ├── ecr.yml │ ├── ecs.yml │ ├── efs.yml │ ├── elasticip-address-audit.yml │ ├── elb.yml │ ├── es.yml │ ├── iam-group.yml │ ├── iam-mfa-audit.yml │ ├── iam-role.yml │ ├── iam.yml │ ├── iot.yml │ ├── lambda-get-function-list.yml │ ├── lambda.yml │ ├── public-instance-audit.yml │ ├── rest-api.yml │ ├── s3-global-grants-audit.yml │ ├── s3-prevent-bucket-creation.yml │ ├── s3-public-audit-scheduled-job.yml │ ├── s3-public-audit-test.yml │ ├── s3-public-audit.yml │ ├── secrets-manager.yml │ ├── sns.yml │ └── termination-protection-audit.yml ├── copy-instance-tags.yml ├── delete-marked-sgroups.yml ├── ebs-autocleanup-tag.yml ├── ebs-garbage-collection-lambda.yml ├── ebs-garbage-collection-with-tags.yml ├── ec2-garbage-collection-audit.yml ├── ec2-health-event.yml ├── ec2-publicipaddress-audit.yml ├── ec2.yml ├── elasticsearch-find-all-domains.yml ├── elasticsearch-security-audit.yml ├── emailer.yml ├── get-resources.yml ├── get_lambda_runtime_audit.yml ├── health-event-issues.yml ├── iam-ec2-policy-check.yml ├── iam-policy-CreatePolicy-audit.yml ├── iam-policy-CreatePolicyVersion-audit.yml ├── iam-policy-account-Summary-audit.yml ├── iam-policy-account-audit.yml ├── iam-role-with-managed-policy-audit.yml ├── iam-user-DeleteAccessKey.yml ├── iam-user-DeleteLoginProfile-offboarding.yml ├── iam-user-UpdateAccessKey-offboarding.yml ├── iam-user-administrator-access-audit.yml ├── iam-user-audit.yml ├── iam-user-set-groups.yml ├── iam-user-tagged-resources-audit.yml ├── iam.py ├── iam.yml ├── mailer.yml ├── mark-unused-sgroups.yml ├── mfa-audit-broken.yml ├── mfa-audit.yml ├── mfa-unused.yml ├── mfa.yml ├── new-user-audit.yml ├── offhours.yml ├── owner-tag-audit.yml ├── phd-notifications.yml ├── public-instance-audit.yml ├── public-subnet-instance-audit-lambda.yml ├── public-subnet-instance-audit-notify.yml ├── public-subnet-instance-audit-whitelist.yml ├── roles.yml ├── s3-prevent-bucket-creation.yml ├── s3-public-audit.yml ├── s3-server-access-logging.yml ├── s3-service-limit-audit.yml ├── s3-target-bucket-audit.yml ├── security-groups-unused-notify.yml ├── security-groups-unused.yml ├── sgroup-audit.yml ├── slack-notify.yml ├── ssm-managed-instance.yaml ├── stopped-instances.yml ├── subnet-ip-address-usage-audit.yml ├── tag-audit.yml ├── team-tag-ec2-audit.yml ├── team-tag-s3-audit.yml ├── termination-protection-audit.yml ├── termination-protection-list.yml ├── unused-sgroup-audit.yml └── vpn.yml ├── scripts ├── custodian-iam-user-cross-account-audit.sh ├── get-iam-roleids.sh ├── get-iam-userids.sh ├── list-custodian-schema-health-event-support.sh ├── report-with-user-input.sh ├── report.sh └── report_with_user_inputs_and_auto_commit.sh └── update-mailer-lambda.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 David Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cheatsheet.txt: -------------------------------------------------------------------------------- 1 | ============================ 2 | c7n-mailer Developer Install 3 | ============================ 4 | $ git clone https://github.com/capitalone/cloud-custodian 5 | $ cd cloud-custodian 6 | $ virtualenv c7n_mailer 7 | $ source c7n_mailer/bin/activate 8 | $ cd tools/c7n_mailer 9 | $ pip install -r requirements.txt 10 | $ python setup.py develop 11 | 12 | 13 | =================== 14 | Invoking c7n Mailer 15 | =================== 16 | c7n-mailer --config mailer.yml --update-lambda && custodian run -c test.yml -s . 17 | c7n-mailer --config mailer_iesandbox.yml --update-lambda && custodian run -c test.yml -s . 18 | 19 | 20 | =============================== 21 | Finding Default Email Templates 22 | =============================== 23 | find ~/ -type f -name "default.html.j2" 24 | find ~/ -type f -name "slack_default.j2" 25 | 26 | 27 | ============================== 28 | Clearing Cloud Custodian Cache 29 | ============================== 30 | $ custodian run --help 31 | $ rm ~/.cache/cloud-custodian.cache 32 | 33 | ============================== 34 | Getting Jenkins Version Number 35 | ============================== 36 | java -jar jenkins-cli.jar -s http://localhost:8080/ version 37 | 38 | ===================================================== 39 | Extracting Email Message Variable Names in Mailer SQS 40 | ===================================================== 41 | Copy the encoded SQS message into a file (e.g. result) 42 | Decode the text using: 43 | $ cat result | base64 -d > result.zlib 44 | $ printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - result.zlib | gzip -dc 45 | 46 | The printf is just to pad a proper header for gzip. Otherwise gzip will not be able to uncompress it. 47 | 48 | ======================================== 49 | Cloning a Development Branch for Testing 50 | ======================================== 51 | git clone -b mailer-test https://github.com/LykinsN/cloud-custodian.git 52 | 53 | 54 | =================== 55 | Useful Git Commands 56 | =================== 57 | git clone -b mailer-test https://github.com/LykinsN/cloud-custodian.git 58 | git pull (from directory branch was cloned) 59 | git branch -a (to view branch info) 60 | 61 | 62 | ======================================= 63 | AWS CLI to Create Dummy Security Groups 64 | ======================================= 65 | Create security groups in David's VPC Sandbox 66 | export AWS_PROFILE=sandbox 67 | aws ec2 create-security-group --group-name launch-wizard-10 --description "david.lin security group" --vpc-id vpc-2ea22555 68 | aws ec2 create-security-group --group-name launch-wizard-11 --description "david.lin security group" --vpc-id vpc-2ea22555 69 | aws ec2 create-security-group --group-name launch-wizard-12 --description "david.lin security group" --vpc-id vpc-2ea22555 70 | aws ec2 create-security-group --group-name launch-wizard-13 --description "david.lin security group" --vpc-id vpc-2ea22555 71 | aws ec2 create-security-group --group-name launch-wizard-14 --description "david.lin security group" --vpc-id vpc-2ea22555 72 | aws ec2 create-security-group --group-name launch-wizard-15 --description "david.lin security group" --vpc-id vpc-2ea22555 73 | 74 | ================ 75 | Custom Reporting 76 | ================ 77 | $ custodian report --format grid -s output public-instance-whitelist.yml --field KeyName=KeyName --field PublicIpAddress=PublicIpAddress --no-default-fields --field InstanceId=InstanceI d --field VpcId=VpcId --field tag:SubnetId=SubnetId 78 | 79 | $ custodian report -s output --no-default-fields --format grid --field InstanceId=InstanceId --field tag:Name=tag:Name --field InstanceType=InstanceType --field VpcId=VpcId --field tag: State=State.Name stopped.yml 80 | 81 | -------------------------------------------------------------------------------- /cleancache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # to find path of cache issue `sudo find / cloud-custodian.cache 4 | 5 | # for ubuntu 6 | rm ~/.cache/cloud-custodian.cache 7 | 8 | # for centos 9 | # rm /home/ec2-user/.cache/cloud-custodian.cache 10 | 11 | echo 'Cloud Custodian cache deleted' 12 | -------------------------------------------------------------------------------- /cron/crontab.txt: -------------------------------------------------------------------------------- 1 | 0 17 * * * /home/ubuntu/cloudcustodian/cron/mfa-audit.sh > /home/ubuntu/cloudcustodian/cron/mfa-audit.log 2>&1 2 | 3 | -------------------------------------------------------------------------------- /cron/mfa-audit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PATH=/home/ubuntu/bin:/home/ubuntu/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin 3 | export PATH 4 | source c7n_mailer/bin/activate 5 | echo "Running MFA audit policies..." 6 | custodian run -c /home/ubuntu/cloudcustodian/policies/mfa-audit.yml -s output --region us-east-1 7 | echo "MFA audit policies completed" 8 | 9 | 10 | -------------------------------------------------------------------------------- /custom-site-packages/README.md: -------------------------------------------------------------------------------- 1 | The custom iam.py site-package should live in c7n_mailer site-package directory: 2 | 3 | /home/ubuntu/c7n_mailer/lib/python2.7/site-packages/c7n/resources/iam.py 4 | 5 | 6 | The following block of code was modified to support filtering 7 | on specific IAM Policy actions: 8 | 9 |
10 | for s in statements:
11 |     if ('Condition' not in s and
12 |             'Action' in s and
13 |             ('account:*' in s['Action'] or
14 |             'account:EnableRegion' in s['Action']) and
15 |             'Resource' in s and
16 |             isinstance(s['Resource'], six.string_types) and
17 |             s['Resource'] == "*" and
18 |             s['Effect'] == "Allow"):
19 |         return True
20 | return False
21 | 
22 | -------------------------------------------------------------------------------- /examples/cheatsheet.txt: -------------------------------------------------------------------------------- 1 | ============================ 2 | c7n-mailer Developer Install 3 | ============================ 4 | $ git clone https://github.com/capitalone/cloud-custodian 5 | $ cd cloud-custodian 6 | $ virtualenv c7n_mailer 7 | $ source c7n_mailer/bin/activate 8 | $ cd tools/c7n_mailer 9 | $ pip install -r requirements.txt 10 | $ python setup.py develop 11 | 12 | 13 | =================== 14 | Invoking c7n Mailer 15 | =================== 16 | c7n-mailer --config mailer.yml --update-lambda && custodian run -c test.yml -s . 17 | c7n-mailer --config mailer_iesandbox.yml --update-lambda && custodian run -c test.yml -s . 18 | 19 | 20 | =============================== 21 | Finding Default Email Templates 22 | =============================== 23 | find ~/ -type f -name "default.html.j2" 24 | find ~/ -type f -name "slack_default.j2" 25 | 26 | 27 | ============================== 28 | Clearing Cloud Custodian Cache 29 | ============================== 30 | $ custodian run --help 31 | $ rm ~/.cache/cloud-custodian.cache 32 | 33 | 34 | ======================================== 35 | Cloning a Development Branch for Testing 36 | ======================================== 37 | git clone -b mailer-test https://github.com/LykinsN/cloud-custodian.git 38 | 39 | 40 | =================== 41 | Useful Git Commands 42 | =================== 43 | git clone -b mailer-test https://github.com/LykinsN/cloud-custodian.git 44 | git pull (from directory branch was cloned) 45 | git branch -a (to view branch info) 46 | 47 | 48 | ======================================= 49 | AWS CLI to Create Dummy Security Groups 50 | ======================================= 51 | Create security groups in David's VPC Sandbox 52 | export AWS_PROFILE=sandbox 53 | aws ec2 create-security-group --group-name launch-wizard-10 --description "david.lin security group" --vpc-id vpc-2ea22555 54 | aws ec2 create-security-group --group-name launch-wizard-11 --description "david.lin security group" --vpc-id vpc-2ea22555 55 | aws ec2 create-security-group --group-name launch-wizard-12 --description "david.lin security group" --vpc-id vpc-2ea22555 56 | aws ec2 create-security-group --group-name launch-wizard-13 --description "david.lin security group" --vpc-id vpc-2ea22555 57 | aws ec2 create-security-group --group-name launch-wizard-14 --description "david.lin security group" --vpc-id vpc-2ea22555 58 | aws ec2 create-security-group --group-name launch-wizard-15 --description "david.lin security group" --vpc-id vpc-2ea22555 59 | 60 | ================ 61 | Custom Reporting 62 | ================ 63 | $ custodian report --format grid -s output public-instance-whitelist.yml --field KeyName=KeyName --field PublicIpAddress=PublicIpAddress --no-default-fields --field InstanceId=InstanceI d --field VpcId=VpcId --field tag:SubnetId=SubnetId 64 | 65 | $ custodian report -s output --no-default-fields --format grid --field InstanceId=InstanceId --field tag:Name=tag:Name --field InstanceType=InstanceType --field VpcId=VpcId --field tag: State=State.Name stopped.yml 66 | 67 | -------------------------------------------------------------------------------- /examples/cleancache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm ~/.cache/cloud-custodian.cache 3 | 4 | -------------------------------------------------------------------------------- /examples/event-pattern-for-aws-health-event-issue: -------------------------------------------------------------------------------- 1 | If you want this rule to get triggered for all AWS services, 2 | you will not be able to use "detail" such as "eventTypeCategory" [1]. 3 | Therefore, the pattern to monitor all AWS Health events is: 4 | 5 | 6 | { 7 | "source": [ 8 | "aws.health" 9 | ], 10 | "detail-type": [ 11 | "AWS Health Event" 12 | ] 13 | } 14 | 15 | If you want this to get triggered for a specific service (e.g. ELB), you can change it to the following: 16 | 17 | 18 | { 19 | "source": [ 20 | "aws.health" 21 | ], 22 | "detail-type": [ 23 | "AWS Health Event" 24 | ], 25 | "detail": { 26 | "service": [ 27 | "ELASTICLOADBALANCING" 28 | ], 29 | "eventTypeCategory": [ 30 | "issue" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/example-output-from-health-event-issues: -------------------------------------------------------------------------------- 1 | { 2 | "arn": "arn:aws:health:us-east-1::event/INTERNETCONNECTIVITY/AWS_INTERNETCONNECTIVITY_OPERATIONAL_ISSUE/AWS_INTERNETCONNECTIVITY_OPERATIONAL_ISSUE_XOIUP_161168 3 | 1635", 4 | "service": "INTERNETCONNECTIVITY", 5 | "eventTypeCode": "AWS_INTERNETCONNECTIVITY_OPERATIONAL_ISSUE", 6 | "eventTypeCategory": "issue", 7 | "region": "us-east-1", 8 | "startTime": "2021-01-26T17:20:35.521000+00:00", 9 | "lastUpdatedTime": "2021-01-26T17:23:08.321000+00:00", 10 | "statusCode": "open", 11 | "eventScopeCode": "PUBLIC", 12 | "Description": "External Network Connectivity Issues\n\n[09:20 AM PST] We are investigating connectivity issues with an internet provider, mainly affecting the 13 | East Coast of the United States, outside of the AWS Network. We are investigating the issue with the external provider.", 14 | "AffectedEntities": [ 15 | { 16 | "entityValue": "UNKNOWN", 17 | "lastUpdatedTime": "2021-01-26T17:23:08.321000+00:00" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /images/custom_offhours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidclin/cloudcustodian-policies/1cbfbb798ac43dce806aa4c0ddcc6848ba788144/images/custom_offhours.png -------------------------------------------------------------------------------- /images/maid_hours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidclin/cloudcustodian-policies/1cbfbb798ac43dce806aa4c0ddcc6848ba788144/images/maid_hours.png -------------------------------------------------------------------------------- /images/singlenodedeploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidclin/cloudcustodian-policies/1cbfbb798ac43dce806aa4c0ddcc6848ba788144/images/singlenodedeploy.png -------------------------------------------------------------------------------- /msg-templates/cheatsheet: -------------------------------------------------------------------------------- 1 | ============================================ 2 | Finding Path to c7n-mailer Default Templates 3 | ============================================ 4 | find ~/ -type f -name "default.html.j2" (for email) 5 | find ~/ -type f -name "slack_default.j2" (for Slack) 6 | 7 | =============================== 8 | All possible msg template paths 9 | =============================== 10 | /home/ubuntu/cloud-custodian/tools/c7n_mailer/tests/test-templates/slack_default.j2 11 | /home/ubuntu/cloud-custodian/tools/c7n_mailer/c7n_mailer/msg-templates/slack_default.j2 12 | /home/ubuntu/junk/lib/python3.6/site-packages/c7n_mailer/msg-templates/slack_default.j2 13 | /home/ubuntu/custodian/lib/python3.6/site-packages/c7n_mailer/msg-templates/slack_default.j2 14 | 15 | ======================================================== 16 | Copy templates to all possible msg templates directories 17 | ======================================================== 18 | export slack_template="slack_template_filename_goes_here" 19 | export email_template="email_template_filename_goes_here" 20 | 21 | cp $email_template /home/ubuntu/cloud-custodian/tools/c7n_mailer/tests/test-templates/ 22 | cp $email_template /home/ubuntu/cloud-custodian/tools/c7n_mailer/c7n_mailer/msg-templates/ 23 | cp $email_template /home/ubuntu/junk/lib/python3.6/site-packages/c7n_mailer/msg-templates/ 24 | cp $email_template /home/ubuntu/custodian/lib/python3.6/site-packages/c7n_mailer/msg-templates/ 25 | 26 | cp $slack_template /home/ubuntu/cloud-custodian/tools/c7n_mailer/tests/test-templates/ 27 | cp $slack_template /home/ubuntu/cloud-custodian/tools/c7n_mailer/c7n_mailer/msg-templates/ 28 | cp $slack_template /home/ubuntu/junk/lib/python3.6/site-packages/c7n_mailer/msg-templates/ 29 | cp $slack_template /home/ubuntu/custodian/lib/python3.6/site-packages/c7n_mailer/msg-templates/ 30 | 31 | ============================================ 32 | Update msg templates using c7n-mailer Lambda 33 | ============================================ 34 | export policy="policy_filename_goes_here" 35 | 36 | from ~/cloudcustodian/policies directory run: 37 | c7n-mailer --config /home/ubuntu/cloudcustodian/mailer/mailer.yml --update-lambda && custodian run -c $policy -s . 38 | -------------------------------------------------------------------------------- /msg-templates/s3-prevent-bucket-creation.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {# 5 | Sample Policy that can be used with this template: 6 | 7 | Additional parameters can be passed in from the policy - i.e. action_desc, violation_desc 8 | 9 | - name: delete-unencrypted-ec2 10 | resource: ec2 11 | filters: 12 | - type: ebs 13 | key: Encrypted 14 | value: false 15 | actions: 16 | - terminate 17 | - type: notify 18 | template: default.html 19 | subject: "[custodian {{ account }}] Delete Unencrypted EC2 - {{ region }}" 20 | violation_desc: "The following EC2(s) are not encrypted:" 21 | action_desc: "The EC2(s) have been terminated" 22 | from: custodian@domain.com 23 | to: 24 | - owner@domain.com 25 | transport: 26 | type: sqs 27 | queue: https://sqs.us-east-1.amazonaws.com/12345678910/custodian-sqs-queue 28 | #} 29 | 30 | 31 | {# You can set any mandatory tags here, and they will be formatted/outputted in the message #} 32 | {% set requiredTags = ['Application','Owner'] %} 33 | 34 | {# The macros below format some resource attributes for better presentation #} 35 | {% macro getTag(resource, tagKey) -%} 36 | {% if resource.get('Tags') %} 37 | {% for t in resource.get('Tags') %} 38 | {% if t.get('Key') == tagKey %} 39 | {{ t.get('Value') }} 40 | {% endif %} 41 | {% endfor %} 42 | {% endif %} 43 | {%- endmacro %} 44 | 45 | {% macro extractList(resource, column) -%} 46 | {% for p in resource.get(column) %} 47 | {{ p }}, 48 | {% endfor %} 49 | {%- endmacro %} 50 | 51 | {% macro columnHeading(columnNames, tableWidth) -%} 52 | 53 | {% for columnName in columnNames %} 54 | 55 | {% endfor %} 56 | {%- endmacro %} 57 | 58 | {# The macro below creates the table: 59 | Formatting can be dependent on the column names that are passed in 60 | #} 61 | {% macro columnData(resources, columnNames) -%} 62 | {% for resource in resources %} 63 | 64 | {% for columnName in columnNames %} 65 | {% if columnName in requiredTags %} 66 | 67 | {% elif columnName == 'tag.Name' %} 68 | 69 | {% elif columnName == 'InstanceCount' %} 70 | 71 | {% elif columnName == 'VolumeConsumedReadWriteOps' %} 72 | 73 | {% elif columnName == 'PublicIp' %} 74 | 75 | {% else %} 76 | 77 | {% endif %} 78 | {% endfor %} 79 | 80 | {% endfor %} 81 |
{{ columnName }}
{{ getTag(resource,columnName) }}{{ getTag(resource,'Name') }}{{ resource['Instances'] | length }}{{ resource['c7n.metrics']['AWS/EBS.VolumeConsumedReadWriteOps.Maximum'][0]['Maximum'] }}{{ resource['NetworkInterfaces'][0].get('Association')['PublicIp'] }}{{ resource[columnName] }}
82 | {%- endmacro %} 83 | 84 | {# Main #} 85 | {% macro createTable(columnNames, resources, tableWidth) %} 86 | {{ columnHeading(columnNames, tableWidth) }} 87 | {{ columnData(resources, columnNames) }} 88 | {%- endmacro %} 89 | 90 | 91 | Custodian Notification - {{ account }} 92 | 93 | 94 | 131 | 132 | 133 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /msg-templates/s3-public-audit.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {# 5 | Sample Policy that can be used with this template: 6 | 7 | Additional parameters can be passed in from the policy - i.e. action_desc, violation_desc 8 | 9 | - name: delete-unencrypted-ec2 10 | resource: ec2 11 | filters: 12 | - type: ebs 13 | key: Encrypted 14 | value: false 15 | actions: 16 | - terminate 17 | - type: notify 18 | template: default.html 19 | subject: "[custodian {{ account }}] Delete Unencrypted EC2 - {{ region }}" 20 | violation_desc: "The following EC2(s) are not encrypted:" 21 | action_desc: "The EC2(s) have been terminated" 22 | from: custodian@domain.com 23 | to: 24 | - owner@domain.com 25 | transport: 26 | type: sqs 27 | queue: https://sqs.us-east-1.amazonaws.com/12345678910/custodian-sqs-queue 28 | #} 29 | 30 | 31 | {# You can set any mandatory tags here, and they will be formatted/outputted in the message #} 32 | {% set requiredTags = ['Application','Owner'] %} 33 | 34 | {# The macros below format some resource attributes for better presentation #} 35 | {% macro getTag(resource, tagKey) -%} 36 | {% if resource.get('Tags') %} 37 | {% for t in resource.get('Tags') %} 38 | {% if t.get('Key') == tagKey %} 39 | {{ t.get('Value') }} 40 | {% endif %} 41 | {% endfor %} 42 | {% endif %} 43 | {%- endmacro %} 44 | 45 | {% macro extractList(resource, column) -%} 46 | {% for p in resource.get(column) %} 47 | {{ p }}, 48 | {% endfor %} 49 | {%- endmacro %} 50 | 51 | {% macro columnHeading(columnNames, tableWidth) -%} 52 | 53 | {% for columnName in columnNames %} 54 | 55 | {% endfor %} 56 | {%- endmacro %} 57 | 58 | {# The macro below creates the table: 59 | Formatting can be dependent on the column names that are passed in 60 | #} 61 | {% macro columnData(resources, columnNames) -%} 62 | {% for resource in resources %} 63 | 64 | {% for columnName in columnNames %} 65 | {% if columnName in requiredTags %} 66 | 67 | {% elif columnName == 'tag.Name' %} 68 | 69 | {% elif columnName == 'InstanceCount' %} 70 | 71 | {% elif columnName == 'VolumeConsumedReadWriteOps' %} 72 | 73 | {% elif columnName == 'PublicIp' %} 74 | 75 | {% else %} 76 | 77 | {% endif %} 78 | {% endfor %} 79 | 80 | {% endfor %} 81 |
{{ columnName }}
{{ getTag(resource,columnName) }}{{ getTag(resource,'Name') }}{{ resource['Instances'] | length }}{{ resource['c7n.metrics']['AWS/EBS.VolumeConsumedReadWriteOps.Maximum'][0]['Maximum'] }}{{ resource['NetworkInterfaces'][0].get('Association')['PublicIp'] }}{{ resource[columnName] }}
82 | {%- endmacro %} 83 | 84 | {# Main #} 85 | {% macro createTable(columnNames, resources, tableWidth) %} 86 | {{ columnHeading(columnNames, tableWidth) }} 87 | {{ columnData(resources, columnNames) }} 88 | {%- endmacro %} 89 | 90 | 91 | Custodian Notification - {{ account }} 92 | 93 | 94 | 131 | 132 | 133 | 292 | 293 | 294 | -------------------------------------------------------------------------------- /msg-templates/slack-acm-certificate-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian ACM Certificate Audit", 5 | "title":"ACM Certificate Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Description", 10 | "value":"ACM certificate(s) found nearing their expiration date <60 days" 11 | }, 12 | { 13 | "title":"Domain Name(s)", 14 | "value":"{{ resources | selectattr('DomainName') | map(attribute='DomainName') | list }}" 15 | }, 16 | { 17 | "title":"Expiration Date(s)", 18 | "value":"{{ resources | selectattr('NotAfter') | map(attribute='NotAfter') | list }}" 19 | }, 20 | { 21 | "title":"Certificate Arn(s)", 22 | "value":"{{ resources | selectattr('CertificateArn') | map(attribute='CertificateArn') | list }}" 23 | }, 24 | { 25 | "title":"Account ID", 26 | "value":"{{ account_id }}" 27 | }, 28 | { 29 | "title":"Region", 30 | "value":"{{ region }}" 31 | }, 32 | { 33 | "title":"Action Description", 34 | "value":"See email notification for details." 35 | } 36 | ] 37 | } 38 | ], 39 | "channel":"{{ recipient }}", 40 | "username":"Custodian" 41 | } 42 | -------------------------------------------------------------------------------- /msg-templates/slack-cfn-garbage-collection-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Garbage Collection", 5 | "title":"CloudFormation Stack Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"CloudFormation stack found older than 3 days", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account ID", 16 | "value":"{{ account_id }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Delete IAM Pipeline Training CloudFormation stacks that have 'iam-challenge' in the name and older than 3 days. No further action necessary." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-ebs-garbage-collection.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"EBS Garbage Collection", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Available EBS Volumes Older than 1 Day :", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account", 16 | "value":"{{ account }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Unused EBS volumes deleted. No further action is required on your part." 25 | }, 26 | { 27 | "title":"Note:", 28 | "value":"This is informational only. Check email for more details." 29 | } 30 | ] 31 | } 32 | ], 33 | "channel":"{{ recipient }}", 34 | "username":"Custodian" 35 | } 36 | -------------------------------------------------------------------------------- /msg-templates/slack-ec2-garbage-collection-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"EC2 Packer Builder Reaper Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Packer Builder Instance(s) found with age greater than 1 hour", 10 | "value":"{{ resources | selectattr('InstanceId') | map(attribute='InstanceId') | list }}" 11 | }, 12 | { 13 | "title":"Account ID", 14 | "value":"{{ account_id }}" 15 | }, 16 | { 17 | "title":"Region", 18 | "value":"{{ region }}" 19 | }, 20 | { 21 | "title":"Action Description", 22 | "value":"All Packer Builder instances older than 1 hr have been deleted. This notification is informational only. No action is required on your part." 23 | } 24 | ] 25 | } 26 | ], 27 | "channel":"{{ recipient }}", 28 | "username":"Custodian" 29 | } 30 | -------------------------------------------------------------------------------- /msg-templates/slack-elasticsearch-security-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"ElasticSearch Security Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Info", 10 | "value":"An ES domain was found with access policy that is too permissive." 11 | }, 12 | { 13 | "title":"Account", 14 | "value":"{{ account }}" 15 | }, 16 | { 17 | "title":"Region", 18 | "value":"{{ region }}" 19 | }, 20 | { 21 | "title":"Action Description", 22 | "value":"Email notification sent. See email for details." 23 | } 24 | ] 25 | } 26 | ], 27 | "channel":"{{ recipient }}", 28 | "username":"Custodian" 29 | } 30 | -------------------------------------------------------------------------------- /msg-templates/slack-iam-policy-account-audit-summary.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM Policy Audit - Summary", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"IAM policies found containing the account:* or account:EnableRegion action", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account ID", 16 | "value":"{{ account_id }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent. " 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-iam-policy-account-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM Policy Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"IAM policy created or modified containing the account:* action or account:EnableRegion", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account ID", 16 | "value":"{{ account_id }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent. " 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-iam-user-DeleteAccessKey-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM User Access Key Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Access key Deleted for IAM User", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"AccessKeyId", 16 | "value":"{{ resources | selectattr('UserId') | map(attribute='UserId') | list }}" 17 | }, 18 | { 19 | "title":"Changed by", 20 | "value":"{{ event.detail.userIdentity.userName }}" 21 | }, 22 | { 23 | "title":"Account ID", 24 | "value":"{{ account_id }}" 25 | }, 26 | { 27 | "title":"Region", 28 | "value":"{{ region }}" 29 | }, 30 | { 31 | "title":"Action Description", 32 | "value":"This is informational only. No action required. " 33 | } 34 | ] 35 | } 36 | ], 37 | "channel":"{{ recipient }}", 38 | "username":"Custodian" 39 | } 40 | -------------------------------------------------------------------------------- /msg-templates/slack-iam-user-DeleteLoginProfile-offboarding-audit: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM User Management Console Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Management console disabled for IAM User", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Management console disabled by", 16 | "value":"{{ event.detail.userIdentity.userName }}" 17 | }, 18 | { 19 | "title":"Account ID", 20 | "value":"{{ account_id }}" 21 | }, 22 | { 23 | "title":"Region", 24 | "value":"{{ region }}" 25 | }, 26 | { 27 | "title":"Action Description", 28 | "value":"This is informational only. No action required." 29 | } 30 | ] 31 | } 32 | ], 33 | "channel":"{{ recipient }}", 34 | "username":"Custodian" 35 | } 36 | -------------------------------------------------------------------------------- /msg-templates/slack-iam-user-UpdateAccessKey-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM User Access Key Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Disabled IAM User Found with Re-activated Access Key", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account ID", 16 | "value":"{{ account_id }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent. " 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-iam-user-UpdateAccessKey-offboarding-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM User Access Key Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Access key disabled for IAM User", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Changed by", 16 | "value":"{{ event.detail.userIdentity.userName }}" 17 | }, 18 | { 19 | "title":"Account ID", 20 | "value":"{{ account_id }}" 21 | }, 22 | { 23 | "title":"Region", 24 | "value":"{{ region }}" 25 | }, 26 | { 27 | "title":"Action Description", 28 | "value":"This is informational only. No action required. " 29 | } 30 | ] 31 | } 32 | ], 33 | "channel":"{{ recipient }}", 34 | "username":"Custodian" 35 | } 36 | -------------------------------------------------------------------------------- /msg-templates/slack-iam-user-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM User(s) Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"IAM Users not in the Ec2Instance Launchers Group but have AmazonEC2FullAccess", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account", 16 | "value":"{{ account }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-jinja2-filter-template.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian ACM Certificate Audit", 5 | "title":"ACM Certificate Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Description", 10 | "value":"ACM certificate(s) found nearing their expiration date <60 days" 11 | }, 12 | { 13 | "title":"Domain Name(s)", 14 | "value":"{{ resources | selectattr('DomainName') | map(attribute='DomainName') | list }}" 15 | }, 16 | { 17 | "title":"Expiration Date(s)", 18 | "value":"{{ resources | selectattr('NotAfter') | map(attribute='NotAfter') | list }}" 19 | }, 20 | { 21 | "title":"Certificate Arn(s)", 22 | "value":"{{ resources | selectattr('CertificateArn') | map(attribute='CertificateArn') | list }}" 23 | }, 24 | { 25 | "title":"Account ID", 26 | "value":"{{ account_id }}" 27 | }, 28 | { 29 | "title":"Region", 30 | "value":"{{ region }}" 31 | }, 32 | { 33 | "title":"Action Description", 34 | "value":"See email notification for details." 35 | } 36 | ] 37 | } 38 | ], 39 | "channel":"{{ recipient }}", 40 | "username":"Custodian" 41 | } 42 | -------------------------------------------------------------------------------- /msg-templates/slack-mfa-audit-disable-access.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM Users in Administrators Group with MFA Disabled", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"IAM User Name(s)", 10 | "value":"{{ resources | selectattr('UserName') | map(attribute='UserName') | list }}" 11 | }, 12 | { 13 | "title":"Create Date", 14 | "value":"{{ resources | selectattr('CreateDate') | map(attribute='CreateDate') | list }}" 15 | }, 16 | { 17 | "title":"Account", 18 | "value":"{{ account }}" 19 | }, 20 | { 21 | "title":"Region", 22 | "value":"{{ region }}" 23 | }, 24 | { 25 | "title":"Action Description", 26 | "value":"Console access disabled. Access keys deleted. Please work with user if access is still required and make sure MFA gets enabled. 27 | } 28 | ] 29 | } 30 | ], 31 | "channel":"{{ recipient }}", 32 | "username":"Custodian" 33 | } 34 | -------------------------------------------------------------------------------- /msg-templates/slack-mfa-audit-reminder.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"Reminder to enable MFA", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"User Name(s)", 10 | "value":"{{ resources | selectattr('UserName') | map(attribute='UserName') | list }}" 11 | }, 12 | { 13 | "title":"Create Date", 14 | "value":"{{ resources | selectattr('CreateDate') | map(attribute='CreateDate') | list }}" 15 | }, 16 | { 17 | "title":"Account", 18 | "value":"{{ account }}" 19 | }, 20 | { 21 | "title":"Region", 22 | "value":"{{ region }}" 23 | }, 24 | { 25 | "title":"Action Description", 26 | "value":"If your user name is on this list, please enable MFA before access is disabled." 27 | }, 28 | ] 29 | } 30 | ], 31 | "channel":"{{ recipient }}", 32 | "username":"Custodian" 33 | } 34 | -------------------------------------------------------------------------------- /msg-templates/slack-mfa-audit.yml: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"Security Audit: Detected Admins with MFA Disabled", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"IAM User(s)", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account ID", 16 | "value":"{{ account_id }}" 17 | }, 18 | { 19 | "title":"Action", 20 | "value":"Please work with user(s) to enable MFA." 21 | } 22 | ] 23 | } 24 | ], 25 | "channel":"{{ recipient }}", 26 | "username":"Custodian" 27 | } 28 | -------------------------------------------------------------------------------- /msg-templates/slack-mfa-unused-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"IAM Users in Administrators Group with MFA Disabled", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Resources", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Region", 16 | "value":"{{ region }}" 17 | }, 18 | { 19 | "title":"Action Description", 20 | "value":"Console access disabled. Access keys deleted." 21 | }, 22 | { 23 | "title":"Note", 24 | "value":"Users will need to contact IE Team to regain access." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-phd-issue.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Personal Health Dashboard (PHD) Operational Issue", 5 | "title":"Personal Health Dashboard (PHD) Operational Notification", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Account ID", 10 | "value":"{{ account_id }}" 11 | }, 12 | { 13 | "title":"Region", 14 | "value":"{{ region }}" 15 | }, 16 | { 17 | "title":"Service(s)", 18 | "value":"{{ resources | selectattr('service') | map(attribute='service') | list }}" 19 | }, 20 | { 21 | "title":"Action", 22 | "value":"See Personal Health Dashboard 'Open issues' tab @ phd.aws.amazon.com for more info. Note, you may need to click the View event log to see details." 23 | } 24 | ] 25 | } 26 | ], 27 | "channel":"{{ recipient }}", 28 | "username":"Custodian" 29 | } 30 | -------------------------------------------------------------------------------- /msg-templates/slack-phd-notifications.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Personal Health Dashboard (PHD)", 5 | "title":"Personal Health Dashboard (PHD) Notification", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Account ID", 10 | "value":"{{ account_id }}" 11 | }, 12 | { 13 | "title":"Region", 14 | "value":"{{ region }}" 15 | }, 16 | { 17 | "title":"Service(s)", 18 | "value":"{{ resources | selectattr('service') | map(attribute='service') | list }}" 19 | }, 20 | { 21 | "title":"Action", 22 | "value":"See Personal Health Dashboard 'Other notifications' tab @ phd.aws.amazon.com for more info." 23 | } 24 | ] 25 | } 26 | ], 27 | "channel":"{{ recipient }}", 28 | "username":"Custodian" 29 | } 30 | -------------------------------------------------------------------------------- /msg-templates/slack-public-instance-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"EC2 Instance Public Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"EC2 Instance was launched with Public IP and Public subnet", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account", 16 | "value":"{{ account }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent containing KeyName." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-s3-prevent-bucket-creation.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"Request to Create New S3 Bucket Rejected", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"S3 Bucket Name", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account", 16 | "value":"{{ account }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-s3-public-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"Public S3 Bucket Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"S3 Bucket Name", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account", 16 | "value":"{{ account }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-s3-service-limit-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"S3 Service Limit Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"S3 Service Limit Threshold Exceeded:", 10 | "value":"It may be time to increase the S3 service limit or do some housekeeping." 11 | }, 12 | { 13 | "title":"Account", 14 | "value":"{{ account }}" 15 | }, 16 | { 17 | "title":"Region", 18 | "value":"{{ region }}" 19 | }, 20 | { 21 | "title":"Action Description", 22 | "value":"Email notification sent." 23 | } 24 | ] 25 | } 26 | ], 27 | "channel":"{{ recipient }}", 28 | "username":"Custodian" 29 | } 30 | -------------------------------------------------------------------------------- /msg-templates/slack-s3-target-bucket-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"S3 Target Bucket Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Notifcation:", 10 | "value":"S3 buckets were found with non-compliant target bucket names." 11 | }, 12 | { 13 | "title":"Account", 14 | "value":"{{ account }}" 15 | }, 16 | { 17 | "title":"Region", 18 | "value":"{{ region }}" 19 | }, 20 | { 21 | "title":"Action Description", 22 | "value":"Email notification sent." 23 | } 24 | ] 25 | } 26 | ], 27 | "channel":"{{ recipient }}", 28 | "username":"Custodian" 29 | } 30 | -------------------------------------------------------------------------------- /msg-templates/slack-subnet-ip-address-usage-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Subnet IP Address Usage Audit", 5 | "title":"Subnet IP Address Usage Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Account ID", 10 | "value":"{{ account_id }}" 11 | }, 12 | { 13 | "title":"Region", 14 | "value":"{{ region }}" 15 | }, 16 | { 17 | "title":"SubnetId(s)", 18 | "value":"{{ resources | selectattr('SubnetId') | map(attribute='SubnetId') | list }}" 19 | }, 20 | { 21 | "title":"AvailableIpAddressCount(s)", 22 | "value":"{{ resources | selectattr('AvailableIpAddressCount') | map(attribute='AvailableIpAddressCount') | list }}" 23 | }, 24 | { 25 | "title":"CidrBlock(s)", 26 | "value":"{{ resources | selectattr('CidrBlock') | map(attribute='CidrBlock') | list }}" 27 | }, 28 | { 29 | "title":"AvailabilityZone(s)", 30 | "value":"{{ resources | selectattr('AvailabilityZone') | map(attribute='AvailabilityZone') | list }}" 31 | }, 32 | { 33 | "title":"Action Description", 34 | "value":"See email notification for more details." 35 | } 36 | ] 37 | } 38 | ], 39 | "channel":"{{ recipient }}", 40 | "username":"Custodian" 41 | } 42 | -------------------------------------------------------------------------------- /msg-templates/slack-team-tag-ec2-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"EC2 Team Tag Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Instance(s) found with absent or empty Team tag", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account ID", 16 | "value":"{{ account_id }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent containing KeyName(s)." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-team-tag-s3-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"S3 Team Tag Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Buckets(s) found with absent or empty Team tag", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account ID", 16 | "value":"{{ account_id }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-termination-protection-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"EC2 Termination Protection Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"White Listed EC2 Instances Found with Termination Protection Disabled:", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account", 16 | "value":"{{ account }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Email notification sent." 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /msg-templates/slack-unused-sgroup-audit.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"Security Group Audit", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Unused Security Groups that match '*wizard':", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Account", 16 | "value":"{{ account }}" 17 | }, 18 | { 19 | "title":"Region", 20 | "value":"{{ region }}" 21 | }, 22 | { 23 | "title":"Action Description", 24 | "value":"Unused security groups deleted." 25 | }, 26 | { 27 | "title":"Note:", 28 | "value":"Check email for more details." 29 | } 30 | ] 31 | } 32 | ], 33 | "channel":"{{ recipient }}", 34 | "username":"Custodian" 35 | } 36 | -------------------------------------------------------------------------------- /msg-templates/slack_delete-marked.html.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Garbage Collection", 5 | "title":"Unused Security Groups", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Resources", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Region", 16 | "value":"{{ region }}" 17 | }, 18 | { 19 | "title":"Status", 20 | "value":"Unused security groups marked for deletion successfully deleted." 21 | } 22 | ] 23 | } 24 | ], 25 | "channel":"{{ recipient }}", 26 | "username":"Custodian" 27 | } 28 | -------------------------------------------------------------------------------- /msg-templates/slack_ec2-public-whitelist.j2: -------------------------------------------------------------------------------- 1 | { 2 | "attachments":[ 3 | { 4 | "fallback":"Cloud Custodian Policy Violation", 5 | "title":"Detected EC2 instance launched in public subnet", 6 | "color":"danger", 7 | "fields":[ 8 | { 9 | "title":"Resources", 10 | "value":"{%- for resource in resources -%} 11 | {{ format_resource(resource, policy['resource']) }} 12 | {%- endfor -%}" 13 | }, 14 | { 15 | "title":"Region", 16 | "value":"{{ region }}" 17 | }, 18 | { 19 | "title":"Action Description", 20 | "value":"EC2 instance was immediately terminated" 21 | }, 22 | { 23 | "title":"Note", 24 | "value":"Check CloudTrail to correlate who launched instance" 25 | } 26 | ] 27 | } 28 | ], 29 | "channel":"{{ recipient }}", 30 | "username":"Custodian" 31 | } 32 | -------------------------------------------------------------------------------- /policies/acm-certificate-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: acm-certificate-audit 3 | resource: acm-certificate 4 | description: | 5 | Retrieve list of ACM certificates and 6 | send notifications if expiration reaches 7 | given threshold 8 | filters: 9 | - or: 10 | - "tag:Audit": absent 11 | - "tag:Audit": empty 12 | - type: value 13 | key: Name 14 | op: regex 15 | value: ".*" 16 | - type: value 17 | key: NotAfter 18 | op: less-than 19 | value_type: expiration 20 | value: 60 21 | mode: 22 | type: periodic 23 | role: arn:aws:iam::XXXXXXXXXXXX:role/CloudCustodian 24 | schedule: "rate(12 days)" 25 | packages: [boto3, botocore, urllib3] 26 | actions: 27 | - type: post-finding 28 | severity_normalized: 10 29 | types: 30 | - "Software and Configuration Checks/AWS Security Best Practices" 31 | - type: notify 32 | template: acm-certificate-audit.html 33 | slack_template: slack-acm-certificate-audit 34 | template_format: 'html' 35 | priority_header: '5' 36 | subject: 'ACM Certificate about to expire' 37 | to: 38 | - cloudcustodianadmins@company.com 39 | - slack://#my-slack-channel 40 | owner_absent_contact: 41 | - cloudcustodianadmin@company.com 42 | transport: 43 | type: sqs 44 | queue: https://sqs.us-east-1.amazonaws.com/XXXXXXXXXXXX/cloud-cloudcustodian 45 | -------------------------------------------------------------------------------- /policies/admin-group.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-users-in-admin-group 3 | resource: iam-user 4 | description: | 5 | Retrieve list of IAM users in the group named 'Administrators'. 6 | filters: 7 | - type: group 8 | key: GroupName 9 | value: Administrators 10 | -------------------------------------------------------------------------------- /policies/auto-team-tag.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: tag-team-infra 3 | resource: ec2 4 | comment: | 5 | Cloud Custodian EC2 Team tag based on the owner 6 | filters: 7 | - "tag:Team": absent 8 | - type: value 9 | key: "tag:Owner" 10 | value: (.*david\.lin|.*john\.doe) 11 | op: regex 12 | actions: 13 | - type: tag 14 | key: "Team" 15 | value: "InfrastuctureTeam" 16 | - name: tag-team-it 17 | resource: ec2 18 | comment: | 19 | Cloud Custodian EC2 Team tag based on the owner 20 | filters: 21 | - "tag:Team": absent 22 | - type: value 23 | key: "tag:Owner" 24 | value: (.*harry\.potter) 25 | op: regex 26 | actions: 27 | - type: tag 28 | key: "Team" 29 | value: "WizardsTeam" 30 | -------------------------------------------------------------------------------- /policies/autotag-owner.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: autotag-copy 3 | resource: ec2 4 | comment: | 5 | Copy autotag to test-owner if absent 6 | filters: 7 | - "tag:AutoTag_Creator": not-null 8 | - or: 9 | - "tag:Owner": empty 10 | - "tag:Owner": absent 11 | actions: 12 | - type: copy-tag 13 | current_key: AutoTag_Creator 14 | new_key: Owner 15 | 16 | - name: strip-tag 17 | resource: ec2 18 | comment: | 19 | Strip Copy autotag to owner if absent 20 | filters: 21 | - "tag:Owner": not-null 22 | actions: 23 | - type: normalize-tag 24 | key: Owner 25 | action: remove 26 | value: "arn:aws:iam::123456789012:" 27 | -------------------------------------------------------------------------------- /policies/c7n-org/CustomAccount/README.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | These policies send Slack and email notifications when an IAM user's console management gets enabled or access keys re-activated. 3 | Please remember to update c7n_mailer so the associated msg templates get updated. 4 | -------------------------------------------------------------------------------- /policies/c7n-org/CustomAccount/iam-user-CreateLoginProfile.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-user-CreateLoginProfile-audit 4 | resource: iam-user 5 | description: | 6 | Cloud Custodian IAM User Management Console Event Audit 7 | comment: | 8 | Monitor re-activation of IAM user management console 9 | email/Slack notification if contains account:* action 10 | mode: 11 | type: cloudtrail 12 | events: 13 | - source: iam.amazonaws.com 14 | event: CreateLoginProfile 15 | ids: 'requestParameters.userName' 16 | filters: 17 | - or: 18 | - type: value 19 | key: UserName 20 | value: 'iam-username-1' 21 | - type: value 22 | key: UserName 23 | value: 'iam-username-2' 24 | 25 | actions: 26 | - type: notify 27 | template: iam-user-CreateLoginProfile-audit.html 28 | slack_template: slack-iam-user-CreateLoginProfile-audit 29 | template_format: 'html' 30 | priority_header: '5' 31 | subject: 'Security Audit: IAM User Console Access Found Reenabled in Account' 32 | to: 33 | - name@company.com 34 | - slack://#slack-channel-goes-here 35 | owner_absent_contact: 36 | - name@company.com 37 | transport: 38 | type: sqs 39 | queue: https://sqs.us-east-1.amazonaws.com/XXXXXXXXXXXX/cloud-cloudcustodian 40 | -------------------------------------------------------------------------------- /policies/c7n-org/CustomAccount/iam-user-UpdateAccessKey-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-user-UpdateAccessKey-audit 4 | resource: iam-user 5 | description: | 6 | Cloud Custodian IAM User UpdateAccessKey Event Audit 7 | comment: | 8 | Monitor re-activation of IAM user access keys 9 | email/Slack notification if contains account:* action 10 | mode: 11 | type: cloudtrail 12 | events: 13 | - source: iam.amazonaws.com 14 | event: UpdateAccessKey 15 | ids: 'requestParameters.userName' 16 | filters: 17 | - type: event 18 | key: 'detail.requestParameters.status' 19 | value: 'Active' 20 | - or: 21 | - type: value 22 | key: UserName 23 | value: 'neo' 24 | - type: value 25 | key: UserName 26 | value: 'trinity' 27 | actions: 28 | - type: notify 29 | template: iam-user-UpdateAccessKey-audit.html 30 | slack_template: slack-iam-user-UpdateAccessKey-audit 31 | template_format: 'html' 32 | priority_header: '5' 33 | subject: 'Security Audit: IAM User Access Key Found Re-activated in Production Account' 34 | to: 35 | - username@company.com 36 | - slack://#my-slack-channel-name 37 | owner_absent_contact: 38 | - username@company.com 39 | transport: 40 | type: sqs 41 | queue: https://sqs.us-east-1.amazonaws.com/XXXXXXXXXXXX/cloud-cloudcustodian 42 | -------------------------------------------------------------------------------- /policies/c7n-org/acm-certificate-cross-account-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: acm-certificate-cross-account-audit 3 | resource: acm-certificate 4 | description: | 5 | Retrieve list of ACM certificates and 6 | send notifications if expiration reaches 7 | given threshold 8 | filters: 9 | - or: 10 | - "tag:Audit": absent 11 | - "tag:Audit": empty 12 | - type: value 13 | key: Name 14 | op: regex 15 | value: ".*" 16 | - type: value 17 | key: NotAfter 18 | op: less-than 19 | value_type: expiration 20 | value: 60 21 | mode: 22 | type: periodic 23 | schedule: "rate(12 days)" 24 | actions: 25 | # - type: post-finding 26 | # severity_normalized: 10 27 | # types: 28 | # - "Software and Configuration Checks/AWS Security Best Practices" 29 | - type: notify 30 | template: acm-certificate-audit.html 31 | slack_template: slack-acm-certificate-audit 32 | template_format: 'html' 33 | priority_header: '5' 34 | subject: 'ACM Certificate Audit' 35 | to: 36 | - cloudcustodianadmins@company.com 37 | - slack:// 38 | owner_absent_contact: 39 | - cloudcustodianadmins@company.com 40 | transport: 41 | type: sqs 42 | queue: https://sqs.us-east-1.amazonaws.com/123456789012/cloud-cloudcustodian 43 | -------------------------------------------------------------------------------- /policies/c7n-org/all-accounts.yml: -------------------------------------------------------------------------------- 1 | accounts: 2 | - account_id: '1234567890' 3 | email: email@address.com 4 | name: Sandbox 5 | role: arn:aws:iam::1234567890:role/OrganizationAccountAccessRole 6 | tags: 7 | - team:sandbox 8 | -------------------------------------------------------------------------------- /policies/c7n-org/app-elb.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: app-elb-filter-policy 3 | resource: app-elb 4 | description: | 5 | Retrieve list of Network and Application Load Balancers 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/cfn-garbage-collection-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: cfn-garbage-collection-audit 3 | resource: aws.cfn 4 | description: | 5 | Cloud Custodian CloudFormation Stack Garbage Collection 6 | comments: | 7 | Retrieve Delete old CloudFormation stacks matching given string 8 | mode: 9 | type: periodic 10 | schedule: "rate(1 day)" 11 | role: arn:aws:iam::111111111111:role/cloud_custodian_role_in_cross_account 12 | filters: 13 | - type: value 14 | key: StackName 15 | op: regex 16 | value: ".*your_string_goes_here.*" 17 | - type: value 18 | key: CreationTime 19 | op: greater-than 20 | value_type: age 21 | value: 3 22 | actions: 23 | - type: delete 24 | force: true 25 | - type: post-finding 26 | severity_normalized: 10 27 | types: 28 | - "Software and Configuration Checks/AWS Security Best Practices" 29 | - type: notify 30 | template: cfn-garbage-collection-audit.html 31 | slack_template: slack-cfn-garbage-collection-audit 32 | template_format: 'html' 33 | priority_header: '5' 34 | subject: 'CloudFormation Garbage Collection Audit' 35 | to: 36 | - custodianadmins@email.com 37 | - slack://#channel_name 38 | owner_absent_contact: 39 | - custodianadmins@email.com 40 | transport: 41 | type: sqs 42 | queue: https://sqs.us-east-1.amazonaws.com/111111111111/cloud-cloudcustodian 43 | -------------------------------------------------------------------------------- /policies/c7n-org/cheatsheet.txt: -------------------------------------------------------------------------------- 1 | =========================== 2 | Path to orgaccounts.py file 3 | =========================== 4 | /home/ubuntu/cloud-custodian/tools/c7n_org/scripts/orgaccounts.py 5 | How: sudo find / -name orgaccounts.py 6 | 7 | python orgaccounts.py -f accounts.yml 8 | 9 | ====================================== 10 | Security Audit for Public IP Addresses 11 | ====================================== 12 | custodian run -s output test-elastic-ip-all.yml --region all 13 | custodian report -s output test-elastic-ip-all.yml --region all --format grid > elastic-ip-all.log 14 | 15 | custodian run -s output test-ec2-publicipaddress-all.yml --region all 16 | custodian report -s output test-ec2-publicipaddress-all.yml --region all --format grid --field PublicIp=PublicIp > ec2-public-ip.log 17 | 18 | Tip: Copy to clipboard and reduce font size 19 | 20 | 21 | 22 | ======================================= 23 | Launch c7n-org based on tags and region 24 | ======================================= 25 | c7n-org run -s output -c all-accounts.yml -u iam-group.yml -t team:tarsadmin --region us-east-1 26 | c7n-org run -s output -c all-accounts.yml -u iam-role.yml -t team:tarsadmin --region us-east-1 27 | c7n-org run -s output -c all-accounts.yml -u rest-api.yml -t team:tarsadmin --region all 28 | c7n-org run -s output -c all-accounts.yml -u app-elb.yml -t team:tarsadmin --region all 29 | c7n-org run -s output -c all-accounts.yml -u elb.yml -t team:tarsadmin --region all 30 | c7n-org run -s output -c all-accounts.yml -u iot.yml -t team:tarsadmin --region all 31 | c7n-org run -s output -c all-accounts.yml -u secrets-manager.yml -t team:tarsadmin --region all 32 | c7n-org run -s output -c all-accounts.yml -u efs.yml -t team:tarsadmin --region all 33 | c7n-org run -s output -c all-accounts.yml -u ecs.yml -t team:tarsadmin --region all 34 | c7n-org run -s output -c all-accounts.yml -u ebs.yml -t team:tarsadmin --region all 35 | c7n-org run -s output -c all-accounts.yml -u sns.yml -t team:tarsadmin --region all 36 | c7n-org run -s output -c all-accounts.yml -u ecr.yml -t team:tarsadmin --region all 37 | c7n-org run -s output -c all-accounts.yml -u dynamodb-table.yml -t team:tarsadmin --region all 38 | c7n-org run -s output -c all-accounts.yml -u lambda.yml -t team:tarsadmin --region all 39 | c7n-org run -s output -c all-accounts.yml -u iam.yml -t team:tarsadmin 40 | c7n-org run -s output -c accounts.yml -u public-instance-audit.yml -t team:sandbox --region us-west-2 41 | c7n-org run -s output -c accounts.yml -u s3-prevent-bucket-creation.yml -t team:sandbox 42 | 43 | 44 | =================== 45 | c7n Report Examples 46 | =================== 47 | 48 | custodian report -s output test.yml --field NetworkInterfaces.VpcId=VpcId --field SubnetId=SubnetId --field KeyName=KeyName --field tag:AutoTag_Creator=tag:AutoTag_Creator 49 | 50 | ======================= 51 | c7n-org Report Examples 52 | ======================= 53 | c7n-org report -c all-accounts.yml -u iam-group.yml -s output --field GroupName=GroupName --field GroupId=GroupId --field Arn=Arn --field CreateDate=CreateDate --region us-east-1 54 | c7n-org report -c all-accounts.yml -u iam-role.yml -s output --field RoleName=RoleName --field Description=Description --field Arn=Arn --field CreateDate=CreateDate --region us-east-1 55 | c7n-org report -c all-accounts.yml -u rest-api.yml -s output --field name=name --field id=id --field description=description --field endpointConfiguration[0].types=endpointConfiguration[0].types --field createdDate=createdDate --no-default-fields --region all 56 | c7n-org report -c all-accounts.yml -u app-elb.yml -s output --field LoadBalancerName=LoadBalancerName --field State.Code=State.Code --field DNSName=DNSName --field Type=Type --field Scheme=Scheme --field LoadBalancerName=LoadBalancerName --field CreatedTime=CreatedTime --no-default-fields 57 | c7n-org report -c all-accounts.yml -u iot.yml -s output --field thingName=thingName --field thingTypeName=thingTypeName --field thingArn=thingArn --no-default-fields --region all 58 | c7n-org report -c all-accounts.yml -u secrets-manager.yml -s output --field Name=Name --field Tags.Key=Tags[0].Key --field Tags.Value=Tags[0].Value --field LastChangedDate=LastChangedDate --no-default-fields --region all 59 | c7n-org report -c all-accounts.yml -u efs.yml -s output --field FileSystemId=FileSystemId --field NumberOfMountTargets=NumberOfMountTargets --field PerformanceMode=PerformanceMode --field SizeInBytes=SizeInBytes.Value --field Tag:Key=Tags[0].Key --field Tag:Value=Tags[0].Value --field CreationTime=CreationTime --no-default-fields --region all 60 | c7n-org report -c all-accounts.yml -u ecs.yml -s output --field serviceName=serviceName --field status=status --field launchType=launchType --field createdAt=createdAt --field deployments.taskDefinition=deployments[0].taskDefinition --field deployments.updatedAt=deployments[0].updatedAt --no-default-fields --region all 61 | c7n-org report -c all-accounts.yml -u ebs.yml -s output -field VolumeId=VolumeId --field State=State --field Size=Size --field Attachments.InstanceId=Attachments[0].InstanceId --field Attachments.State=Attachments[0].State --field Attachments.DeleteOnTermination=Attachments[0].DeleteOnTermination --field Attachments.Device=Attachments[0].Device --field VolumeType=VolumeType --field CreateTime=CreateTime --no-default-fields --region all 62 | c7n-org report -c all-accounts.yml -u sns.yml -s output --no-default-fields --region all 63 | c7n-org report -c all-accounts.yml -u ecr.yml -s output --no-default-fields --field repositoryName=repositoryName --field createdAt=createdAt --region all 64 | c7n-org report -c all-accounts.yml -u dynamodb-table.yml -s output --no-default-fields --field TableName=TableName --field region=region --field ItemCount=ItemCount --field TableSizeBytes=TableSizeBytes --field TableStatus=TableStatus --field LatestStreamArn=LatestStreamArn --region all 65 | c7n-org report -c all-accounts.yml -u lambda.yml -s output --no-default-fields --field FunctionName=FunctionName --field region=region --field LastModified=LastModified --region all 66 | 67 | 68 | ======================== 69 | Launch c7n-mailer Lambda 70 | ======================== 71 | c7n-mailer --config /home/ubuntu/cloudcustodian/mailer/mailer.yml --update-lambda && custodian run -c test.yml -s . 72 | 73 | 74 | ============================================ 75 | Finding Path to c7n-mailer Default Templates 76 | ============================================ 77 | find ~/ -type f -name "default.html.j2" (for email) 78 | find ~/ -type f -name "slack_default.j2" (for Slack) 79 | 80 | /home/ubuntu/cloud-custodian/tools/c7n_mailer/msg-templates/ 81 | 82 | =============================== 83 | Example Custodian Custom Report 84 | =============================== 85 | custodian report -s output owner-tag-audit.yml --field State=State --field Name=tag:Name --field InstanceId=InstanceId --field Team=tag:Team --field Owner=tag:Owner --no-default-fields 86 | 87 | Note: Sometimes a field will have a value preceded with 'tag:' and other times without. Trial and error. :) 88 | 89 | 90 | Another example using JMESpath query (i.e. JSON filtering) 91 | custodian report -s output vpn.yml --no-default --field Name=tag:Name --field VpnId=VpnConnectionId --format grid --field CustomerGwId=CustomerGatewayId --field OutsideIp="VgwTelemetry[0].OutsideIpAddress" --field Status="VgwTelemetry[0].Status" --field LastStatusChange="VgwTelemetry[0].LastStatusChange" 92 | 93 | 94 | ========================== 95 | Get Jenkins Version Number 96 | ========================== 97 | java -jar jenkins-cli.jar -s http://localhost:8080/ version 98 | 99 | 100 | =================== 101 | Useful Git Commands 102 | =================== 103 | git clone -b mailer-test https://github.com/LykinsN/cloud-custodian.git 104 | git pull (from directory branch was cloned) 105 | git branch -a (to view branch info) 106 | 107 | ============================ 108 | c7n-mailer Developer Install 109 | ============================ 110 | $ git clone https://github.com/capitalone/cloud-custodian 111 | $ cd cloud-custodian 112 | $ virtualenv c7n_mailer 113 | $ source c7n_mailer/bin/activate 114 | $ cd tools/c7n_mailer 115 | $ pip install -r requirements.txt 116 | $ python setup.py develop 117 | 118 | ============================== 119 | Deleting Cloud Custodian Cache 120 | ============================== 121 | rm ~/.cache/cloud-custodian.cache 122 | 123 | 124 | ==================================================== 125 | AWS CLI to Create Dummy Security Groups (IE Sandbox) 126 | ==================================================== 127 | Create security groups in David's VPC IE Sandbox 128 | export AWS_PROFILE=iesandbox 129 | aws ec2 create-security-group --group-name launch-wizard-10 --description "david.lin.ctr security group" --vpc-id vpc-2ea22555 130 | aws ec2 create-security-group --group-name launch-wizard-11 --description "david.lin.ctr security group" --vpc-id vpc-2ea22555 131 | aws ec2 create-security-group --group-name launch-wizard-12 --description "david.lin.ctr security group" --vpc-id vpc-2ea22555 132 | aws ec2 create-security-group --group-name launch-wizard-13 --description "david.lin.ctr security group" --vpc-id vpc-2ea22555 133 | aws ec2 create-security-group --group-name launch-wizard-14 --description "david.lin.ctr security group" --vpc-id vpc-2ea22555 134 | aws ec2 create-security-group --group-name launch-wizard-15 --description "david.lin.ctr security group" --vpc-id vpc-2ea22555 135 | 136 | ================================================ 137 | AWS CLI to Create Dummy Security Groups (TRI-NA) 138 | ================================================ 139 | Create security groups in TRI-NA 140 | export AWS_PROFILE=default 141 | aws ec2 create-security-group --group-name launch-wizard-abc --description "david.lin.ctr security group" --vpc-id vpc-b7407ed3 142 | aws ec2 create-security-group --group-name launch-wizard-def --description "david.lin.ctr security group" --vpc-id vpc-b7407ed3 143 | aws ec2 create-security-group --group-name launch-wizard-fhi --description "david.lin.ctr security group" --vpc-id vpc-b7407ed3 144 | aws ec2 create-security-group --group-name launch-wizard-jkl --description "david.lin.ctr security group" --vpc-id vpc-b7407ed3 145 | aws ec2 create-security-group --group-name launch-wizard-mno --description "david.lin.ctr security group" --vpc-id vpc-b7407ed3 146 | aws ec2 create-security-group --group-name launch-wizard-pqr --description "david.lin.ctr security group" --vpc-id vpc-b7407ed3 147 | 148 | ============= 149 | Custom Report 150 | ============= 151 | custodian report --format grid -s output public-instance-whitelist.yml --field KeyName=KeyName --field PublicIpAddress=PublicIpAddress --no-default-fields --field InstanceId=InstanceId --field VpcId=VpcId --field tag:SubnetId=SubnetId 152 | -------------------------------------------------------------------------------- /policies/c7n-org/copy-instance-tags.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: copy-instance-tags 3 | resource: ebs 4 | description: | 5 | Cloud Custodian Copy Instance Tag to Volume 6 | comment: | 7 | Copy instance tags to respective instance's ebs volume. 8 | mode: 9 | type: periodic 10 | role: arn:aws:iam::1234567890:role/CloudCustodian 11 | schedule: "rate(15 minutes)" 12 | filters: 13 | - type: value 14 | key: "Attachments[0].Device" 15 | value: not-null 16 | actions: 17 | - type: copy-instance-tags 18 | tags: 19 | - Name 20 | - type: copy-instance-tags 21 | tags: 22 | - Owner 23 | - type: copy-instance-tags 24 | tags: 25 | - Team 26 | - type: copy-instance-tags 27 | tags: 28 | - Backup 29 | 30 | -------------------------------------------------------------------------------- /policies/c7n-org/dynamodb-table.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: dynamodb-table-filter-policy 3 | resource: dynamodb-table 4 | description: | 5 | Retrieve list of DynamoDB tables that match regex. 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/ebs.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ebs-filter-policy 3 | resource: ebs 4 | description: | 5 | Retrieve list of EBS that match regex. 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/ecr.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ecr-filter-policy 3 | resource: ecr 4 | description: | 5 | Retrieve list of ECR functions that match regex. 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/ecs.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ecs-filter-policy 3 | resource: ecs-service 4 | description: | 5 | Retrieve list of ECS clusters 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | -------------------------------------------------------------------------------- /policies/c7n-org/efs.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: efs-filter-policy 3 | resource: efs 4 | description: | 5 | Retrieve list of EFS that match regex. 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/elasticip-address-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: elastic-ip 3 | resource: elastic-ip 4 | description: | 5 | Cloud Custodian Elastic IP Audit 6 | comments: | 7 | Retrieve info 8 | filters: 9 | - type: value 10 | key: PublicIp 11 | value: "x.x.x.x" 12 | -------------------------------------------------------------------------------- /policies/c7n-org/elb.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: elb-filter-policy 3 | resource: elb 4 | description: | 5 | Retrieve list of Classic ELBs 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/es.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: es 3 | resource: elasticsearch 4 | description: | 5 | Cloud Custodian Elasticsearch 6 | comments: | 7 | Retrieve Elasticsearch Attributes 8 | filters: 9 | - or: 10 | - "tag:Name": empty 11 | - not: 12 | - "tag:Name": empty 13 | -------------------------------------------------------------------------------- /policies/c7n-org/iam-group.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-group-filter-policy 3 | resource: iam-group 4 | description: | 5 | Retrieve list of IAM groups 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/iam-mfa-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-mfa-audit 3 | description: | 4 | Cloud Custodian IAM User MFA Audit 5 | comments: | 6 | Retrieve list of all IAM users in the group 'Administrators' 7 | who have not enabled MFA and send notifications. 8 | resource: iam-user 9 | mode: 10 | type: periodic 11 | schedule: "rate(1 day)" 12 | filters: 13 | - not: 14 | - type: credential 15 | key: mfa_active 16 | value: true 17 | - type: group 18 | key: GroupName 19 | value: Administrators 20 | actions: 21 | - type: notify 22 | template: mfa-audit.html 23 | template_format: 'html' 24 | slack_template: slack-mfa-audit 25 | priority_header: '5' 26 | subject: 'Cloud Custodian: IAM User Admins Audit' 27 | to: 28 | - custodianadmins@email.com 29 | - slack://#test-alerts 30 | transport: 31 | type: sqs 32 | queue: https://sqs.us-east-1.amazonaws.com/111111111111/cloud-cloudcustodian 33 | -------------------------------------------------------------------------------- /policies/c7n-org/iam-role.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-role-filter-policy 3 | resource: iam-role 4 | description: | 5 | Retrieve list of IAM roles 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/iam.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-user-filter-policy 3 | resource: iam-user 4 | description: | 5 | Retrieve list of IAM users that match regex. 6 | filters: 7 | - type: value 8 | key: UserName 9 | op: regex 10 | value: ".*" 11 | -------------------------------------------------------------------------------- /policies/c7n-org/iot.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iot-filter-policy 3 | resource: iot 4 | description: | 5 | Retrieve list of Secrets 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/lambda-get-function-list.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: lambda-filter-policy 3 | resource: lambda 4 | description: | 5 | Retrieve list of Lambda functions that match regex. 6 | filters: 7 | - type: value 8 | key: FunctionName 9 | op: regex 10 | value: .*acm.* 11 | -------------------------------------------------------------------------------- /policies/c7n-org/lambda.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: lambda-filter-policy 3 | resource: lambda 4 | description: | 5 | Retrieve list of Lambda functions that match regex. 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/public-instance-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: public-instance-audit 3 | resource: ec2 4 | description: | 5 | Cloud Custodian Public Instance Audit 6 | comments: | 7 | Retrieve list of all instances that 8 | - are not in whitelist 9 | - attached to a public subnet 10 | - have public IP address 11 | mode: 12 | type: ec2-instance-state 13 | events: 14 | - pending 15 | filters: 16 | - not: 17 | - type: value 18 | key: "tag:Name" 19 | value: (VPN|Bastion|OpenVPN-Test) 20 | op: regex 21 | - or: 22 | - type: subnet 23 | key: "tag:Name" 24 | op: regex 25 | value: ".*pub" 26 | - type: value 27 | key: "PublicIpAddress" 28 | value: not-null 29 | actions: 30 | - type: notify 31 | template: public-instance-audit.html 32 | slack_template: slack-public-instance-audit 33 | template_format: 'html' 34 | priority_header: '5' 35 | subject: 'Security Audit: Public EC2 Instance Launched' 36 | to: 37 | - email@address.com 38 | - slack://# 39 | owner_absent_contact: 40 | - email@address.com 41 | transport: 42 | type: sqs 43 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 44 | -------------------------------------------------------------------------------- /policies/c7n-org/rest-api.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: rest-api-filter-policy 3 | resource: rest-api 4 | description: | 5 | Retrieve list of REST APIs 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/s3-global-grants-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: s3-retrieve-global-grants 3 | resource: s3 4 | filters: 5 | - type: global-grants 6 | 7 | -------------------------------------------------------------------------------- /policies/c7n-org/s3-prevent-bucket-creation.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | 4 | - name: s3-prevent-bucket-creation 5 | resource: s3 6 | description: | 7 | Cloud Custodian S3 Bucket Creation Prevention 8 | comments: | 9 | Prevents creation of S3 buckets in us-east-1 10 | and sends email notification to user 11 | mode: 12 | type: cloudtrail 13 | events: 14 | - CreateBucket 15 | timeout: 200 16 | filters: 17 | - and: 18 | - not: 19 | - type: value 20 | key: "Name" 21 | value: "david-lin-sandbox-1|david-lin--sandbox-2" 22 | op: regex 23 | - type: event 24 | key: "region" 25 | op: in 26 | value: 27 | - us-east-1 28 | actions: 29 | - type: delete 30 | remove-contents: true 31 | - type: notify 32 | template: s3-prevent-bucket-creation.html 33 | template_format: 'html' 34 | slack_template: slack-s3-prevent-bucket-creation 35 | priority_header: '5' 36 | subject: "S3 Audit: S3 Bucket Deleted" 37 | to: 38 | - email@address.com 39 | - slack://# 40 | - event-owner 41 | owner_absent_contact: 42 | - email@address.com 43 | transport: 44 | type: sqs 45 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 46 | -------------------------------------------------------------------------------- /policies/c7n-org/s3-public-audit-scheduled-job.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: s3-public-audit 3 | description: | 4 | Cloud Custodian Public S3 Audit 5 | comments: | 6 | Send notification when public S3 bucket is found 7 | resource: s3 8 | mode: 9 | type: periodic 10 | schedule: "rate(6 hours)" 11 | timeout: 300 12 | filters: 13 | - not: 14 | - type: value 15 | key: Name 16 | value: white-listed-public-bucket 17 | - or: 18 | - type: has-statement 19 | statements: 20 | - Effect: Allow 21 | Action: 's3:*' 22 | Principal: '*' 23 | - type: has-statement 24 | statements: 25 | - Effect: Allow 26 | Action: 's3:GetObject' 27 | Principal: '*' 28 | actions: 29 | - type: notify 30 | template: s3-public-audit.html 31 | template_format: 'html' 32 | slack_template: slack-s3-public-audit 33 | priority_header: '5' 34 | subject: 'Security Audit: Public S3 Bucket Found' 35 | to: 36 | - email@domain.com 37 | - slack://#my-slack-channel-name 38 | owner_absent_contact: 39 | - email@domain.com 40 | transport: 41 | type: sqs 42 | queue: https://sqs.us-east-1.amazonaws.com/XXXXXXXXXXXX/cloud-cloudcustodian 43 | -------------------------------------------------------------------------------- /policies/c7n-org/s3-public-audit-test.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: s3-public-audit 3 | description: | 4 | Cloud Custodian Public S3 Audit 5 | comments: | 6 | Retrieve list of public S3 buckets 7 | resource: s3 8 | filters: 9 | - type: global-grants 10 | -------------------------------------------------------------------------------- /policies/c7n-org/s3-public-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: s3-public-audit 3 | description: | 4 | Cloud Custodian Public S3 Audit 5 | comments: | 6 | Send notification when public S3 bucket gets created 7 | resource: s3 8 | mode: 9 | type: cloudtrail 10 | events: 11 | - CreateBucket 12 | filters: 13 | - type: global-grants 14 | actions: 15 | - type: notify 16 | template: s3-public-audit.html 17 | template_format: 'html' 18 | slack_template: slack-s3-public-audit 19 | priority_header: '5' 20 | subject: 'Security Audit: Public S3 Bucket Created' 21 | to: 22 | - email@address.com 23 | - slack://# 24 | owner_absent_contact: 25 | - email@address.com 26 | transport: 27 | type: sqs 28 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 29 | -------------------------------------------------------------------------------- /policies/c7n-org/secrets-manager.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: secrets-manager-filter-policy 3 | resource: secrets-manager 4 | description: | 5 | Retrieve list of Secrets 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/sns.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: sns-filter-policy 3 | resource: sns 4 | description: | 5 | Retrieve list of SNS that match regex. 6 | filters: 7 | - or: 8 | - "tag:Audit": absent 9 | - "tag:Audit": empty 10 | - type: value 11 | key: Name 12 | op: regex 13 | value: ".*" 14 | -------------------------------------------------------------------------------- /policies/c7n-org/termination-protection-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: termination-protection-audit 3 | resource: ec2 4 | description: | 5 | Cloud Custodian EC2 Termination Protection Audit 6 | comment: | 7 | Periodically check for white listed EC2 instances that 8 | do not have termination protection enabled. 9 | Send email/Slack notification. 10 | mode: 11 | type: periodic 12 | schedule: "rate(5 minutes)" 13 | query: 14 | - instance-state-name: running 15 | filters: 16 | - not: 17 | - type: termination-protected 18 | - or: 19 | - "tag:Name": Cloud Custodian Production 20 | - "tag:Name": GHE 21 | - "tag:Name": david.lin.Bastion 22 | actions: 23 | - type: notify 24 | template: termination-protection-audit.html 25 | slack_template: slack-termination-protection-audit 26 | template_format: 'html' 27 | priority_header: '5' 28 | subject: 'Security Audit: White Listed Instance(s) found with Termination Protection Disabled' 29 | to: 30 | - email@address.com 31 | - slack://# 32 | owner_absent_contact: 33 | - email@address.com 34 | transport: 35 | type: sqs 36 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 37 | -------------------------------------------------------------------------------- /policies/copy-instance-tags.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: copy-instance-tags 3 | resource: ebs 4 | description: | 5 | Cloud Custodian Copy Instance Tag to Volume 6 | comment: | 7 | Copy instance tags to respective instance's ebs volume. 8 | mode: 9 | type: periodic 10 | role: arn:aws:iam::1234567890:role/CloudCustodian 11 | schedule: "rate(15 minutes)" 12 | filters: 13 | - type: value 14 | key: "Attachments[0].Device" 15 | value: not-null 16 | actions: 17 | - type: copy-instance-tags 18 | tags: 19 | - Name 20 | - type: copy-instance-tags 21 | tags: 22 | - Owner 23 | - type: copy-instance-tags 24 | tags: 25 | - Team 26 | -------------------------------------------------------------------------------- /policies/delete-marked-sgroups.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: unmark-attached-security-groups 3 | resource: security-group 4 | description: | 5 | Unmark attached security groups that were previously tagged for deletion. 6 | filters: 7 | - used 8 | - type: value 9 | key: GroupName 10 | value: not-null 11 | - "tag:maid_status": not-null 12 | actions: 13 | - unmark 14 | 15 | - name: delete-marked-security-groups 16 | resource: security-group 17 | description: | 18 | Delete security groups marked for deletion 19 | filters: 20 | - type: marked-for-op 21 | op: delete 22 | actions: 23 | - delete 24 | - type: notify 25 | template: sgroup-delete-marked.html 26 | template_format: 'html' 27 | priority_header: '5' 28 | subject: 'CloudCustodian: Unused Security Groups' 29 | to: 30 | - email@address.com 31 | owner_absent_contact: 32 | - email@address.com 33 | transport: 34 | type: sqs 35 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/sandbox 36 | -------------------------------------------------------------------------------- /policies/ebs-autocleanup-tag.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ebs-autocleanup-tag 3 | resource: ebs 4 | description: | 5 | Cloud Custodian EBS AutoCleanup Tag 6 | comments: | 7 | Tags ebs volume with name "AutoCleanup" and sets value to "true". 8 | This policy is used with the ebs-garbage-collection policy 9 | which periodically checks ebs volumes with the "AutoClenaup" 10 | tag set to "true" to mark ebs volumes for deletion after 24 hours 11 | of being in the state "available". 12 | mode: 13 | type: periodic 14 | role: arn:aws:iam::929292782238:role/CloudCustodian 15 | schedule: "rate(5 minutes)" 16 | filters: 17 | - or: 18 | - not: 19 | - or: 20 | - "tag:AutoCleanup": "false" 21 | - "tag:AutoCleanup": "False" 22 | - "tag:AutoCleanup": "FALSE" 23 | - "tag:AutoCleanup": absent 24 | actions: 25 | - type: tag 26 | key: "AutoCleanup" 27 | value: "true" 28 | -------------------------------------------------------------------------------- /policies/ebs-garbage-collection-lambda.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ebs-mark-unattached-deletion 3 | resource: ebs 4 | comments: | 5 | Delete any unattached EBS volumes. 6 | Volumes set to not delete on instance termination do have 7 | valid use cases as data drives, but 99% of the time they 8 | appear to be just garbage creation. 9 | To run across all regions -> custodian run --dryrun -s out --region all ebs-garbage-collection.yml 10 | Use this policy at your discretion. 11 | mode: 12 | type: periodic 13 | role: arn:aws:iam::{account_id}:role/CloudCustodianRole 14 | schedule: "rate(1 day)" 15 | filters: 16 | - Attachments: [] 17 | - "tag:maid_status": absent 18 | actions: 19 | - delete 20 | -------------------------------------------------------------------------------- /policies/ebs-garbage-collection-with-tags.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ebs-garbage-collection-with-tags 3 | resource: ebs 4 | description: | 5 | Cloud Custodian EBS Garbage Collection 6 | comments: | 7 | Delete unattached EBS volumes older than 1 day (24hrs) that 8 | have the tag AutoCleanup set to true. 9 | Volumes set to not delete on instance termination do have 10 | valid use cases as data drives, but 99% of the time they 11 | appear to be just garbage creation. 12 | Use this policy at your discretion. 13 | mode: 14 | type: periodic 15 | role: arn:aws:iam::1234567890:role/CloudCustodian 16 | schedule: "rate(1 hour)" 17 | filters: 18 | - Attachments: [] 19 | - type: value 20 | key: CreateTime 21 | op: greater-than 22 | value_type: age 23 | value: 1 24 | - "tag:AutoCleanup": "true" 25 | actions: 26 | - delete 27 | - type: notify 28 | template: ebs-garbage-collection.html 29 | slack_template: slack-ebs-garbage-collection 30 | template_format: 'html' 31 | priority_header: '5' 32 | subject: 'EBS Garbage Collection' 33 | to: 34 | - email@address.com 35 | - slack://#slackchannel 36 | owner_absent_contact: 37 | - email@address.com 38 | transport: 39 | type: sqs 40 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 41 | -------------------------------------------------------------------------------- /policies/ec2-garbage-collection-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ec2-garbage-collection-audit 3 | resource: ec2 4 | description: | 5 | Cloud Custodian EC2 Garbage Collection 6 | comments: | 7 | Terminate EC2 instances that have been running longer than specified age 8 | filters: 9 | - type: value 10 | key: tag:Name 11 | op: regex 12 | value: ^InstanceNameGoesHere$ 13 | - type: instance-age 14 | op: gt 15 | hours: 1 16 | mode: 17 | type: periodic 18 | role: arn:aws:iam::XXXXXXXXXXXX:role/CloudCustodian 19 | schedule: "rate(30 minutes)" 20 | packages: [boto3, botocore, urllib3] 21 | actions: 22 | - terminate 23 | - type: post-finding 24 | severity_normalized: 10 25 | types: 26 | - "Software and Configuration Checks/AWS Security Best Practices" 27 | - type: notify 28 | template: ec2-garbage-collection-audit.html 29 | slack_template: slack-ec2-garbage-collection-audit 30 | template_format: 'html' 31 | priority_header: '5' 32 | subject: 'EC2 Packer Builder Reaper Audit' 33 | to: 34 | - cloudcustodianadmins@company.com 35 | - slack://# 36 | owner_absent_contact: 37 | - cloudcustodianadmins@company.com 38 | transport: 39 | type: sqs 40 | queue: https://sqs.us-east-1.amazonaws.com/XXXXXXXXXXXX/cloud-cloudcustodian 41 | -------------------------------------------------------------------------------- /policies/ec2-health-event.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ec2-health-event 3 | resource: ec2 4 | description: | 5 | Cloud Custodian EC2 Health Event 6 | comments: | 7 | Retrieve EC2 instances with scheduled event 8 | filters: 9 | - type: health-event 10 | statuses: [upcoming,open,closed] 11 | mode: 12 | type: periodic 13 | role: arn:aws:iam::123456789:role/CloudCustodian 14 | schedule: "cron(0 20 * * ? *)" 15 | packages: [boto3, botocore, urllib3] 16 | actions: 17 | - type: post-finding 18 | severity_normalized: 10 19 | types: 20 | - "Software and Configuration Checks/AWS Security Best Practices" 21 | - type: notify 22 | template: ec2-health-event.html 23 | slack_template: slack-ec2-health-event 24 | template_format: 'html' 25 | priority_header: '5' 26 | subject: 'Upcoming EC2 Scheduled Events' 27 | to: 28 | - email@example.com 29 | - slack://# 30 | owner_absent_contact: 31 | - email@example.com 32 | transport: 33 | type: sqs 34 | queue: https://sqs.us-east-1.amazonaws.com/123456789/cloud-cloudcustodian 35 | -------------------------------------------------------------------------------- /policies/ec2-publicipaddress-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ec2-publicipaddress-audit 3 | resource: ec2 4 | description: | 5 | Cloud Custodian Public Ipaddress Audit 6 | comments: | 7 | Retrieve list of all instances that 8 | - have public IP address matching value 9 | filters: 10 | - type: value 11 | key: "PublicIpAddress" 12 | value: "x.x.x.x" 13 | -------------------------------------------------------------------------------- /policies/ec2.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ec2-attributes 3 | resource: ec2 4 | description: | 5 | Cloud Custodian EC2 Attributes 6 | comments: | 7 | Retrieve EC2 Attributes 8 | filters: 9 | - and: 10 | - type: instance-attribute 11 | attribute: instanceType 12 | key: "Value" 13 | value: p3.8xlarge 14 | - type: value 15 | key: tag:Name 16 | op: regex 17 | value: ".*Jenkins2-Driving.*" 18 | -------------------------------------------------------------------------------- /policies/elasticsearch-find-all-domains.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: elastic-search-find-all-domains 3 | resource: elasticsearch 4 | description: | 5 | Cloud Custodian Elasticsearch 6 | comments: | 7 | Find Elasticsearch Domains and Retrieve Attributes 8 | filters: 9 | - or: 10 | - "tag:Name": empty 11 | - not: 12 | - "tag:Name": empty 13 | -------------------------------------------------------------------------------- /policies/elasticsearch-security-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: elasticsearch_security_audit 3 | resource: elasticsearch 4 | description: | 5 | Cloud Custodian Elasticsearch Security Audit 6 | comments: | 7 | Periodically check PUBLIC ES domains that have 8 | access policies that are too permissive. 9 | Ignore PRIVATE ES domains. 10 | PRIVATE domains will have VPCOptions configured. 11 | PUBLIC domains will have a Condition with AccessApolicies configured. 12 | Send email/Slack notification. 13 | mode: 14 | type: periodic 15 | role: arn:aws:iam:::role/CloudCustodian 16 | schedule: "rate(5 minutes)" 17 | filters: 18 | - type: value 19 | key: VPCOptions 20 | value: null 21 | - or: 22 | - not: 23 | - type: value 24 | key: AccessPolicies 25 | op: regex 26 | value: .*Condition.* 27 | - type: value 28 | key: AccessPolicies 29 | op: regex 30 | value: .*0.0.0.0/0.* 31 | actions: 32 | - type: notify 33 | template: elasticsearch-security-audit.html 34 | slack_template: slack-elasticsearch-security-audit 35 | template_format: 'html' 36 | priority_header: '5' 37 | subject: 'ElasticSearch Security Audit: ES Domain found out of compliance' 38 | to: 39 | - 40 | - slack://# 41 | owner_absent_contact: 42 | - 43 | transport: 44 | type: sqs 45 | queue: https://sqs.us-east-1.amazonaws.com//cloud-cloudcustodian 46 | -------------------------------------------------------------------------------- /policies/emailer.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: mfa-unused 3 | resource: iam-user 4 | description: | 5 | Retrieve list of all IAM users in the group 'Administrators' 6 | who have not enabled MFA and generate email report. 7 | filters: 8 | - type: credential 9 | key: mfa_active 10 | value: false 11 | - type: group 12 | key: GroupName 13 | value: Administrators 14 | actions: 15 | - type: notify 16 | template: default.html 17 | template_format: 'html' 18 | priority_header: '5' 19 | subject: 'CloudCustodian: Admins with MFA Disabled' 20 | to: 21 | - david.lin.ctr@tri.global 22 | owner_absent_contact: 23 | - david.lin.ctr@tri.global 24 | transport: 25 | type: sqs 26 | queue: https://sqs.us-east-1.amazonaws.com/929292782238/david-lin-ctr-cloudcustodian 27 | -------------------------------------------------------------------------------- /policies/get-resources.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: report-all-ec2s 4 | resource: ec2 5 | -------------------------------------------------------------------------------- /policies/get_lambda_runtime_audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: lambda_runtime_audit 3 | resource: lambda 4 | description: | 5 | Cloud Custodian Lambda Runtime Audit 6 | comments: | 7 | Retrieve list of all Lambdas 8 | filters: 9 | - or: 10 | - "tag:Team": absent 11 | - "tag:Team": empty 12 | - type: value 13 | key: Runtime 14 | op: regex 15 | value: .*nodejs.* 16 | -------------------------------------------------------------------------------- /policies/health-event-issues.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: health-event-issues 3 | resource: health-event 4 | mode: 5 | type: periodic 6 | role: arn:aws:iam::123456789123:role/CloudCustodian 7 | schedule: "cron(0 5 * * ? *)" 8 | filters: 9 | - type: value 10 | key: eventTypeCategory 11 | value: issue 12 | - type: value 13 | key: statusCode 14 | value: open 15 | actions: 16 | - type: post-finding 17 | severity_normalized: 10 18 | types: 19 | - "Software and Configuration Checks/AWS Security Best Practices" 20 | - type: notify 21 | template: phd-issue.html 22 | slack_template: slack-phd-issue 23 | template_format: 'html' 24 | priority_header: '5' 25 | subject: 'Personal Health Dashboard - Operational Issue Notification' 26 | to: 27 | - cloudcustodianadmins@email.com 28 | - slack://#alerts 29 | owner_absent_contact: 30 | - cloudcustodianadmins@email.com 31 | transport: 32 | type: sqs 33 | queue: https://sqs.us-east-1.amazonaws.com/123456789123/cloud-cloudcustodian 34 | -------------------------------------------------------------------------------- /policies/iam-ec2-policy-check.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-no-used-ec2-all-policy 3 | resource: iam-policy 4 | filters: 5 | - type: has-allow-all 6 | 7 | ############################################################################################## 8 | Note: By default, `has-allow-all` matches IAM policies that have the following JSON code block 9 | ############################################################################################## 10 | { 11 | 'Version': '2012-10-17', 12 | 'Statement': [{ 13 | 'Action': '*', 14 | 'Resource': '*', 15 | 'Effect': 'Allow' 16 | }] 17 | } 18 | 19 | 20 | ############################################################################################## 21 | Since I needed to have the Action match on specific values, the following lines were manually 22 | added to the /cloud-custodian/c7n/resources/iam.py module: 23 | ############################################################################################## 24 | def has_allow_all_policy(self, client, resource): 25 | statements = client.get_policy_version( 26 | PolicyArn=resource['Arn'], 27 | VersionId=resource['DefaultVersionId'] 28 | )['PolicyVersion']['Document']['Statement'] 29 | if isinstance(statements, dict): 30 | statements = [statements] 31 | 32 | # has ec2:* 33 | for s in statements: 34 | if ('Condition' not in s and 35 | 'Action' in s and 36 | isinstance(s['Action'], six.string_types) and 37 | s['Action'] == "ec2:*" and 38 | 'Resource' in s and 39 | isinstance(s['Resource'], six.string_types) and 40 | s['Resource'] == "*" and 41 | s['Effect'] == "Allow"): 42 | return True 43 | 44 | # has elasticloadbalancing:* 45 | for s in statements: 46 | if ('Condition' not in s and 47 | 'Action' in s and 48 | isinstance(s['Action'], six.string_types) and 49 | s['Action'] == "elasticloadbalancing:*" and 50 | 'Resource' in s and 51 | isinstance(s['Resource'], six.string_types) and 52 | s['Resource'] == "*" and 53 | s['Effect'] == "Allow"): 54 | return True 55 | 56 | # has cloudwatch:* 57 | for s in statements: 58 | if ('Condition' not in s and 59 | 'Action' in s and 60 | isinstance(s['Action'], six.string_types) and 61 | s['Action'] == "cloudwatch:*" and 62 | 'Resource' in s and 63 | isinstance(s['Resource'], six.string_types) and 64 | s['Resource'] == "*" and 65 | s['Effect'] == "Allow"): 66 | return True 67 | 68 | # has autoscaling:* 69 | for s in statements: 70 | if ('Condition' not in s and 71 | 'Action' in s and 72 | isinstance(s['Action'], six.string_types) and 73 | s['Action'] == "autoscaling:*" and 74 | 'Resource' in s and 75 | isinstance(s['Resource'], six.string_types) and 76 | s['Resource'] == "*" and 77 | s['Effect'] == "Allow"): 78 | return True 79 | 80 | # has iam:CreateServiceLinkedRole 81 | for s in statements: 82 | if ('Condition' not in s and 83 | 'Action' in s and 84 | isinstance(s['Action'], six.string_types) and 85 | s['Action'] == "iam:CreateServiceLinkedRole" and 86 | 'Resource' in s and 87 | isinstance(s['Resource'], six.string_types) and 88 | s['Resource'] == "*" and 89 | s['Effect'] == "Allow"): 90 | return True 91 | 92 | # has ec2:RunInstances 93 | for s in statements: 94 | if ('Condition' not in s and 95 | 'Action' in s and 96 | isinstance(s['Action'], six.string_types) and 97 | s['Action'] == "ec2:RunInstances" and 98 | 'Resource' in s and 99 | isinstance(s['Resource'], six.string_types) and 100 | s['Resource'] == "*" and 101 | s['Effect'] == "Allow"): 102 | return True 103 | return False 104 | 105 | def process(self, resources, event=None): 106 | c = local_session(self.manager.session_factory).client('iam') 107 | results = [r for r in resources if self.has_allow_all_policy(c, r)] 108 | self.log.info( 109 | "%d of %d iam policies have allow all.", 110 | len(results), len(resources)) 111 | return results 112 | 113 | ############################################################################################## 114 | Note: For the changes to the iam.py module to take effect, remember to issue: 115 | ############################################################################################## 116 | 117 | $ cd ~/cloud-custodian 118 | $ python install setup.up install 119 | -------------------------------------------------------------------------------- /policies/iam-policy-CreatePolicy-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-policy-CreatePolicy-account-audit 4 | resource: iam-policy 5 | description: | 6 | Cloud Custodian IAM Policy account:* and account:EnableRegion Audit 7 | comment: | 8 | Send email/Slack notification if IAM policy contains account:* or account:EnableRegion action. 9 | Note, this policy will NOT work out of the box and requires the iam.py site-package be modified 10 | to match on specific actions. 11 | mode: 12 | type: cloudtrail 13 | role: arn:aws:iam::1234567890:role/CloudCustodian 14 | events: 15 | - source: iam.amazonaws.com 16 | event: CreatePolicy 17 | ids: 'responseElements.policy.arn' 18 | packages: [boto3, botocore, urllib3] 19 | filters: 20 | - type: has-allow-all 21 | actions: 22 | - type: post-finding 23 | severity_normalized: 10 24 | types: 25 | - "Software and Configuration Checks/AWS Security Best Practices" 26 | - type: notify 27 | template: iam-policy-account-audit.html 28 | slack_template: slack-iam-policy-account-audit 29 | template_format: 'html' 30 | priority_header: '5' 31 | subject: 'Security Audit: IAM policies found with account:* action' 32 | to: 33 | - foo@company.com 34 | - slack://# 35 | owner_absent_contact: 36 | - foo@company.com 37 | transport: 38 | type: sqs 39 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 40 | -------------------------------------------------------------------------------- /policies/iam-policy-CreatePolicyVersion-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-policy-CreatePolicyVersion-account-audit 4 | resource: iam-policy 5 | description: | 6 | Cloud Custodian IAM Policy account:* and account:EnableRegion Audit 7 | comment: | 8 | Send email/Slack notification if IAM policy contains account:* or account:EnableRegion action. 9 | Note, this policy will NOT work out of the box and requires the iam.py site-package be modified 10 | to match on specific actions. 11 | mode: 12 | type: cloudtrail 13 | role: arn:aws:iam::1234567890:role/CloudCustodian 14 | events: 15 | - source: iam.amazonaws.com 16 | event: CreatePolicyVersion 17 | ids: 'requestParameters.policyArn' 18 | packages: [boto3, botocore, urllib3] 19 | filters: 20 | - type: has-allow-all 21 | actions: 22 | - type: post-finding 23 | severity_normalized: 10 24 | types: 25 | - "Software and Configuration Checks/AWS Security Best Practices" 26 | - type: notify 27 | template: iam-policy-account-audit.html 28 | slack_template: slack-iam-policy-account-audit 29 | template_format: 'html' 30 | priority_header: '5' 31 | subject: 'Security Audit: IAM policies found with account:* action' 32 | to: 33 | - foo@company.com 34 | - slack://# 35 | owner_absent_contact: 36 | - foo@company.com 37 | transport: 38 | type: sqs 39 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 40 | -------------------------------------------------------------------------------- /policies/iam-policy-account-Summary-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-policy-Summary-account-audit 4 | resource: iam-policy 5 | description: | 6 | Cloud Custodian IAM Policy account:* Audit 7 | comment: | 8 | Periodically check IAM policies and send 9 | email/Slack notification if contains account:* action 10 | This policy does NOT work out of the box and requires 11 | a modification to the iam.py site-package for the has-allow-all filter 12 | if you want to match on policies with actions that are NOT "*". 13 | mode: 14 | type: periodic 15 | role: arn:aws:iam::1234567890:role/CloudCustodian 16 | schedule: "rate(1 day)" 17 | packages: [boto3, botocore, urllib3] 18 | filters: 19 | - type: has-allow-all 20 | actions: 21 | - type: post-finding 22 | severity_normalized: 10 23 | types: 24 | - "Software and Configuration Checks/AWS Security Best Practices" 25 | - type: notify 26 | template: iam-policy-account-audit-summary.html 27 | slack_template: slack-iam-policy-account-audit-summary 28 | template_format: 'html' 29 | priority_header: '5' 30 | subject: 'Security Audit: IAM policies found with account:* action' 31 | to: 32 | - foo@company.com 33 | - slack://# 34 | owner_absent_contact: 35 | - foo@company.com 36 | transport: 37 | type: sqs 38 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 39 | -------------------------------------------------------------------------------- /policies/iam-policy-account-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-policy-account-audit-policy 4 | resource: iam-policy 5 | description: | 6 | Cloud Custodian IAM Policy account:* Audit 7 | comment: | 8 | Periodically check IAM policies and send 9 | email/Slack notification if contains account:* action 10 | Note: The iam.py module was manually modified to match on 11 | the Action account:*. This policy will NOT work out of the box. 12 | mode: 13 | type: periodic 14 | role: arn:aws:iam::929292782238:role/CloudCustodian 15 | schedule: "rate(1 hour)" 16 | packages: [boto3, botocore, urllib3] 17 | filters: 18 | - type: has-allow-all 19 | actions: 20 | - type: post-finding 21 | severity_normalized: 10 22 | types: 23 | - "Software and Configuration Checks/AWS Security Best Practices" 24 | - type: notify 25 | template: iam-policy-account-audit.html 26 | slack_template: slack-iam-policy-account-audit 27 | template_format: 'html' 28 | priority_header: '5' 29 | subject: 'Security Audit: IAM policies found with account:* action' 30 | to: 31 | - cloudcustodianadmins@tri.global 32 | - slack://#ie-alerts 33 | owner_absent_contact: 34 | - cloudcustodianadmins@tri.global 35 | transport: 36 | type: sqs 37 | queue: https://sqs.us-east-1.amazonaws.com/929292782238/cloud-cloudcustodian 38 | -------------------------------------------------------------------------------- /policies/iam-role-with-managed-policy-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-role-with-managed-policy-audit 3 | resource: iam-role 4 | description: | 5 | Cloud Custodian IAM Role Audit 6 | comments: | 7 | Send notification when IAM role is found with 8 | AmazonEC2FullAccess, AutoScalingFullAccess, 9 | ElasitcLoadBalancingFullAccess, or AutoScalingConsoleFullAccess. 10 | mode: 11 | type: periodic 12 | role: arn:aws:iam:::role/CloudCustodian 13 | schedule: "rate(1 day)" 14 | filters: 15 | - or: 16 | - type: has-specific-managed-policy 17 | value: AmazonEC2FullAccess 18 | - type: has-specific-managed-policy 19 | value: AutoScalingFullAccess 20 | - type: has-specific-managed-policy 21 | value: ElasticLoadBalancingFullAccess 22 | - type: has-specific-managed-policy 23 | value: AutoScalingConsoleFullAccess 24 | actions: 25 | - type: notify 26 | template: iam-role-audit.html 27 | slack_template: slack-iam-role-audit 28 | template_format: 'html' 29 | priority_header: '5' 30 | subject: 'Security Audit: IAM Role(s) found with AmazonEC2FullAccess Permissions' 31 | to: 32 | - cloudcustodianadmins@company.com 33 | - slack://# 34 | owner_absent_contact: 35 | - cloudcustodianadmins@company.com 36 | transport: 37 | type: sqs 38 | queue: https://sqs.us-east-1.amazonaws.com//cloud-cloudcustodian 39 | -------------------------------------------------------------------------------- /policies/iam-user-DeleteAccessKey.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-user-DeleteAccessKey-audit 3 | resource: iam-user 4 | description: | 5 | Cloud Custodian IAM User DeleteAccessKey Event Audit 6 | comment: | 7 | Monitor deletion of IAM user access keys 8 | Slack notification if contains account:* action 9 | mode: 10 | type: cloudtrail 11 | role: arn:aws:iam::123456789123:role/CloudCustodian 12 | events: 13 | - source: iam.amazonaws.com 14 | event: DeleteAccessKey 15 | ids: 'requestParameters.userName' 16 | filters: 17 | - type: event 18 | key: 'detail.eventName' 19 | value: 'DeleteAccessKey' 20 | actions: 21 | - type: notify 22 | slack_template: slack-iam-user-DeleteAccessKey-audit 23 | template_format: 'html' 24 | priority_header: '5' 25 | subject: 'IAM User Access Key Deleted' 26 | to: 27 | - slack://#slack-channel-name-goes-here 28 | transport: 29 | type: sqs 30 | queue: https://sqs.us-east-1.amazonaws.com/123456789123/cloud-cloudcustodian 31 | -------------------------------------------------------------------------------- /policies/iam-user-DeleteLoginProfile-offboarding.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-user-DeleteLoginProfile-audit 4 | resource: iam-user 5 | description: | 6 | Cloud Custodian IAM User Management Console Event Audit 7 | comment: | 8 | Monitor Disablement of IAM user management console 9 | Slack notification if contains account:* action 10 | mode: 11 | type: cloudtrail 12 | role: arn:aws:iam::XXXXXXXXXXXX:role/CloudCustodian 13 | events: 14 | - source: iam.amazonaws.com 15 | event: DeleteLoginProfile 16 | ids: 'requestParameters.userName' 17 | actions: 18 | - type: notify 19 | template: iam-user-DeleteLoginProfile-offboarding-audit.html 20 | slack_template: slack-iam-user-DeleteLoginProfile-offboarding-audit 21 | template_format: 'html' 22 | priority_header: '5' 23 | subject: 'IAM User Console Access Disabled' 24 | to: 25 | - slack://#it-offboarding 26 | transport: 27 | type: sqs 28 | queue: https://sqs.us-east-1.amazonaws.com/XXXXXXXXXXXX/cloud-cloudcustodian 29 | -------------------------------------------------------------------------------- /policies/iam-user-UpdateAccessKey-offboarding.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-user-UpdateAccessKey-offboarding-audit 4 | resource: iam-user 5 | description: | 6 | Cloud Custodian IAM User UpdateAccessKey Event Audit for Offboarding 7 | comment: | 8 | Monitor de-activation of IAM user access keys 9 | Slack notification if contains account:* action 10 | mode: 11 | type: cloudtrail 12 | role: arn:aws:iam::XXXXXXXXXXXX:role/CloudCustodian 13 | events: 14 | - source: iam.amazonaws.com 15 | event: UpdateAccessKey 16 | ids: 'requestParameters.userName' 17 | filters: 18 | - type: event 19 | key: 'detail.requestParameters.status' 20 | value: 'Inactive' 21 | actions: 22 | - type: notify 23 | slack_template: slack-iam-user-UpdateAccessKey-offboarding-audit 24 | template_format: 'html' 25 | priority_header: '5' 26 | subject: 'IAM User Access Key Deactivated' 27 | to: 28 | - slack://#it-offboarding 29 | transport: 30 | type: sqs 31 | queue: https://sqs.us-east-1.amazonaws.com/XXXXXXXXXXXX/cloud-cloudcustodian 32 | -------------------------------------------------------------------------------- /policies/iam-user-administrator-access-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-user-administrator-access-audit 3 | resource: iam-user 4 | description: | 5 | Cloud Custodian IAM User Audit with AWS Security Hub Integration 6 | comments: | 7 | Send notification when IAM user is found with Administrator access 8 | mode: 9 | type: periodic 10 | role: arn:aws:iam:::role/CloudCustodian 11 | schedule: "rate(1 day)" 12 | packages: [boto3, botocore, urllib3] 13 | filters: 14 | - or: 15 | - type: group 16 | key: GroupName 17 | value: Administrators 18 | op: regex 19 | - type: group 20 | key: GroupName 21 | value: Administrators-HighlyConfidential 22 | op: regex 23 | - type: policy 24 | key: PolicyName 25 | value: AdministratorAccess 26 | op: regex 27 | - not: 28 | - or: 29 | - UserName: david.lin 30 | - UserName: rodney.mullen 31 | actions: 32 | - type: post-finding 33 | severity_normalized: 50 34 | types: 35 | - "Effects/Data Exposure" 36 | - type: notify 37 | template: iam-user-administrator-access-audit.html 38 | template_format: 'html' 39 | slack_template: slack-iam-user-administrator-access-audit 40 | priority_header: '5' 41 | subject: 'IAM User Audit: Non-whitelisted IAM User(s) found with Administrator Access' 42 | to: 43 | - 44 | - slack:// 45 | owner_absent_contact: 46 | - 47 | transport: 48 | type: sqs 49 | queue: https://sqs.us-east-1.amazonaws.com//cloud-cloudcustodian 50 | -------------------------------------------------------------------------------- /policies/iam-user-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-user-audit 3 | resource: iam-user 4 | description: | 5 | Cloud Custodian IAM User Audit 6 | comments: | 7 | Send notification when IAM user is found with AmazonEC2FullAccess 8 | and not part of the Ec2InstanceLaunchers group. 9 | mode: 10 | type: periodic 11 | role: arn:aws:iam:::role/CloudCustodian 12 | schedule: "rate(1 day)" 13 | filters: 14 | - not: 15 | - type: group 16 | key: GroupName 17 | value: Ec2InstanceLaunchers 18 | - type: policy 19 | key: PolicyName 20 | value: AmazonEC2FullAccess 21 | op: regex 22 | actions: 23 | - type: notify 24 | template: iam-user-audit 25 | template_format: 'html' 26 | slack_template: slack-iam-user-audit 27 | priority_header: '5' 28 | subject: 'IAM User Audit: IAM User(s) found not in Ec2InstanceLaunchers but with AmazonEC2FullAccess' 29 | to: 30 | - cloudcustodianadmins@company.com 31 | - slack://# 32 | owner_absent_contact: 33 | - cloudcustodianadmins@company.com 34 | transport: 35 | type: sqs 36 | queue: https://sqs.us-east-1.amazonaws.com//cloud-cloudcustodian 37 | -------------------------------------------------------------------------------- /policies/iam-user-set-groups.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-user-set-group 3 | resource: iam-user 4 | filters: 5 | - type: value 6 | key: UserName 7 | value: iam-user-1|iam-user-2|iam-user-3 8 | op: regex 9 | actions: 10 | - type: set-groups 11 | state: add 12 | group: MyIAMGroupName 13 | -------------------------------------------------------------------------------- /policies/iam-user-tagged-resources-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: iam-user-ec2-tagged-resources-report 4 | resource: ec2 5 | filters: 6 | - or: 7 | - type: value 8 | key: tag:Owner 9 | op: regex 10 | value: .*minh.do.* 11 | 12 | - name: iam-user-ebs-tagged-resources-report 13 | resource: ebs 14 | filters: 15 | - or: 16 | - type: value 17 | key: tag:Owner 18 | op: regex 19 | value: .*minh.do.* 20 | 21 | - name: iam-user-ebs-snapshot-tagged-resources-report 22 | resource: ebs-snapshot 23 | filters: 24 | - or: 25 | - type: value 26 | key: tag:Owner 27 | op: regex 28 | value: .*minh.do.* 29 | 30 | - name: iam-user-security-group-tagged-resources-report 31 | resource: security-group 32 | filters: 33 | - or: 34 | - type: value 35 | key: tag:Owner 36 | op: regex 37 | value: .*minh.do.* 38 | 39 | - name: iam-user-ami-tagged-resources-report 40 | resource: ami 41 | filters: 42 | - or: 43 | - type: value 44 | key: tag:Owner 45 | op: regex 46 | value: .*minh.do.* 47 | 48 | - name: iam-user-dynamodb-table-tagged-resources-report 49 | resource: dynamodb-table 50 | filters: 51 | - or: 52 | - type: value 53 | key: tag:Owner 54 | op: regex 55 | value: .*minh.do.* 56 | 57 | - name: iam-user-dynamodb-stream-tagged-resources-report 58 | resource: dynamodb-stream 59 | filters: 60 | - or: 61 | - type: value 62 | key: tag:Owner 63 | op: regex 64 | value: .*minh.do.* 65 | 66 | - name: iam-user-dynamodb-backup-tagged-resources-report 67 | resource: dynamodb-backup 68 | filters: 69 | - or: 70 | - type: value 71 | key: tag:Owner 72 | op: regex 73 | value: .*minh.do.* 74 | 75 | - name: iam-user-elasticsearch-resources-report 76 | resource: elasticsearch 77 | filters: 78 | - or: 79 | - type: value 80 | key: tag:Owner 81 | op: regex 82 | value: .*minh.do.* 83 | 84 | - name: iam-user-elb-tagged-resources-report 85 | resource: elb 86 | filters: 87 | - or: 88 | - type: value 89 | key: tag:Owner 90 | op: regex 91 | value: .*minh.do.* 92 | 93 | - name: iam-user-eni-tagged-resources-report 94 | resource: eni 95 | filters: 96 | - or: 97 | - type: value 98 | key: tag:Owner 99 | op: regex 100 | value: .*minh.do.* 101 | 102 | - name: iam-user-lambda-tagged-resources-report 103 | resource: lambda 104 | filters: 105 | - or: 106 | - type: value 107 | key: tag:Owner 108 | op: regex 109 | value: .*minh.do.* 110 | 111 | - name: iam-user-lambda-layer-tagged-resources-report 112 | resource: lambda-layer 113 | filters: 114 | - or: 115 | - type: value 116 | key: tag:Owner 117 | op: regex 118 | value: .*minh.do.* 119 | 120 | - name: iam-user-rds-tagged-resources-report 121 | resource: rds 122 | filters: 123 | - or: 124 | - type: value 125 | key: tag:Owner 126 | op: regex 127 | value: .*minh.do.* 128 | 129 | - name: iam-user-s3-tagged-resources-report 130 | resource: s3 131 | filters: 132 | - or: 133 | - type: value 134 | key: tag:Owner 135 | op: regex 136 | value: .*minh.do.* 137 | 138 | - name: iam-user-sqs-tagged-resources-report 139 | resource: sqs 140 | filters: 141 | - or: 142 | - type: value 143 | key: tag:Owner 144 | op: regex 145 | value: .*minh.do.* 146 | 147 | - name: iam-user-sns-tagged-resources-report 148 | resource: sns 149 | filters: 150 | - or: 151 | - type: value 152 | key: tag:Owner 153 | op: regex 154 | value: .*minh.do.* 155 | 156 | - name: iam-user-cfn-tagged-resources-report 157 | resource: cfn 158 | filters: 159 | - or: 160 | - type: value 161 | key: tag:Owner 162 | op: regex 163 | value: .*minh.do.* 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /policies/iam.py: -------------------------------------------------------------------------------- 1 | # This section of code should be used to replace the has-allow-all function 2 | # in the /cloud-custodian/c7n/resources/iam.py file 3 | # 4 | # Usage: 5 | # 6 | # 1) Backup original ~/cloud-custodian/c7n/resources/iam.py 7 | # 2) Update iam.py with section below (search for has-allow-all) 8 | # 3) Rebuild site-package 9 | # 4) cd ~/cloud-custodian 10 | # python setup.py install 11 | # 5) Test 12 | 13 | schema = type_schema('has-allow-all') 14 | permissions = ('iam:ListPolicies', 'iam:ListPolicyVersions') 15 | 16 | def has_allow_all_policy(self, client, resource): 17 | statements = client.get_policy_version( 18 | PolicyArn=resource['Arn'], 19 | VersionId=resource['DefaultVersionId'] 20 | )['PolicyVersion']['Document']['Statement'] 21 | if isinstance(statements, dict): 22 | statements = [statements] 23 | 24 | for s in statements: 25 | if ('Condition' not in s and 26 | 'Action' in s and 27 | ('account:*' in s['Action'] or 28 | 'account:EnableRegion' in s['Action']) and 29 | 'Resource' in s and 30 | isinstance(s['Resource'], six.string_types) and 31 | s['Resource'] == "*" and 32 | s['Effect'] == "Allow"): 33 | return True 34 | return False 35 | -------------------------------------------------------------------------------- /policies/iam.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-user-filter-policy 3 | resource: iam-user 4 | description: | 5 | Retrieve list of IAM users that match regex. 6 | filters: 7 | - type: value 8 | key: UserName 9 | op: regex 10 | value: "david.lin.ctr" 11 | -------------------------------------------------------------------------------- /policies/mailer.yml: -------------------------------------------------------------------------------- 1 | # Which queue should we listen to for messages 2 | queue_url: https://sqs.us-east-1.amazonaws.com/1234567890/sandbox 3 | 4 | # Default from address 5 | from_address: email@address.com 6 | 7 | # Tags that we should look at for address infomation 8 | contact_tags: 9 | - OwnerContact 10 | - OwnerEmail 11 | - SNSTopicARN 12 | 13 | # Standard Lambda Function Config 14 | region: us-east-1 15 | role: arn:aws:iam::1234567890:role/CloudCustodianRole 16 | slack_token: xoxb-bot_token_string_goes_here 17 | 18 | -------------------------------------------------------------------------------- /policies/mark-unused-sgroups.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: mark-unused-security-groups-for-deletion 3 | resource: security-group 4 | description: | 5 | Mark unused security groups for deletion in X days. 6 | A mark is a tag that gets created for each 7 | unused security group. 8 | The key/value pair takes on the following attributes: 9 | key = maid_status 10 | value = 'Resource does not meet policy: delete@year/month/day' 11 | filters: 12 | - unused 13 | - type: value 14 | key: GroupName 15 | op: regex 16 | value: .*launch\-wizard.* 17 | actions: 18 | - type: mark-for-op 19 | op: delete 20 | days: 0 21 | -------------------------------------------------------------------------------- /policies/mfa-audit-broken.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: mfa-audit-reminder 3 | description: Cloud Custodian MFA Audit Notification 4 | comment: | 5 | Retrieve list of all IAM users with MFA disabled 6 | in the group 'Administrators' and send notification 7 | if MFA is not enabled after 3 days of the create date. 8 | Send notification via SES and Slack. 9 | resource: iam-user 10 | mode: 11 | type: periodic 12 | role: arn:aws:iam::1234567890:role/CloudCustodian 13 | schedule: "rate(5 minutes)" 14 | filters: 15 | - type: credential 16 | key: mfa_active 17 | value: false 18 | - type: group 19 | key: GroupName 20 | value: Administrators 21 | - type: value 22 | key: CreateDate 23 | op: less-than 24 | value_type: age 25 | value: 3 26 | actions: 27 | - type: notify 28 | template: mfa-audit-reminder.html 29 | template_format: 'html' 30 | slack_template: slack-mfa-audit-reminder 31 | priority_header: '5' 32 | subject: 'Security Audit: IAM users in Administrators group with MFA Disabled' 33 | to: 34 | - 35 | - slack://#ie-stratus 36 | owner_absent_contact: 37 | - 38 | transport: 39 | type: sqs 40 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 41 | 42 | 43 | - name: mfa-audit-disable-access 44 | description: Cloud Custodian MFA Audit Disable Access 45 | comment: | 46 | Retrieve list of all IAM users with MFA disabled 47 | in the group 'Administrators' and send notification 48 | if MFA is not enabled after 5 days of inactivity. 49 | Send notification via SES and Slack. 50 | Disable user access to management console. 51 | Delete user access-keys. 52 | resource: iam-user 53 | mode: 54 | type: periodic 55 | role: arn:aws:iam::1234567890:role/CloudCustodian 56 | schedule: "rate(5 minutes)" 57 | filters: 58 | - type: credential 59 | key: mfa_active 60 | value: false 61 | - type: group 62 | key: GroupName 63 | value: Administrators 64 | - type: value 65 | key: CreateDate 66 | op: greater-than 67 | value_type: age 68 | value: 5 69 | actions: 70 | - type: delete 71 | options: 72 | - access-keys 73 | - console-access 74 | - type: notify 75 | template: mfa-audit-disable-access 76 | template_format: 'html' 77 | slack_template: slack-mfa-audit-disable-access 78 | priority_header: '5' 79 | subject: 'Security Audit: AWS Console Access Disabled and Access Keys Deleted' 80 | to: 81 | - 82 | - slack://# 83 | owner_absent_contact: 84 | - 85 | transport: 86 | type: sqs 87 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 88 | -------------------------------------------------------------------------------- /policies/mfa-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: mfa-audit-reminder 3 | description: Cloud Custodian MFA Audit Notification 4 | comment: | 5 | Retrieve list of all IAM users with MFA disabled 6 | in the group 'Administrators' and send notification 7 | if MFA is not enabled after 3 days of the create date. 8 | Send notification via SES and Slack. 9 | Requires 'iam:ListGroupsForUser' permissions. 10 | resource: iam-user 11 | filters: 12 | - type: credential 13 | key: mfa_active 14 | value: false 15 | - type: group 16 | key: GroupName 17 | value: Administrators 18 | - type: value 19 | key: CreateDate 20 | op: less-than 21 | value_type: age 22 | value: 3 23 | actions: 24 | - type: notify 25 | template: mfa-audit-reminder.html 26 | template_format: 'html' 27 | slack_template: slack-mfa-audit-reminder 28 | priority_header: '5' 29 | subject: 'Security Audit: IAM users in Administrators group with MFA Disabled' 30 | to: 31 | - 32 | - slack://# 33 | owner_absent_contact: 34 | - 35 | transport: 36 | type: sqs 37 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 38 | 39 | 40 | - name: mfa-audit-disable-access 41 | description: Cloud Custodian MFA Audit Disable Access 42 | comment: | 43 | Retrieve list of all IAM users with MFA disabled 44 | in the group 'Administrators' and send notification 45 | if MFA is not enabled after 5 days of inactivity. 46 | Send notification via SES and Slack. 47 | Disable user access to management console. 48 | Delete user access-keys. 49 | resource: iam-user 50 | filters: 51 | - type: credential 52 | key: mfa_active 53 | value: false 54 | - type: group 55 | key: GroupName 56 | value: Administrators 57 | - type: value 58 | key: CreateDate 59 | op: greater-than 60 | value_type: age 61 | value: 5 62 | actions: 63 | - type: delete 64 | options: 65 | - access-keys 66 | - console-access 67 | - type: notify 68 | template: mfa-audit-disable-access.html 69 | template_format: 'html' 70 | slack_template: slack-mfa-audit-disable-access 71 | priority_header: '5' 72 | subject: 'Security Audit: AWS Console Access Disabled and Access Keys Deleted' 73 | to: 74 | - 75 | - slack://# 76 | owner_absent_contact: 77 | - 78 | transport: 79 | type: sqs 80 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 81 | -------------------------------------------------------------------------------- /policies/mfa-unused.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: mfa-unused 3 | resource: iam-user 4 | description: | 5 | Retrieve list of all IAM users in the group 'Administrators' 6 | who have not enabled MFA. 7 | filters: 8 | - type: credential 9 | key: mfa_active 10 | value: false 11 | - type: group 12 | key: GroupName 13 | value: Administrators 14 | -------------------------------------------------------------------------------- /policies/mfa.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: mfa-user-filter-policy 3 | resource: iam-user 4 | description: | 5 | Retrieve list of IAM users with MFA enabled. 6 | filters: 7 | - type: credential 8 | key: mfa_active 9 | value: true 10 | -------------------------------------------------------------------------------- /policies/new-user-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: new-user-audit 3 | resource: iam-user 4 | description: | 5 | Cloud Custodian New User Audit 6 | comment: | 7 | Retrieves list of all IAM users with MFA disabled 8 | in the last 30 days. 9 | filters: 10 | - type: credential 11 | key: mfa_active 12 | value: false 13 | - type: value 14 | key: CreateDate 15 | op: less-than 16 | value_type: age 17 | value: 30 18 | - type: group 19 | key: GroupName 20 | value: CloudCustodianAdmins 21 | 22 | -------------------------------------------------------------------------------- /policies/offhours.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: maid-offhours 3 | description: | 4 | Cloud Custodian Maid Offhours 5 | comment: | 6 | Stop EC2 instances after offhours that have tag of 7 | key = 'maid_offhours' 8 | value = schedule 9 | example value -> 'on=(M-F,16);off=(M-F,23);tz=est' 10 | use 'pt' for pacific time 11 | See http://capitalone.github.io/cloud-custodian/docs/quickstart/offhours.html#offhours 12 | resource: ec2 13 | mode: 14 | type: periodic 15 | role: arn:aws:iam::1234567890:role/CloudCustodian 16 | schedule: "rate(1 minute)" 17 | filters: 18 | - type: offhour 19 | default_tz: est 20 | offhour: 1 21 | actions: 22 | - stop 23 | 24 | - name: maid-onhours 25 | description: | 26 | Cloud Custodian Maid Onhours 27 | comment: | 28 | Start EC2 instances after onhours that have a tag of 29 | key = 'maid_offhours' 30 | value = schedule 31 | example value -> 'on=(M-F,16);tz=est' 32 | use 'pt' for pacific time 33 | See http://capitalone.github.io/cloud-custodian/docs/quickstart/offhours.html#offhours 34 | resource: ec2 35 | mode: 36 | type: periodic 37 | role: arn:aws:iam::1234567890:role/CloudCustodian 38 | schedule: "rate(1 minute)" 39 | filters: 40 | - type: onhour 41 | default_tz: est 42 | onhour: 1 43 | actions: 44 | - start 45 | 46 | - name: custom-offhours 47 | description: | 48 | Cloud Custodian Custom Offhours 49 | comment: | 50 | Stop EC2 instances after hours that have custom tag of 51 | tag = 'StopAfterHours' 52 | value = schedule 53 | example value -> 'off=(M-F,23);tz=est' 54 | use 'tz=pt' for pacific time 55 | See http://capitalone.github.io/cloud-custodian/docs/quickstart/offhours.html#offhours 56 | resource: ec2 57 | mode: 58 | type: periodic 59 | role: arn:aws:iam::1234567890:role/CloudCustodian 60 | schedule: "rate(1 minute)" 61 | filters: 62 | - type: offhour 63 | tag: StopAfterHours 64 | default_tz: est 65 | offhour: 1 66 | actions: 67 | - stop 68 | 69 | - name: custom-onhours 70 | description: | 71 | Cloud Custodian Custom Onhours 72 | comments: | 73 | Start EC2 instances after onhours that have custom tag of 74 | tag = 'StartAfterHours' 75 | value = schedule 76 | example value -> 'on=(M-F,16);tz=est' 77 | use 'tz=pt' for pacific time 78 | See http://capitalone.github.io/cloud-custodian/docs/quickstart/offhours.html#offhours 79 | resource: ec2 80 | mode: 81 | type: periodic 82 | role: arn:aws:iam::1234567890:role/CloudCustodian 83 | schedule: "rate(1 minute)" 84 | filters: 85 | - type: onhour 86 | tag: StartAfterHours 87 | default_tz: est 88 | onhour: 1 89 | actions: 90 | - start 91 | -------------------------------------------------------------------------------- /policies/owner-tag-audit.yml: -------------------------------------------------------------------------------- 1 | # custodian report -s output owner-tag-audit.yml --field Name=tag:Name --field tag:Owner=tag:Owner --field KeyName=KeyName --field InstanceId=InstanceId --field Type=InstanceType --field State=State --format grid --no-default 2 | policies: 3 | - name: owner-tag-audit 4 | resource: ec2 5 | description: | 6 | Cloud Custodian Owner Tag Audit 7 | comments: | 8 | Retrieve list of all instances that 9 | match specific "Owner" tag 10 | mode: 11 | type: ec2-instance-state 12 | role: arn:aws:iam::123456789:role/CloudCustodian 13 | events: 14 | - running 15 | filters: 16 | - or: 17 | - type: value 18 | key: "tag:Owner" 19 | value: (.*david.*) 20 | op: regex 21 | - type: value 22 | key: "KeyName" 23 | value: (.*david.*) 24 | op: regex 25 | actions: 26 | - type: notify 27 | template: owner-tag-audit.html 28 | slack_template: slack-ownder-tag-audit 29 | template_format: 'html' 30 | priority_header: '5' 31 | subject: 'Tag Audit: EC Instance(s) with Owner tag set to srikanth.yadav.ctr' 32 | to: 33 | - 34 | - slack://# 35 | owner_absent_contact: 36 | - 37 | transport: 38 | type: sqs 39 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 40 | -------------------------------------------------------------------------------- /policies/phd-notifications.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: phd-notifications 3 | resource: health-event 4 | description: | 5 | Cloud Custodian Personal Health Dashboard (PHD) Notifications 6 | comments: | 7 | Send alert when PHD notification is found 8 | mode: 9 | type: periodic 10 | role: arn:aws:iam::929292782238:role/CloudCustodian 11 | schedule: "rate(1 day)" 12 | filters: 13 | - type: value 14 | key: "lastUpdatedTime" 15 | op: less-than 16 | value_type: age 17 | value: 1 18 | actions: 19 | - type: notify 20 | slack_template: slack-phd-notifications 21 | priority_header: '5' 22 | subject: 'Personal Health Dashboard Notification(s)' 23 | to: 24 | - slack://#ie-alerts 25 | transport: 26 | type: sqs 27 | queue: https://sqs.us-east-1.amazonaws.com/929292782238/cloud-cloudcustodian 28 | -------------------------------------------------------------------------------- /policies/public-instance-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: public-instance-audit 3 | resource: ec2 4 | description: | 5 | Cloud Custodian Public Instance Audit 6 | comments: | 7 | Retrieve list of all instances that 8 | - are not in whitelist 9 | - attached to a public subnet 10 | - have public IP address 11 | mode: 12 | type: ec2-instance-state 13 | role: arn:aws:iam::1234567890:role/CloudCustodian 14 | events: 15 | - pending 16 | filters: 17 | - not: 18 | - type: value 19 | key: "tag:Name" 20 | value: (david-VPN|davidi-Bastion) 21 | op: regex 22 | - or: 23 | - type: subnet 24 | key: "tag:Name" 25 | op: regex 26 | value: ".*pub" 27 | - type: value 28 | key: "PublicIpAddress" 29 | value: not-null 30 | - and: 31 | - type: value 32 | key: VpcId 33 | value: vpc-12345678 34 | actions: 35 | - type: notify 36 | template: public-instance-audit.html 37 | slack_template: slack-public-instance-audit 38 | template_format: 'html' 39 | priority_header: '5' 40 | subject: 'Security Audit: Public EC2 Instance Launched' 41 | to: 42 | - 43 | - slack://# 44 | owner_absent_contact: 45 | - 46 | transport: 47 | type: sqs 48 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 49 | -------------------------------------------------------------------------------- /policies/public-subnet-instance-audit-lambda.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: subnet-audit 3 | resource: ec2 4 | description: | 5 | Filter ec2 resources based on the attributes of the network 6 | they are attached to then take action. For example, subnets with tag 'Location' 7 | and value that matches 'Internet' should be stopped. 8 | mode: 9 | type: ec2-instance-state 10 | role: arn:aws:iam::485020822820:role/CloudCustodianRole 11 | events: 12 | - pending 13 | filters: 14 | - type: subnet 15 | key: "tag:Location" 16 | value: "Internet" 17 | actions: 18 | - stop 19 | -------------------------------------------------------------------------------- /policies/public-subnet-instance-audit-notify.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: public-subnet-instance-audit-notification 3 | resource: ec2 4 | mode: 5 | type: ec2-instance-state 6 | role: arn:aws:iam::485020822820:role/CloudCustodianRole 7 | events: 8 | - pending 9 | filters: 10 | - type: subnet 11 | key: "tag:Location" 12 | value: "Internet" 13 | actions: 14 | - type: notify 15 | template: default.html 16 | template_format: 'html' 17 | priority_header: '5' 18 | subject: 'Cloud Custodian: EC2 Instance Launched in Public Subnet' 19 | to: 20 | - david.lin.ctr@tri.global, peter.richmond@tri.global, mike.garrison@tri.global 21 | owner_absent_contact: 22 | - david.lin.ctr@tri.global 23 | transport: 24 | type: sqs 25 | queue: https://sqs.us-east-1.amazonaws.com/485020822820/david-lin-ctr-iesandbox-cloudcustodian 26 | -------------------------------------------------------------------------------- /policies/public-subnet-instance-audit-whitelist.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: whitelist 3 | resource: ec2 4 | mode: 5 | type: ec2-instance-state 6 | role: arn:aws:iam::1234567890:role/CloudCustodianRole 7 | events: 8 | - pending 9 | filters: 10 | - not: 11 | - type: value 12 | key: "tag:Name" 13 | value: (Instance_Name_1|Instance_Name_2) 14 | op: regex 15 | - and: 16 | - type: subnet 17 | key: "tag:Name" 18 | value: "PublicSubnet" 19 | actions: 20 | - terminate 21 | - type: notify 22 | template: ec2-public-whitelist.html 23 | slack_template: slack_ec2-public-whitelist 24 | template_format: 'html' 25 | priority_header: '5' 26 | subject: 'Cloud Custodian: EC2 Instance Launched in Public Subnet' 27 | to: 28 | - email@address.com 29 | - slack://#slack-channel-goes-here 30 | owner_absent_contact: 31 | - email@address.com 32 | transport: 33 | type: sqs 34 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/sandbox 35 | -------------------------------------------------------------------------------- /policies/roles.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: iam-roles-unused 3 | resource: iam-role 4 | description: | 5 | Retrieve list of unused roles. 6 | filters: 7 | - type: used 8 | state: false 9 | -------------------------------------------------------------------------------- /policies/s3-prevent-bucket-creation.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | 4 | - name: s3-prevent-bucket-creation 5 | resource: s3 6 | description: | 7 | Cloud Custodian S3 Bucket Creation Prevention 8 | comments: | 9 | Prevents creation of S3 buckets in us-east-1 10 | and sends email notification to user 11 | mode: 12 | type: cloudtrail 13 | role: arn:aws:iam::account_id:role/CloudCustodian 14 | events: 15 | - CreateBucket 16 | timeout: 200 17 | filters: 18 | - and: 19 | - not: 20 | - type: value 21 | key: "Name" 22 | value: "david-lin-ctr-sandbox-1|david-lin-ctr-sandbox-2" 23 | op: regex 24 | - type: event 25 | key: "region" 26 | op: in 27 | value: 28 | - us-east-1 29 | actions: 30 | - type: delete 31 | remove-contents: true 32 | - type: notify 33 | template: s3-prevent-bucket-creation.html 34 | template_format: 'html' 35 | slack_template: slack-s3-prevent-bucket-creation 36 | priority_header: '5' 37 | subject: "S3 Audit: S3 Bucket Deleted" 38 | to: 39 | - cloudcustodianadmins@company.com 40 | - slack://#channel_name 41 | - event-owner 42 | owner_absent_contact: 43 | - cloudcustodianadmins@company.com 44 | transport: 45 | type: sqs 46 | queue: https://sqs.us-east-1.amazonaws.com/account_id/cloud-cloudcustodian 47 | -------------------------------------------------------------------------------- /policies/s3-public-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: s3-public-audit 3 | description: | 4 | Cloud Custodian Public S3 Audit 5 | comments: | 6 | Send notification when public S3 bucket gets created 7 | resource: s3 8 | mode: 9 | type: cloudtrail 10 | role: arn:aws:iam::1234567890:role/CloudCustodian 11 | events: 12 | - CreateBucket 13 | filters: 14 | - type: global-grants 15 | actions: 16 | - type: notify 17 | template: s3-public-audit.html 18 | template_format: 'html' 19 | slack_template: slack-s3-public-audit 20 | priority_header: '5' 21 | subject: 'Security Audit: Public S3 Bucket Created' 22 | to: 23 | - your_verified_email@domain.com 24 | - slack://#channel_name_goes_here 25 | owner_absent_contact: 26 | - your_verified_email@domain.com 27 | transport: 28 | type: sqs 29 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 30 | -------------------------------------------------------------------------------- /policies/s3-server-access-logging.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | - name: s3-server-access-logging-us-east-1 4 | resource: s3 5 | description: | 6 | Cloud Custodian S3 Server Access Logging 7 | comments: | 8 | Enables S3 server access logging and sets TargetBucket 9 | and TargetPrefix for us-east-1 10 | mode: 11 | type: periodic 12 | role: arn:aws:iam::1234567890:role/CloudCustodian 13 | schedule: "rate(1 day)" 14 | timeout: 300 15 | filters: 16 | - type: value 17 | key: "Location.LocationConstraint" 18 | value: null 19 | actions: 20 | - type: toggle-logging 21 | target_bucket: s3-access-logs-1234567890-us-east-1 22 | target_prefix: access_logs/{source_bucket_name}/{source_bucket_name} 23 | 24 | 25 | - name: s3-server-access-logging-us-east-2 26 | resource: s3 27 | description: | 28 | Cloud Custodian S3 Server Access Logging 29 | comments: | 30 | Enables S3 server access logging and sets TargetBucket 31 | and TargetPrefix for us-east-2 32 | mode: 33 | type: periodic 34 | role: arn:aws:iam::1234567890:role/CloudCustodian 35 | schedule: "rate(1 day)" 36 | timeout: 300 37 | filters: 38 | - type: value 39 | key: "Location.LocationConstraint" 40 | value: "us-east-2" 41 | actions: 42 | - type: toggle-logging 43 | target_bucket: s3-access-logs-1234567890-us-east-2 44 | target_prefix: access_logs/{source_bucket_name}/{source_bucket_name} 45 | 46 | 47 | - name: s3-server-access-logging-us-west-1 48 | resource: s3 49 | description: | 50 | Cloud Custodian S3 Server Access Logging 51 | comments: | 52 | Enables S3 server access logging and sets TargetBucket 53 | and TargetPrefix for us-west-1 54 | mode: 55 | type: periodic 56 | role: arn:aws:iam::1234567890:role/CloudCustodian 57 | schedule: "rate(1 day)" 58 | timeout: 300 59 | filters: 60 | - type: value 61 | key: "Location.LocationConstraint" 62 | value: "us-west-1" 63 | actions: 64 | - type: toggle-logging 65 | target_bucket: s3-access-logs-1234567890-us-west-1 66 | target_prefix: access_logs/{source_bucket_name}/{source_bucket_name} 67 | 68 | 69 | - name: s3-server-access-logging-us-west-2 70 | resource: s3 71 | description: | 72 | Cloud Custodian S3 Server Access Logging 73 | comments: | 74 | Enables S3 server access logging and sets TargetBucket 75 | and TargetPrefix for us-west-2 76 | mode: 77 | type: periodic 78 | role: arn:aws:iam::1234567890:role/CloudCustodian 79 | schedule: "rate(1 day)" 80 | timeout: 300 81 | filters: 82 | - type: value 83 | key: "Location.LocationConstraint" 84 | value: "us-west-2" 85 | actions: 86 | - type: toggle-logging 87 | target_bucket: s3-access-logs-1234567890-us-west-2 88 | target_prefix: access_logs/{source_bucket_name}/{source_bucket_name} 89 | 90 | 91 | - name: s3-server-access-logging-ap-northeast-1 92 | resource: s3 93 | description: | 94 | Cloud Custodian S3 Server Access Logging 95 | comments: | 96 | Enables S3 server access logging and sets TargetBucket 97 | and TargetPrefix for ap-northeast-1 98 | mode: 99 | type: periodic 100 | role: arn:aws:iam::1234567890:role/CloudCustodian 101 | schedule: "rate(1 day)" 102 | timeout: 300 103 | filters: 104 | - type: value 105 | key: "Location.LocationConstraint" 106 | value: "ap-northeast-1" 107 | actions: 108 | - type: toggle-logging 109 | target_bucket: s3-access-logs-1234567890-ap-northeast-1 110 | target_prefix: access_logs/{source_bucket_name}/{source_bucket_name} 111 | -------------------------------------------------------------------------------- /policies/s3-service-limit-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: s3-service-limit-audit 3 | resource: s3 4 | description: | 5 | Cloud Custodian S3 Service Limit Audit 6 | comment: | 7 | Periodically check S3 service limit 8 | mode: 9 | type: periodic 10 | role: arn:aws:iam:::role/CloudCustodian 11 | schedule: "rate(1 day)" 12 | timeout: 300 13 | filters: 14 | - not: 15 | - "tag:Name": "NoOneWillEverUseThisName" 16 | - type: value 17 | value_type: resource_count 18 | op: gt 19 | value: 200 20 | actions: 21 | - type: notify 22 | template: s3-service-limit-audit.html 23 | slack_template: slack-s3-service-limit-audit 24 | template_format: 'html' 25 | priority_header: '5' 26 | subject: 'S3 Service Limit Audit: S3 Service Limit Exceeded' 27 | to: 28 | - 29 | - slack://# 30 | owner_absent_contact: 31 | - 32 | transport: 33 | type: sqs 34 | queue: https://sqs.us-east-1.amazonaws.com//cloud-cloudcustodian 35 | -------------------------------------------------------------------------------- /policies/s3-target-bucket-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | 3 | 4 | - name: s3-target-bucket-audit 5 | resource: s3 6 | description: | 7 | Cloud Custodian S3 Target Bucket Audit 8 | comments: | 9 | Checks S3 server access logging target bucket name is compliant. 10 | Sends notification if name is not compliant. 11 | Supplements s3-server-access-logging.yml policy. 12 | mode: 13 | type: periodic 14 | role: arn:aws:iam::acccount_id:role/CloudCustodian 15 | schedule: "rate(1 day)" 16 | timeout: 300 17 | filters: 18 | - not: 19 | - or: 20 | - type: value 21 | key: "Logging" 22 | value: empty 23 | - type: value 24 | key: "Logging.TargetBucket" 25 | value: "^s3-access-logs-.*" 26 | op: regex 27 | actions: 28 | - type: notify 29 | template: s3-target-bucket-audit.html 30 | template_format: 'html' 31 | slack_template: slack-s3-target-bucket-audit 32 | priority_header: '5' 33 | subject: 'Security Audit: S3 Target Bucket Audit' 34 | to: 35 | - email@address.com 36 | - slack://#channel 37 | owner_absent_contact: 38 | - email@address.com 39 | transport: 40 | type: sqs 41 | queue: https://sqs.us-east-1.amazonaws.com/account_id/cloud-cloudcustodian 42 | -------------------------------------------------------------------------------- /policies/security-groups-unused-notify.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: security-groups-unused 3 | resource: security-group 4 | description: | 5 | Retrieve unused security groups using regex. 6 | Notify using Simple Email Service (SES). 7 | To get a complete list, use value of .* 8 | To get a subset, use a regex pattern. 9 | filters: 10 | - unused 11 | - type: value 12 | key: GroupName 13 | op: regex 14 | value: .* 15 | actions: 16 | - type: notify 17 | template: default.html 18 | template_format: 'html' 19 | priority_header: '5' 20 | subject: 'CloudCustodian: Unused Security Groups' 21 | to: 22 | - email-address-goes-here 23 | owner_absent_contact: 24 | - email-address-goes-here 25 | transport: 26 | type: sqs 27 | queue: sqs-url-goes-here 28 | -------------------------------------------------------------------------------- /policies/security-groups-unused.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: security-groups-unused 3 | resource: security-group 4 | description: | 5 | Retrieve unused security groups using regex. 6 | To get a complete list, use value of .* 7 | To get a subset, use a regex pattern. 8 | filters: 9 | - unused 10 | - type: value 11 | key: GroupName 12 | op: regex 13 | value: ".*wiz" 14 | -------------------------------------------------------------------------------- /policies/sgroup-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: sgroup-audit 3 | resource: aws.security-group 4 | description: | 5 | Cloud Custodian Security Groups Audit 6 | comments: | 7 | Retrieve Security Groups that Match Filter 8 | filters: 9 | - type: ingress 10 | Cidr: 11 | value_type: cidr 12 | op: in 13 | value: 10.120.0.0/16 14 | - not: 15 | - type: ingress 16 | Cidr: 17 | value_type: cidr 18 | op: in 19 | value: 10.121.0.0/16 20 | -------------------------------------------------------------------------------- /policies/slack-notify.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: slack-notify 3 | resource: security-group 4 | description: | 5 | Retrieve unused security groups using regex. 6 | Notify using Slack. 7 | To get a complete list, use value of .* 8 | To get a subset, use a regex pattern. 9 | filters: 10 | - unused 11 | - type: value 12 | key: GroupName 13 | op: regex 14 | value: .* 15 | actions: 16 | - type: notify 17 | template_slack: slack_default 18 | template_format: 'html' 19 | priority_header: '5' 20 | subject: 'CloudCustodian: Unused Security Groups' 21 | to: 22 | - slack://#cloudcustodianprivate 23 | owner_absent_contact: 24 | - email@address.com 25 | transport: 26 | type: sqs 27 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/sandbox 28 | -------------------------------------------------------------------------------- /policies/ssm-managed-instance.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: ssm-managed-instance 3 | resource: ssm-managed-instance 4 | description: | 5 | Cloud Custodian SSM Managed Instances 6 | comments: | 7 | Retrieve All SSM Managed Instance Attributes 8 | filters: 9 | - not: 10 | - type: value 11 | key: foo 12 | value: "foo" 13 | -------------------------------------------------------------------------------- /policies/stopped-instances.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: stopped-instances 3 | resource: ec2 4 | description: | 5 | Cloud Custodian Stopped Instances Audit 6 | comments: | 7 | Retrieve list of all instances that 8 | - are stopped 9 | filters: 10 | - type: value 11 | key: VpcId 12 | value: vpc-b7407ed3 13 | - type: value 14 | key: State.Name 15 | value: stopped 16 | 17 | -------------------------------------------------------------------------------- /policies/subnet-ip-address-usage-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: subnet-ip-address-usage-audit 3 | resource: subnet 4 | description: | 5 | Cloud Custodian Subnet IP Address Audit 6 | comments: | 7 | Periodically retrieve list of private subnets for specific availability zones. 8 | Generate email and Slack notifications when AvailableIpAddressCount 9 | is less-than 10 for specified regions. 10 | mode: 11 | type: periodic 12 | role: arn:aws:iam::123456789012:role/CloudCustodian 13 | schedule: "rate(1 hour)" 14 | packages: [boto3, botocore, urllib3] 15 | filters: 16 | - type: value 17 | key: State 18 | value: "available" 19 | - type: value 20 | key: AvailableIpAddressCount 21 | value: 10 22 | op: less-than 23 | - or: 24 | - type: value 25 | key: AvailabilityZone 26 | value: "us-east-1a" 27 | - type: value 28 | key: AvailabilityZone 29 | value: "us-east-1c" 30 | - type: value 31 | key: AvailabilityZone 32 | value: "us-east-1d" 33 | - type: value 34 | key: MapPublicIpOnLaunch 35 | value: false 36 | actions: 37 | - type: post-finding 38 | severity_normalized: 10 39 | types: 40 | - "Software and Configuration Checks/AWS Security Best Practices" 41 | - type: notify 42 | template: subnet-ip-address-usage-audit.html 43 | slack_template: slack-subnet-ip-address-usage-audit 44 | template_format: 'html' 45 | priority_header: '5' 46 | subject: 'Subnet Audit: Subnets running low on IP addresses' 47 | to: 48 | - cloudcustodianadmins@domain.com 49 | - slack://#custodian-alerts 50 | owner_absent_contact: 51 | - cloudcustodianadmins@domain.com 52 | transport: 53 | type: sqs 54 | queue: https://sqs.us-east-1.amazonaws.com/123456789012/cloud-cloudcustodian 55 | -------------------------------------------------------------------------------- /policies/tag-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: tag-audit 3 | resource: ec2 4 | comment: | 5 | Retrieve list of all resources that match tag 6 | Note, ec2 is used as an example, but any resource that supports tags 7 | can be used. Simply replace the resource with the appropriate name. 8 | For example, replace ec2 with security-group if you want to filter 9 | against tagged security groups. 10 | filters: 11 | - "tag:Team": absent 12 | - type: value 13 | key: "tag:Owner" 14 | value: (.*mike\.garrison|.*amir\.kibbar|.*jon\.voigt|.*chris\.varnerin|.*nikos\.michalakis) 15 | op: regex 16 | # actions: 17 | # - type: tag 18 | # key: "Team" 19 | # value: "Cloud" 20 | -------------------------------------------------------------------------------- /policies/team-tag-ec2-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: team-tag-audit 3 | resource: ec2 4 | description: | 5 | Cloud Custodian EC2 Team Tag Audit 6 | comments: | 7 | Retrieve list of all instances that 8 | - are missing the tag "Team" 9 | mode: 10 | type: periodic 11 | role: arn:aws:iam::123456789012:role/CloudCustodian 12 | schedule: "cron(0 20 * * ? *)" 13 | filters: 14 | - or: 15 | - "tag:Team": absent 16 | - "tag:Team": empty 17 | actions: 18 | - type: notify 19 | template: team-tag-ec2-audit.html 20 | slack_template: slack-team-tag-ec2-audit 21 | template_format: 'html' 22 | priority_header: '5' 23 | subject: 'Tag Audit: EC2 Instance(s) with no tag named Team' 24 | to: 25 | - 26 | - slack://# 27 | owner_absent_contact: 28 | - 29 | transport: 30 | type: sqs 31 | queue: https://sqs.us-east-1.amazonaws.com/123456789012/cloud-cloudcustodian 32 | -------------------------------------------------------------------------------- /policies/team-tag-s3-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: team-tag-s3-audit 3 | resource: s3 4 | description: | 5 | Cloud Custodian S3 Team Tag Audit 6 | comments: | 7 | Periodically retrieve list of all S3 buckets that 8 | are missing the tag "Team" then send notification. 9 | mode: 10 | type: periodic 11 | role: arn:aws:iam::1234567890:role/CloudCustodian 12 | timeout: 300 13 | schedule: "cron(0 17 ? * MON-FRI *)" 14 | filters: 15 | - "tag:Team": absent 16 | actions: 17 | - type: notify 18 | template: team-tag-s3-audit.html 19 | slack_template: slack-team-tag-s3-audit 20 | template_format: 'html' 21 | priority_header: '5' 22 | subject: 'Tag Audit: S3 Bucket(s) with no tag named Team' 23 | to: 24 | - 25 | - slack://# 26 | owner_absent_contact: 27 | - 28 | transport: 29 | type: sqs 30 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 31 | -------------------------------------------------------------------------------- /policies/termination-protection-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: termination-protection-audit 3 | resource: ec2 4 | query: 5 | - instance-state-name: running 6 | filters: 7 | - not: 8 | - type: termination-protected 9 | - or: 10 | - "tag:Name": instance-1 11 | - "tag:Name": instance-2 12 | - "tag:Name": etc 13 | actions: 14 | - type: notify 15 | template: termination-protection-audit.html 16 | slack_template: slack-termination-protection-audit 17 | template_format: 'html' 18 | priority_header: '5' 19 | subject: 'Security Audit: White Listed Instance(s) found with Termination Protection Disabled' 20 | to: 21 | - 22 | - slack://# 23 | owner_absent_contact: 24 | - 25 | transport: 26 | type: sqs 27 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 28 | -------------------------------------------------------------------------------- /policies/termination-protection-list.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: termination-protection-list 3 | resource: ec2 4 | filters: 5 | - type: termination-protected 6 | 7 | -------------------------------------------------------------------------------- /policies/unused-sgroup-audit.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: unused-sgroups-audit 3 | resource: security-group 4 | description: | 5 | Cloud Custodian Unused Security Group Audit 6 | comments: | 7 | Retrieve unused security groups using regex and delete. 8 | Notify using Simple Email Service (SES). 9 | To get a complete list, use value of .* 10 | To get a subset, use a regex pattern. 11 | mode: 12 | type: periodic 13 | role: arn:aws:iam::1234567890:role/CloudCustodian 14 | schedule: "rate(1 day)" 15 | filters: 16 | - unused 17 | - type: value 18 | key: GroupName 19 | op: regex 20 | value: ".*wizard" 21 | actions: 22 | - delete 23 | - type: notify 24 | template: unused-sgroup-audit.html 25 | slack_template: slack-unused-sgroup-audit 26 | template_format: 'html' 27 | priority_header: '5' 28 | subject: 'Security Audit: Unused Security Groups' 29 | to: 30 | - 31 | - slack://# 32 | owner_absent_contact: 33 | - 34 | transport: 35 | type: sqs 36 | queue: https://sqs.us-east-1.amazonaws.com/1234567890/cloud-cloudcustodian 37 | -------------------------------------------------------------------------------- /policies/vpn.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: vpn_connections 3 | resource: vpn-connection 4 | description: | 5 | Cloud Custodian VPN Connections 6 | comments: | 7 | Retrieve all VPN Connections 8 | filters: 9 | - not: 10 | - "tag:Name": empty 11 | -------------------------------------------------------------------------------- /scripts/custodian-iam-user-cross-account-audit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # =========== 4 | # DESCRIPTION 5 | # =========== 6 | # This script is used as part of the TRI offboarding process to 7 | # retrieve a list of IAM users across all AWS accounts under the TRI org. 8 | # 9 | # This script uses c7n-org's orgaccounts.py script to generate a yml file named 10 | # offboading-orgaccounts.yml which contains the list of all known AWS accounts 11 | # under the TRI org. 12 | # 13 | # The offboarding-orgaccounts.yml file is then used by c7n-org to 14 | # search against all IAM users and write the results to file. 15 | # 16 | # VIM is used to open the file to quickly search for IAM user(s) being offboarded. 17 | # 18 | # Within vim, you can use the `/` command to search against usernames. 19 | # If a match is found, the account name that maps to the aws account number 20 | # can be found in the offboarding-oraccounts.yml file. 21 | 22 | # ========= 23 | # VARIABLES 24 | # ========= 25 | # ORGACCOUNTSPATH is the path where c7n-org's orgaccounts.py lives 26 | # ORGACCOUNTSFILE is the name of the file generated after orgaccounts.py is invoked 27 | # C7NORGPATH is the path where the output file offboarding-iam-users-audit.yml is stored 28 | 29 | ORGACCOUNTSPATH="/home/ubuntu/cloud-custodian/tools/c7n_org/scripts" 30 | ORGACCOUNTSFILE="offboarding-orgaccounts.yml" 31 | C7NORGPATH="/home/ubuntu/cloudcustodian/policies/c7n-org" 32 | 33 | 34 | echo "Creating $ORGACCOUNTSFILE file. This will take a minute..." 35 | #python $ORGACCOUNTSPATH/orgaccounts.py -f $ORGACCOUNTSPATH/$ORGACCOUNTSFILE 36 | python $ORGACCOUNTSPATH/orgaccounts.py -f /home/ubuntu/$ORGACCOUNTSFILE 37 | echo "offboarding-orgaccounts.yml file successfully created!" 38 | 39 | echo "Retrieving list of all IAM users across org..." 40 | echo "You will be taken into a VIM session upon completion" 41 | echo "Use the forward slash '/' to search file against IAM user(s)" 42 | read -p "Press enter to continue..." 43 | 44 | source "/home/ubuntu/c7n_org/bin/activate" 45 | c7n-org run -s output -c $ORGACCOUNTSPATH/$ORGACCOUNTSFILE -u $C7NORGPATH/offboarding-iam-users-audit.yml 46 | #c7n-org report -c $ORGACCOUNTSPATH/$ORGACCOUNTSFILE -u $C7NORGPATH/offboarding-iam-users-audit.yml -s output --region us-east-1 > /home/ubuntu/cloudcustodian/policies/c7n 47 | -org/offboarding-iam-users-audit.txt 48 | c7n-org report -c /home/ubuntu/$ORGACCOUNTSFILE -u $C7NORGPATH/offboarding-iam-users-audit.yml -s output --region all > /home/ubuntu/offboarding-iam-users-audit.txt 49 | vim /home/ubuntu/offboarding-iam-users-audit.txt 50 | echo "IAM user audit across accounts completed" 51 | echo "If you would like to see the results again, see file /home/ubuntu/offboarding-iam-users-audit.txt" 52 | echo "To get the account name to account ID mapping, see file /home/ubuntu/offboarding-orgaccounts.yml" 53 | -------------------------------------------------------------------------------- /scripts/get-iam-roleids.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # by David Lin 4 | 5 | # =========== 6 | # DESCRIPTION 7 | # =========== 8 | # This script is used to fetch all IAM RoleIds across all accounts. 9 | # 10 | # This script uses c7n-org's orgaccounts.py script to generate a yml file named 11 | # all-orgaccounts.yml which contains the list of all known AWS accounts 12 | # under the TRI org. 13 | # 14 | # The all-orgaccounts.yml file is then used by c7n-org to 15 | # search against all IAM roles and write the results to file. 16 | # 17 | # VIM is used to open the file to quickly search for IAM RoleIds and RoleNames. 18 | # 19 | # Within vim, you can use the `/` command to search against role names. 20 | # If a match is found, the account name that maps to the aws account number 21 | # can be found in the offboarding-oraccounts.yml file. 22 | 23 | # ========= 24 | # VARIABLES 25 | # ========= 26 | # |-------------------+--------------------------------------------------------------| 27 | # | Variable Name | Description | 28 | # |-------------------+--------------------------------------------------------------| 29 | # | ORG_ACCOUNTS_FILE | filename generated by c7n-org's orgaccounts.py | 30 | # | | after orgaccounts.py is invoked | 31 | # | | this file is saved in the $HOME directory for easy retrieval | 32 | # |-------------------+--------------------------------------------------------------| 33 | # | ORG_ACCOUNTS_PATH | path where c7n-org's orgaccounts.py lives | 34 | # |-------------------+--------------------------------------------------------------| 35 | # | C7N_ORG_PATH | path where the output file ourput-iam-roleids.yml is stored | 36 | # |-------------------+--------------------------------------------------------------| 37 | # | CUSTODIAN_POLICY | name of cloud custodian policy that retrieves iam roles | 38 | # |-------------------+--------------------------------------------------------------| 39 | # | REGION | AWS region | 40 | # |-------------------+--------------------------------------------------------------| 41 | 42 | ORG_ACCOUNTS_FILE="all-orgaccounts.yml" 43 | ORG_ACCOUNTS_PATH="${HOME}/cloud-custodian/tools/c7n_org/scripts" 44 | C7N_ORG_PATH="${HOME}/cloudcustodian/policies/c7n-org" 45 | CUSTODIAN_POLICY="iam-role.yml" 46 | OUTPUT_IAM_ROLEIDS="${HOME}/output-iam-roleids.txt" 47 | REGION="us-east-1" 48 | 49 | read -p "Use latest list of all accounts? [y|n]:" response 50 | 51 | if [ "${response}" = "y" ] 52 | then 53 | # ============================ 54 | # CREATE all-accounts.yml FILE 55 | # ============================ 56 | echo "Creating ${HOME}/${ORG_ACCOUNTS_FILE} file. This will take a minute..." 57 | python $ORG_ACCOUNTS_PATH/orgaccounts.py -f $HOME/$ORG_ACCOUNTS_FILE 58 | echo "${HOME}/${ORG_ACCOUNTS_FILE} successfully created!" 59 | 60 | echo "Retrieving list of all IAM roles across org..." 61 | echo "You will be taken into a VIM session upon completion" 62 | echo "Use the forward slash '/' to search file against IAM role(s)" 63 | read -p "Press enter to continue..." 64 | else 65 | echo "Using last known list of accounts..." 66 | fi 67 | 68 | 69 | # Activate c7n-org virtual environment 70 | source $HOME/c7n_org/bin/activate 71 | c7n-org run -s output -c $HOME/$ORG_ACCOUNTS_FILE -u $C7N_ORG_PATH/$CUSTODIAN_POLICY --region $REGION 72 | c7n-org report -c $HOME/$ORG_ACCOUNTS_FILE -u $C7N_ORG_PATH/$CUSTODIAN_POLICY -s output --no-default-fields --field RoleId=RoleId --field RoleName=RoleName --region us-east- 73 | 1 > $OUTPUT_IAM_ROLEIDS 74 | vim $OUTPUT_IAM_ROLEIDS 75 | 76 | echo "===================================================" 77 | echo "IAM role audit across accounts completed" 78 | echo "If you would like to see the results again, see file $OUTPUT_IAM_ROLEIDS 79 | echo "To get the role name to account ID mapping, see file $OUTPUT_IAM_ROLEIDS 80 | -------------------------------------------------------------------------------- /scripts/get-iam-userids.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # by David Lin 4 | 5 | # =========== 6 | # DESCRIPTION 7 | # =========== 8 | # This script is used to fetch all IAM user IDs across all accounts. 9 | # 10 | # This script uses c7n-org's orgaccounts.py script to generate a yml file named 11 | # all-orgaccounts.yml which contains the list of all known AWS accounts 12 | # under the TRI org. 13 | # 14 | # The all-orgaccounts.yml file is then used by c7n-org to 15 | # search against all IAM users and write the results to file. 16 | # 17 | # VIM is used to open the file to quickly search for IAM UserIds and UserIds. 18 | # 19 | # Within vim, you can use the `/` command to search against usernames. 20 | # If a match is found, the account name that maps to the aws account number 21 | # can be found in the offboarding-oraccounts.yml file. 22 | 23 | # ========= 24 | # VARIABLES 25 | # ========= 26 | # |-------------------+--------------------------------------------------------------| 27 | # | Variable Name | Description | 28 | # |-------------------+--------------------------------------------------------------| 29 | # | ORG_ACCOUNTS_FILE | filename generated by c7n-org's orgaccounts.py | 30 | # | | after orgaccounts.py is invoked | 31 | # | | this file is saved in the $HOME directory for easy retrieval | 32 | # |-------------------+--------------------------------------------------------------| 33 | # | ORG_ACCOUNTS_PATH | path where c7n-org's orgaccounts.py lives | 34 | # |-------------------+--------------------------------------------------------------| 35 | # | C7N_ORG_PATH | path where the output file iam-userids-audit.yml is stored | 36 | # |-------------------+--------------------------------------------------------------| 37 | # | CUSTODIAN_POLICY | name of cloud custodian policy that retrieves iam users | 38 | # |-------------------+--------------------------------------------------------------| 39 | # | REGION | AWS region | 40 | # |-------------------+--------------------------------------------------------------| 41 | 42 | ORG_ACCOUNTS_FILE="all-orgaccounts.yml" 43 | ORG_ACCOUNTS_PATH="${HOME}/cloud-custodian/tools/c7n_org/scripts" 44 | C7N_ORG_PATH="${HOME}/cloudcustodian/policies/c7n-org" 45 | OUTPUT_IAM_USERIDS="${HOME}/output-iam-userids.txt" 46 | CUSTODIAN_POLICY="iam-user.yml" 47 | REGION="us-east-1" 48 | 49 | read -p "Use latest list of all accounts? [y|n]:" response 50 | 51 | if [ "${response}" = "y"] 52 | then 53 | # ==================================== 54 | # CREATE LATEST all-accounts.yml FILE 55 | # ==================================== 56 | echo "Creating ${HOME}/${ORG_ACCOUNTS_FILE} file. This will take a minute..." 57 | python $ORG_ACCOUNTS_PATH/orgaccounts.py -f $HOME/$ORG_ACCOUNTS_FILE 58 | echo "${HOME}/${ORG_ACCOUNTS_FILE} successfully created!" 59 | 60 | echo "Retrieving list of all IAM users across org..." 61 | echo "You will be taken into a VIM session upon completion" 62 | echo "Use the forward slash '/' to search file against IAM user(s)" 63 | read -p "Press enter to continue..." 64 | else 65 | echo "Using last known list of accounts..." 66 | fi 67 | 68 | 69 | # Activate c7n-org virtual environment 70 | source $HOME/c7n_org/bin/activate 71 | c7n-org run -s output -c $HOME/$ORG_ACCOUNTS_FILE -u $C7N_ORG_PATH/$CUSTODIAN_POLICY --region $REGION 72 | c7n-org report -c $HOME/$ORG_ACCOUNTS_FILE -u $C7N_ORG_PATH/$CUSTODIAN_POLICY -s output --no-default-fields --field UserId=UserId --field UserName=UserName --region us-east- 73 | 1 > $OUTPUT_IAM_USERIDS 74 | vim $OUTPUT_IAM_USERIDS 75 | 76 | echo "===================================================" 77 | echo "IAM user audit across accounts completed" 78 | echo "If you would like to see the results again, see file $OUTPUT_IAM_USERIDS 79 | echo "To get the account name to account ID mapping, see file $OUTPUT_IAM_USERIDS 80 | -------------------------------------------------------------------------------- /scripts/list-custodian-schema-health-event-support.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Find aws resources that support the "health-event" filter with "issue" category 4 | # 5 | 6 | # List of services from 'custodian schema' 7 | SERVICE=account,acm-certificate,alarm,ami,app-elb,app-elb-target-group,asg,backup-plan,batch-compute,batch-definition,cache-cluster,cache-snapsho 8 | t,cache-subnet-group,cfn,cloud-directory,cloudhsm-cluster,cloudsearch,cloudtrail,codebuild,codecommit,codepipeline,config-recorder,config-rule,cu 9 | stomer-gateway,datapipeline,dax,directconnect,directory,distribution,dlm-policy,dms-endpoint,dms-instance,dynamodb-backup,dynamodb-stream,dynamod 10 | b-table,ebs,ebs-snapshot,ec2,ec2-reserved,ecr,ecs,ecs-container-instance,ecs-service,ecs-task,ecs-task-definition,efs,efs-mount-target,eks,elasti 11 | cbeanstalk,elasticbeanstalk-environment,elasticsearch,elb,emr,eni,event-rule,event-rule-target,firehose,fsx,fsx-backup,gamelift-build,gamelift-fl 12 | eet,glacier,glue-connection,glue-crawler,glue-database,glue-dev-endpoint,glue-job,glue-table,health-event,healthcheck,hostedzone,hsm,hsm-client,h 13 | sm-hapg,iam-certificate,iam-group,iam-policy,iam-profile,iam-role,iam-user,identity-pool,internet-gateway,iot,kafka,key-pair,kinesis,kinesis-anal 14 | ytics,kms,kms-key,lambda,lambda-layer,launch-config,launch-template-version,lightsail-db,lightsail-elb,lightsail-instance,log-group,message-broke 15 | r,ml-model,nat-gateway,network-acl,network-addr,ops-item,opswork-cm,opswork-stack,peering-connection,r53domain,rds,rds-cluster,rds-cluster-param- 16 | group,rds-cluster-snapshot,rds-param-group,rds-reserved,rds-snapshot,rds-subnet-group,rds-subscription,redshift,redshift-snapshot,redshift-subnet 17 | -group,rest-account,rest-api,rest-resource,rest-stage,rest-vpclink,route-table,rrset,s3,sagemaker-endpoint,sagemaker-endpoint-config,sagemaker-jo 18 | b,sagemaker-model,sagemaker-notebook,sagemaker-transform-job,secrets-manager,security-group,shield-attack,shield-protection,simpledb,snowball,sno 19 | wball-cluster,sns,sqs,ssm-activation,ssm-managed-instance,ssm-parameter,step-machine,storage-gateway,streaming-distribution,subnet,support-case,t 20 | ransit-attachment,transit-gateway,user-pool,vpc,vpc-endpoint,vpn-connection,vpn-gateway,waf,waf-regional,workspaces 21 | 22 | # Delete old result file 23 | rm result 24 | 25 | # Iterate custodian schema 26 | echo '-----------------------------------------------------------------' >> result 27 | echo 'custodian schema service_name.filters.health-event | grep issue' >> result 28 | echo '-----------------------------------------------------------------' >> result 29 | 30 | 31 | for i in $(echo $SERVICE | sed "s/,/ /g") 32 | do 33 | # Loop through the SERVICE list 34 | echo $i >> result 35 | custodian schema $i.filters.health-event | grep issue >> result 36 | echo '-----------------------------------------------------------------' >> result 37 | done 38 | -------------------------------------------------------------------------------- /scripts/report-with-user-input.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script invokes the Cloud Custodian iam-user-tagged-resources-audit.yml 4 | # policy then generates a consolidated report of AWS resources 5 | # that match the given IAM user specified by the Owner tag. 6 | # 7 | # To change the owner, find/replace the IAM user in 8 | # iam-user-tagged-resource.audit.yml. 9 | # 10 | # By default, the policy is invoked in us-east-1. 11 | # The region can be modified by changing the value of variable 'REGION'. 12 | # 13 | # Upon completion, the consolidated report can be found here: 14 | # /home/ubuntu/cloudcustodian/policies/report.xt 15 | # 16 | 17 | # Variables 18 | RESOURCE=ebs,ebs-snapshot,security-group,s3,ami,dynamodb-table,dynamodb-stream,dynamodb-backup,elasticsearch,elb,eni,lambda,lambda-layer,rds,s3,sqs,sns,cfn 19 | REGION="--region us-east-1" 20 | CUSTODIAN_POLICY="/home/ubuntu/cloudcustodian/policies/iam-user-tagged-resources-audit.yml" 21 | CUSTODIAN_OUTPUT_DIRECTORY="/home/ubuntu/cloudcustodian/policies/output" 22 | CUSTODIAN_REPORT="/home/ubuntu/cloudcustodian/policies/report.txt" 23 | 24 | # User input 25 | read -p "Enter AWS username: " aws_username 26 | read -p "Enter GHE username: " ghe_username 27 | read -s -p "Enter GHE password: " ghe_password 28 | 29 | # Activate c7n virtual environment 30 | cd /home/ubuntu 31 | source c7n_mailer/bin/activate 32 | 33 | # Clear c7n cache 34 | echo '------------------' 35 | echo 'Clearing c7n cache ' 36 | echo '------------------' 37 | rm /home/ubuntu/.cache/cloud-custodian.cache 38 | echo '~/.cachecloud-custodian.cache cleared' 39 | 40 | # Invoke c7n policy 41 | echo '-------------------' 42 | echo 'Invoking c7n policy' 43 | echo '-------------------' 44 | custodian run -s $CUSTODIAN_OUTPUT_DIRECTORY $CUSTODIAN_POLICY $REGION 45 | 46 | # Generate c7n reports 47 | echo '-------------------------------' 48 | echo 'Generating report for resources' 49 | echo '-------------------------------' 50 | 51 | # Write ec2 report to file 52 | echo 'ec2' 53 | echo 'ec2' > $CUSTODIAN_REPORT 54 | custodian report -s $CUSTODIAN_OUTPUT_DIRECTORY -t ec2 $CUSTODIAN_POLICY --field tag:Owner=tag:Owner --format grid >> $CUSTODIAN_REPORT 55 | echo ' ' >> $CUSTODIAN_REPORT 56 | 57 | # Append more resources to file 58 | for i in $(echo $RESOURCE | sed "s/,/ /g") 59 | do 60 | # Loop through the RESOURCE list 61 | echo $i 62 | echo $i >> $CUSTODIAN_REPORT 63 | custodian report -s $CUSTODIAN_OUTPUT_DIRECTORY -t $i $CUSTODIAN_POLICY --field tag:Owner=tag:Owner --format grid >> $CUSTODIAN_REPORT 64 | echo ' ' >> $CUSTODIAN_REPORT 65 | done 66 | 67 | echo '' 68 | echo '-------------------------------' 69 | echo 'Report' 70 | echo '-------------------------------' 71 | #more $CUSTODIAN_REPORT 72 | 73 | echo 'Copy report.txt to ~/offboarding' 74 | DATE=`date +%Y-%m-%d` 75 | cp /home/ubuntu/cloudcustodian/policies/report.txt /home/ubuntu/offboarding-aws-audit/$DATE-$aws_username-'report' 76 | 77 | echo '------------------------------------------------' 78 | echo 'Push report.txt to IE/offboarding-aws-audit repo' 79 | echo '------------------------------------------------' 80 | cd /home/ubuntu/offboarding-aws-audit/ 81 | git pull https://$ghe_username:$ghe_password@github.awsinternal.tri.global/IE/offboarding-aws-audit 82 | git add /home/ubuntu/offboarding-aws-audit/$DATE-$aws_username-'report' 83 | git commit -m 'AWS audit report' 84 | git push https://$ghe_username:$ghe_password@github.awsinternal.tri.global/IE/offboarding-aws-audit 85 | 86 | echo '' 87 | echo 'Report committed to IE/offboarding-aws-audit repo ' 88 | echo 'Local copy here /home/ubuntu/cloudcustodian/policies/report.txt' 89 | echo 'Report completed! 90 | -------------------------------------------------------------------------------- /scripts/report.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script invokes the Cloud Custodian iam-user-tagged-resources-audit.yml 4 | # policy then generates a consolidated report of AWS resources 5 | # that match the given IAM user specified by the Owner tag. 6 | # 7 | # To change the owner, find/replace the IAM user in 8 | # iam-user-tagged-resource.audit.yml. 9 | # 10 | # By default, the policy is invoked in us-east-1. 11 | # The region can be modified by changing the value of variable 'REGION'. 12 | # 13 | # Upon completion, the consolidated report can be found here: 14 | # /home/ubuntu/cloudcustodian/policies/report.txt 15 | # 16 | 17 | # Variables 18 | RESOURCE=ebs,ebs-snapshot,security-group,s3,ami,dynamodb-table,dynamodb-stream,dynamodb-backup,elasticsearch,elb,eni,lambda,lambda-layer,rds,s3,sqs,sns,cfn 19 | REGION="--region us-east-1" 20 | CUSTODIAN_POLICY="/home/ubuntu/cloudcustodian/policies/iam-user-tagged-resources-audit.yml" 21 | CUSTODIAN_OUTPUT_DIRECTORY="/home/ubuntu/cloudcustodian/policies/output" 22 | CUSTODIAN_REPORT="/home/ubuntu/cloudcustodian/policies/report.txt" 23 | 24 | # Activate c7n virtual environment 25 | cd /home/ubuntu 26 | source c7n_mailer/bin/activate 27 | 28 | # Clear c7n cache 29 | echo '------------------' 30 | echo 'Clearing c7n cache ' 31 | echo '------------------' 32 | rm /home/ubuntu/.cache/cloud-custodian.cache 33 | echo '~/.cachecloud-custodian.cache cleared' 34 | 35 | # Invoke c7n policy 36 | echo '-------------------' 37 | echo 'Invoking c7n policy' 38 | echo '-------------------' 39 | custodian run -s $CUSTODIAN_OUTPUT_DIRECTORY $CUSTODIAN_POLICY $REGION 40 | 41 | # Generate c7n reports 42 | echo '-------------------------------' 43 | echo 'Generating report for resources' 44 | echo '-------------------------------' 45 | 46 | # Write ec2 report to file 47 | echo 'ec2' 48 | echo 'ec2' > $CUSTODIAN_REPORT 49 | custodian report -s $CUSTODIAN_OUTPUT_DIRECTORY -t ec2 $CUSTODIAN_POLICY --field tag:Owner=tag:Owner --format grid >> $CUSTODIAN_REPORT 50 | echo ' ' >> $CUSTODIAN_REPORT 51 | 52 | # Append more resources to file 53 | for i in $(echo $RESOURCE | sed "s/,/ /g") 54 | do 55 | # Loop through the RESOURCE list 56 | echo $i 57 | echo $i >> $CUSTODIAN_REPORT 58 | custodian report -s $CUSTODIAN_OUTPUT_DIRECTORY -t $i $CUSTODIAN_POLICY --field tag:Owner=tag:Owner --format grid >> $CUSTODIAN_REPORT 59 | echo ' ' >> $CUSTODIAN_REPORT 60 | done 61 | 62 | echo '' 63 | echo '-------------------------------' 64 | echo 'Report' 65 | echo '-------------------------------' 66 | more $CUSTODIAN_REPORT 67 | 68 | echo '' 69 | echo 'Report completed! ' 70 | echo 'See /home/ubuntu/cloudcustodian/policies/report.txt' 71 | -------------------------------------------------------------------------------- /scripts/report_with_user_inputs_and_auto_commit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script invokes the Cloud Custodian iam-user-tagged-resources-audit.yml 4 | # policy then generates a consolidated report of AWS resources 5 | # that match the given IAM user specified by the Owner tag. 6 | # 7 | # To change the owner, find/replace the IAM user in 8 | # iam-user-tagged-resource.audit.yml. 9 | # 10 | # By default, the policy is invoked in us-east-1. 11 | # The region can be modified by changing the value of variable 'REGION'. 12 | # 13 | # Upon completion, the consolidated report can be found here: 14 | # /home/ubuntu/cloudcustodian/policies/report.xt 15 | # 16 | 17 | # Variables 18 | RESOURCE=ebs,ebs-snapshot,security-group,s3,ami,dynamodb-table,dynamodb-stream,dynamodb-backup,elasticsearch,elb,eni,lambda,lambda-layer,rds,s3,sqs,sns,cfn 19 | REGION="--region us-east-1" 20 | CUSTODIAN_POLICY="/home/ubuntu/cloudcustodian/policies/iam-user-tagged-resources-audit.yml" 21 | CUSTODIAN_OUTPUT_DIRECTORY="/home/ubuntu/cloudcustodian/policies/output" 22 | CUSTODIAN_REPORT="/home/ubuntu/cloudcustodian/policies/report.txt" 23 | 24 | # User input 25 | read -p "Enter AWS username: " aws_username 26 | read -p "Enter GHE username: " ghe_username 27 | read -s -p "Enter GHE password: " ghe_password 28 | 29 | # Activate c7n virtual environment 30 | cd /home/ubuntu 31 | source c7n_mailer/bin/activate 32 | 33 | # Clear c7n cache 34 | echo '------------------' 35 | echo 'Clearing c7n cache ' 36 | echo '------------------' 37 | rm /home/ubuntu/.cache/cloud-custodian.cache 38 | echo '~/.cachecloud-custodian.cache cleared' 39 | 40 | # Invoke c7n policy 41 | echo '-------------------' 42 | echo 'Invoking c7n policy' 43 | echo '-------------------' 44 | custodian run -s $CUSTODIAN_OUTPUT_DIRECTORY $CUSTODIAN_POLICY $REGION 45 | 46 | # Generate c7n reports 47 | echo '-------------------------------' 48 | echo 'Generating report for resources' 49 | echo '-------------------------------' 50 | 51 | # Write ec2 report to file 52 | echo 'ec2' 53 | echo 'ec2' > $CUSTODIAN_REPORT 54 | custodian report -s $CUSTODIAN_OUTPUT_DIRECTORY -t ec2 $CUSTODIAN_POLICY --field tag:Owner=tag:Owner --format grid >> $CUSTODIAN_REPORT 55 | echo ' ' >> $CUSTODIAN_REPORT 56 | 57 | # Append more resources to file 58 | for i in $(echo $RESOURCE | sed "s/,/ /g") 59 | do 60 | # Loop through the RESOURCE list 61 | echo $i 62 | echo $i >> $CUSTODIAN_REPORT 63 | custodian report -s $CUSTODIAN_OUTPUT_DIRECTORY -t $i $CUSTODIAN_POLICY --field tag:Owner=tag:Owner --format grid >> $CUSTODIAN_REPORT 64 | echo ' ' >> $CUSTODIAN_REPORT 65 | done 66 | 67 | echo '' 68 | echo '-------------------------------' 69 | echo 'Report' 70 | echo '-------------------------------' 71 | #more $CUSTODIAN_REPORT 72 | 73 | echo 'Copy report.txt to ~/offboarding' 74 | DATE=`date +%Y-%m-%d` 75 | cp /home/ubuntu/cloudcustodian/policies/report.txt /home/ubuntu/offboarding-aws-audit/$DATE-$aws_username-'report' 76 | 77 | echo '------------------------------------------------' 78 | echo 'Push report.txt to IE/offboarding-aws-audit repo' 79 | echo '------------------------------------------------' 80 | cd /home/ubuntu/offboarding-aws-audit/ 81 | git pull https://$ghe_username:$ghe_password@github.awsinternal.tri.global/IE/offboarding-aws-audit 82 | git add /home/ubuntu/offboarding-aws-audit/$DATE-$aws_username-'report' 83 | git commit -m 'AWS audit report' 84 | git push https://$ghe_username:$ghe_password@github.awsinternal.tri.global/IE/offboarding-aws-audit 85 | 86 | echo '' 87 | echo 'Report completed! ' 88 | echo 'See /home/ubuntu/cloudcustodian/policies/report.txt' 89 | -------------------------------------------------------------------------------- /update-mailer-lambda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | c7n-mailer --config /home/ubuntu/cloudcustodian/mailer.yml --update-lambda 3 | --------------------------------------------------------------------------------