├── .gitignore ├── BSP_Mode_1 ├── mode1_tags_long.yml └── mode1_tags_short.yml ├── Jenkinsfile ├── LICENSE.md ├── Makefile ├── README.md ├── accounts.yml ├── policies ├── compliance │ ├── asg.yml │ ├── ebs.yml │ ├── ec2.yml │ ├── elb.yml │ ├── iam.yml │ ├── rds.yml │ └── s3.yml └── operational │ ├── asg.yml │ ├── ebs.yml │ ├── ec2.yml │ ├── elb.yml │ ├── iam.yml │ ├── rds.yml │ └── s3.yml └── test.yml /.gitignore: -------------------------------------------------------------------------------- 1 | custodian 2 | 3 | out -------------------------------------------------------------------------------- /BSP_Mode_1/mode1_tags_long.yml: -------------------------------------------------------------------------------- 1 | vars: 2 | tag-filters: &tag-compliance-filters 3 | - "tag:Application Type": absent 4 | - "tag:Backups Required": absent 5 | - "tag:Customer": absent 6 | - "tag:Environment": absent 7 | - "tag:FISMA System": absent 8 | - "tag:GSA Tenant": absent 9 | - "tag:AWS Instance Type": absent 10 | - "tag:Os Type": absent 11 | - "tag:Responsible SSO": absent 12 | 13 | policies: 14 | - name: tag-compliance 15 | resource: ec2 16 | filters: 17 | - or: *tag-compliance-filters 18 | actions: 19 | - type: notify 20 | from: {{ from_address }} 21 | to: {{ to_addresses }} 22 | subject: "Missing Required Tags" 23 | template: default 24 | transport: 25 | type: sns 26 | topic: {{ topic_arn }} 27 | -------------------------------------------------------------------------------- /BSP_Mode_1/mode1_tags_short.yml: -------------------------------------------------------------------------------- 1 | vars: 2 | tag-filters: &tag-compliance-filters 3 | - "tag:app_type": absent 4 | - "tag:backups": absent 5 | - "tag:customer": absent 6 | - "tag:environment": absent 7 | - "tag:fisma": absent 8 | - "tag:gsa_tenant": absent 9 | - "tag:instance_type": absent 10 | - "tag:ostype": absent 11 | - "tag:sso": absent 12 | 13 | policies: 14 | - name: tag-compliance 15 | resource: ec2 16 | filters: 17 | - or: *tag-compliance-filters 18 | actions: 19 | - type: notify 20 | from: {{ from_address }} 21 | to: {{ to_addresses }} 22 | subject: "Missing Required Tags" 23 | template: default 24 | transport: 25 | type: sns 26 | topic: {{ topic_arn }} 27 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/devsecops-cloud-custodian-rules/aad30c801e681fca3e33ed1f28d4aa6e54f1c153/Jenkinsfile -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | As a work of the United States Government, this project is in the 2 | public domain within the United States. 3 | 4 | Additionally, we waive copyright and related rights in the work 5 | worldwide through the CC0 1.0 Universal public domain dedication. 6 | 7 | ## CC0 1.0 Universal Summary 8 | 9 | This is a human-readable summary of the [Legal Code (read the full text)](https://creativecommons.org/publicdomain/zero/1.0/legalcode). 10 | 11 | ### No Copyright 12 | 13 | The person who associated a work with this deed has dedicated the work to 14 | the public domain by waiving all of his or her rights to the work worldwide 15 | under copyright law, including all related and neighboring rights, to the 16 | extent allowed by law. 17 | 18 | You can copy, modify, distribute and perform the work, even for commercial 19 | purposes, all without asking permission. 20 | 21 | ### Other Information 22 | 23 | In no way are the patent or trademark rights of any person affected by CC0, 24 | nor are the rights that other persons may have in the work or in how the 25 | work is used, such as publicity or privacy rights. 26 | 27 | Unless expressly stated otherwise, the person who associated a work with 28 | this deed makes no warranties about the work, and disclaims liability for 29 | all uses of the work, to the fullest extent permitted by applicable law. 30 | When using or citing the work, you should not imply endorsement by the 31 | author or the affirmer. 32 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/devsecops-cloud-custodian-rules/aad30c801e681fca3e33ed1f28d4aa6e54f1c153/Makefile -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # devsecops-cloud-custodian-rules 2 | A repo containing rule sets for cloud-custodian inside GSA AWS accounts. This repo does not contain cloud-custodian itself. 3 | 4 | ## What is this 5 | Cloud Custodian is a tool that unifies the dozens of tools and scripts most organizations use for managing their AWS 6 | accounts into one open source tool. It’s a stateless rules engine for policy definition and enforcement, with metrics and reporting for AWS. 7 | 8 | http://www.capitalone.io/cloud-custodian/docs/ 9 | https://github.com/capitalone/cloud-custodian 10 | 11 | ## Whats here 12 | see `/policies/operational` for rules that take actions (i.e. stop/start instances, block creation of non-compliant resources, automate encryption/backups) 13 | see `/policies/compliance` for rules that verify compliance (i.e. users w/ console access have MFA enabled, resources are tag appropriate, check that encryption/backups are configured) 14 | 15 | ## Use Cases 16 | Cost Savings: 17 | * Resource Off Hours: Easy way to cut expenses by turning on/off resources on a automated schedule. 18 | * Resource Resizing: Ability to automatically resize resources based on metrics over time. 19 | * Garbage Collection: Automatic notifications and removal of stale and unused resources. 20 | 21 | Compliance: 22 | * Encryption: Verify and enforce encryption across numerous resources. 23 | * Backups: Performs automated snapshots of servers and databases. 24 | * Tag Enforcement: Proper tags are necessary for resource support and tracking. 25 | * Security: Puts up automated safeguards to detect, remediate, and notify customers of non-compliant actions 26 | * Standards: Ensure certain standards are used with consistency across all managed AWS accounts. 27 | 28 | Examples: 29 | * Verifies CloudTrail Logging is enabled and configured properly 30 | * Verifies Network Logging is enabled and configured properly 31 | * Verifies Root user’s access keys have been deleted 32 | * Verifies MFA Token has been applied to Root user 33 | * Verifies proper IAM password policy is enforced for users 34 | 35 | ## Getting Started 36 | Cloud custodian requires [python, pip, virtualenv](https://virtualenv.pypa.io/en/stable/installation/) on client machine or [with docker using `docker exec` or `docker run`](https://github.com/capitalone/cloud-custodian/blob/master/Dockerfile) 37 | 38 | ``` 39 | $ virtualenv --python=python2 custodian 40 | $ source custodian/bin/activate 41 | (custodian) $ pip install c7n aws-cli 42 | (custodian) $ aws-cli configure 43 | 44 | # Validate the configuration 45 | $ custodian validate test.yml 46 | 47 | # Perform a dryrun on the policies (no actions executed) to see what would change 48 | $ custodian run --dryrun -s out test.yml 49 | 50 | # Run the policy 51 | $ custodian run -s out some/policy.yml 52 | ``` 53 | >Note - you can create an IAM user/roles with using `security audit` role if you are only using rules under `policies/compliance` 54 | if you plan to use Cloud Custodian to enforce rules as lambda functions from Cloudtrial or perform actions on resources (e.g. turn on encyrption/backups, resize/start/stop resources that IAM will need `FullAccess` for those resources using least-priviledge principles for only those resources managed by Cloud Custodian) 55 | 56 | ## Concepts 57 | ``` 58 | name: Name for the policy 59 | resource: Which resource type to check (ec2, rds, ebs, etc 100+) 60 | description: | 61 | Brief statement of what the policy does 62 | mode: How the policy will be executed (event(API Triggered), periodic(Cron Scheduled), config(Config Change Triggered), no mode for manual runs) 63 | - filters: Narrow down resource matches with 1 or more of these (See filters below) 64 | - actions: What to do with the resulting resource set found. (notify by email/sns/webhook or perform an operation `mark-for-op` stop, start, terminate, tag, resize, etc) 65 | ``` 66 | 67 | ## Filters 68 | 69 | * Operator matching (in, not-in, absent, not-null, gte, regex, etc) 70 | * Arbitrary nesting of filters with ‘or’ and ‘and’ blocks. 71 | * Simple key/value are equality matches with value expressions 72 | 73 | `regex` fliters use Jmespath expressions: http://jmespath.org/ 74 | -------------------------------------------------------------------------------- /accounts.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/devsecops-cloud-custodian-rules/aad30c801e681fca3e33ed1f28d4aa6e54f1c153/accounts.yml -------------------------------------------------------------------------------- /policies/compliance/asg.yml: -------------------------------------------------------------------------------- 1 | # Auto Scaling Group Policies 2 | policies: 3 | 4 | #################################### 5 | ##### Compliance Policies ##### 6 | #################################### 7 | 8 | - name: asg-older-image 9 | resource: asg 10 | comment: Look for any auto scaling groups using AMIs older than 30 days 11 | filters: 12 | - type: image-age 13 | days: 30 -------------------------------------------------------------------------------- /policies/compliance/ebs.yml: -------------------------------------------------------------------------------- 1 | # Elastic Block Storage (EBS) Policies 2 | policies: 3 | 4 | #################################### 5 | ##### Compliance Policies ##### 6 | #################################### 7 | 8 | - name: ebs-instance-without-encryption-at-rest 9 | description: Instances without encrypted EBS volumes 10 | resource: ebs 11 | filters: 12 | - Encrypted: false 13 | - "State.Name": running -------------------------------------------------------------------------------- /policies/compliance/ec2.yml: -------------------------------------------------------------------------------- 1 | # Elastic Compute Cloud (EC2) Policies 2 | policies: 3 | 4 | #################################### 5 | ##### Compliance Policies ##### 6 | #################################### 7 | 8 | - name: ec2-auto-tag-user-who-created-instance 9 | resource: ec2 10 | description: | 11 | Tag any new instance with the 12 | Creators ID and Principle ID. 13 | mode: 14 | type: cloudtrail 15 | events: 16 | - RunInstances 17 | filters: 18 | - tag:CreatorName: absent 19 | actions: 20 | - type: auto-tag-user 21 | tag: Resource Contact 22 | principal_id_tag: CreatorId 23 | 24 | - name: ec2-organization-tag-compliance 25 | resource: ec2 26 | comment: Report on total count of non compliant instances 27 | filters: 28 | - or: 29 | - "tag:Name": absent 30 | - "tag:Managed_by": absent 31 | - "tag:Environment": absent 32 | - not: 33 | - "State.Name": terminated -------------------------------------------------------------------------------- /policies/compliance/elb.yml: -------------------------------------------------------------------------------- 1 | # Elastic/Application Load Balencers (ELB/ALB) Policies 2 | policies: 3 | 4 | #################################### 5 | ##### Compliance Policies ##### 6 | #################################### 7 | - name: elb-tls-whitelist 8 | description: | 9 | HTTPS/SSL ELBs should only have whitelisted ciphers/protocols 10 | resource: elb 11 | mode: 12 | type: cloudtrail 13 | events: 14 | - CreateLoadBalancer 15 | - CreateLoadBalancerPolicy 16 | - SetLoadBalancerPoliciesOfListener 17 | filters: 18 | - type: ssl-policy 19 | whitelist: &POLICY 20 | - Protocol-TLSv1 21 | - Protocol-TLSv1.1 22 | - Protocol-TLSv1.2 23 | actions: 24 | - type: set-ssl-listener-policy 25 | name: CustodianEnforcedPolicy 26 | attributes: *POLICY -------------------------------------------------------------------------------- /policies/compliance/iam.yml: -------------------------------------------------------------------------------- 1 | # Identity and Access Management (IAM) Policies 2 | policies: 3 | 4 | #################################### 5 | ##### Compliance Policies ##### 6 | #################################### 7 | 8 | - name: iam-sgs-with-ingress-or-egress-with-default-groupname 9 | resource: security-group 10 | filters: 11 | - type: value 12 | key: GroupName 13 | op: eq 14 | value: "default" 15 | - or: 16 | - type: value 17 | key: IpPermissions 18 | value: not-null 19 | - type: value 20 | key: IpPermissionsEgress 21 | value: not-null 22 | actions: 23 | - type: notify 24 | to: 25 | - foo@bar.gov #required even though not needed in SNS 26 | message: "Some sort of message" 27 | transport: 28 | type: sns 29 | topic: arn:aws:sns:us-east-1:111111111:topic-ops 30 | 31 | - name: iam-password-policy-check 32 | resource: account 33 | description: Verifies password policy on account meets our requirements and notifies if not 34 | region: us-east-1 35 | filters: 36 | - type: password-policy 37 | key: MinimumPasswordLength 38 | value: 14 39 | op: less-than 40 | - type: password-policy 41 | key: RequireSymbols 42 | value: false 43 | - type: password-policy 44 | key: RequireNumbers 45 | value: false 46 | - type: password-policy 47 | key: RequireUppercaseCharacters 48 | value: false 49 | - type: password-policy 50 | key: RequireLowercaseCharacters 51 | value: false 52 | - type: password-policy 53 | key: PasswordReusePrevention 54 | value: 2 55 | op: less-than 56 | - type: password-policy 57 | key: MaxPasswordAge 58 | value: 90 59 | op: less-than 60 | - type: password-policy 61 | key: ExpirePasswords 62 | value: false 63 | - type: password-policy 64 | key: HardExpiry 65 | value: false -------------------------------------------------------------------------------- /policies/compliance/rds.yml: -------------------------------------------------------------------------------- 1 | # Rational Database Service (RDS) Policies 2 | 3 | policies: 4 | 5 | #################################### 6 | ##### Compliance Policies ##### 7 | #################################### 8 | -------------------------------------------------------------------------------- /policies/compliance/s3.yml: -------------------------------------------------------------------------------- 1 | # Simple Storage Service (s3) Policies 2 | 3 | policies: 4 | 5 | #################################### 6 | ##### Compliance Policies ##### 7 | #################################### -------------------------------------------------------------------------------- /policies/operational/asg.yml: -------------------------------------------------------------------------------- 1 | # Auto Scaling Group Policies 2 | policies: 3 | 4 | ###################################### 5 | ##### Operational Policies ###### 6 | ###################################### -------------------------------------------------------------------------------- /policies/operational/ebs.yml: -------------------------------------------------------------------------------- 1 | # Elastic Block Storage (EBS) Policies 2 | policies: 3 | 4 | ###################################### 5 | ##### Operational Policies ###### 6 | ###################################### 7 | - name: ebs-terminate-unencrypted-upon-creation 8 | description: | 9 | Terminate all unencrypted EBS volumes upon creation 10 | resource: ebs 11 | mode: 12 | type: cloudtrail 13 | events: 14 | - CreateVolume 15 | filters: 16 | - Encrypted: false 17 | actions: 18 | - delete 19 | 20 | - name: ebs-copy-instance-tags-from-mounted-ec2 21 | resource: ebs 22 | filters: 23 | - type: value 24 | key: "Attachments[0].Device" 25 | value: not-null 26 | actions: 27 | - type: copy-instance-tags 28 | tags: 29 | - App 30 | - Env 31 | - Owner 32 | - Name 33 | 34 | - name: ebs-mark-unattached-deletion-for-op 35 | resource: ebs 36 | comments: | 37 | Mark any unattached EBS volumes for deletion in 30 days. 38 | Volumes set to not delete on instance termination do have 39 | valid use cases as data drives, but 99% of the time they 40 | appear to be just garbage creation. 41 | filters: 42 | - Attachments: [] 43 | - "tag:maid_status": absent 44 | actions: 45 | - type: mark-for-op 46 | op: delete 47 | days: 30 48 | 49 | - name: ebs-unmark-attached-deletion 50 | resource: ebs 51 | comments: | 52 | Unmark any attached EBS volumes that were scheduled for deletion 53 | if they are currently attached 54 | filters: 55 | - type: value 56 | key: "Attachments[0].Device" 57 | value: not-null 58 | - "tag:maid_status": not-null 59 | actions: 60 | - unmark 61 | 62 | - name: ebs-delete-marked 63 | resource: ebs 64 | comments: | 65 | Delete any attached EBS volumes that were scheduled for deletion 66 | filters: 67 | - type: marked-for-op 68 | op: delete 69 | actions: 70 | - delete -------------------------------------------------------------------------------- /policies/operational/ec2.yml: -------------------------------------------------------------------------------- 1 | # Elastic Compute Cloud (EC2) Policies 2 | policies: 3 | 4 | ###################################### 5 | ##### Operational Policies ###### 6 | ###################################### 7 | 8 | - name: ec2-destroy-tag-stagingORdev-after-x-days 9 | resource: ec2 10 | comment: Report dev or staging instances not terminated within 7 days 11 | filters: 12 | - type: value 13 | key: "tag:Name" 14 | op: glob 15 | value: 16 | - "*staging*" 17 | - "*dev*" 18 | - type: instance-age 19 | hours: 7 20 | actions: 21 | - type: mark-for-op 22 | op: stop 23 | days: 1 24 | 25 | - name: ec2-stop-tag-packer-after-x-days 26 | resource: ec2 27 | comment: Report to find long running packer instances 28 | filters: 29 | - type: value 30 | key: "tag:Name" 31 | op: regex 32 | value: "^packer*" 33 | - type: instance-age 34 | hours: 3 35 | 36 | - name: ec2-stop-instances-with-cleanup-tag 37 | resource: ec2 38 | filters: 39 | - "tag:Cleanup": present 40 | actions: 41 | - stop -------------------------------------------------------------------------------- /policies/operational/elb.yml: -------------------------------------------------------------------------------- 1 | # Elastic/Application Load Balencers (ELB/ALB) Policies 2 | policies: 3 | 4 | ###################################### 5 | ##### Operational Policies ###### 6 | ###################################### -------------------------------------------------------------------------------- /policies/operational/iam.yml: -------------------------------------------------------------------------------- 1 | # Identity and Access Management (IAM) Policies 2 | policies: 3 | 4 | ###################################### 5 | ##### Operational Policies ###### 6 | ###################################### 7 | 8 | - name: iam-password-policy-check 9 | resource: account 10 | description: Verifies password policy on account meets our requirements and notifies if not 11 | region: us-east-1 12 | filters: 13 | - type: password-policy 14 | key: MinimumPasswordLength 15 | value: 14 16 | op: less-than 17 | - type: password-policy 18 | key: RequireSymbols 19 | value: false 20 | - type: password-policy 21 | key: RequireNumbers 22 | value: false 23 | - type: password-policy 24 | key: RequireUppercaseCharacters 25 | value: false 26 | - type: password-policy 27 | key: RequireLowercaseCharacters 28 | value: false 29 | - type: password-policy 30 | key: PasswordReusePrevention 31 | value: 2 32 | op: less-than 33 | - type: password-policy 34 | key: MaxPasswordAge 35 | value: 90 36 | op: less-than 37 | - type: password-policy 38 | key: ExpirePasswords 39 | value: false 40 | - type: password-policy 41 | key: HardExpiry 42 | value: false -------------------------------------------------------------------------------- /policies/operational/rds.yml: -------------------------------------------------------------------------------- 1 | # Rational Database Service (RDS) Policies 2 | 3 | policies: 4 | 5 | ##################################### 6 | ##### Operational Policies ##### 7 | ##################################### 8 | 9 | - name: rds-terminate-unencrypted-public 10 | description: | 11 | Terminate all unencrypted or publicly available RDS upon creation 12 | resource: rds 13 | mode: 14 | type: cloudtrail 15 | events: 16 | - CreateDBInstance 17 | filters: 18 | - or: 19 | - StorageEncrypted: false 20 | - PubliclyAccessible: true 21 | actions: 22 | - type: delete 23 | skip-snapshot: true 24 | 25 | - name: rds-prod-multi-az-remediate 26 | resource: rds 27 | description: | 28 | Notify on all Prod RDS Instances that are Not Multi AZ setup. 29 | mode: 30 | type: cloudtrail 31 | events: 32 | - source: rds.amazonaws.com 33 | event: CreateDBInstance 34 | ids: "requestParameters.dBInstanceIdentifier" 35 | filters: 36 | - type: value 37 | key: 'tag:Environment' 38 | value: '^prod' 39 | op: regex 40 | - MultiAZ: false 41 | #actions: 42 | -------------------------------------------------------------------------------- /policies/operational/s3.yml: -------------------------------------------------------------------------------- 1 | # Simple Storage Service (s3) Policies 2 | 3 | policies: 4 | 5 | ##################################### 6 | ##### Operational Policies ##### 7 | ##################################### 8 | - name: s3-require-encryption 9 | resource: s3 10 | description: Apply encryption required policy to new buckets 11 | mode: 12 | type: cloudtrail 13 | events: 14 | - CreateBucket 15 | actions: 16 | - encryption-policy 17 | - encrypt-keys 18 | 19 | - name: s3-remediate 20 | resource: s3 21 | description: Encryption required policy 22 | mode: 23 | type: periodic 24 | schedule: rate(1 day) 25 | filters: 26 | - type: is-log-target 27 | actions: 28 | - attach-encrypt 29 | - type: remove-statements 30 | statement_ids: 31 | - RequireEncryptedPutObject -------------------------------------------------------------------------------- /test.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | - name: remediate-extant-keys 3 | description: | 4 | Scan through all s3 buckets in an account and ensure all objects 5 | are encrypted (default to AES256). 6 | resource: s3 7 | actions: 8 | - encrypt-keys 9 | 10 | - name: ec2-require-non-public-and-encrypted-volumes 11 | resource: ec2 12 | description: | 13 | Provision a lambda and cloud watch event target 14 | that looks at all new instances and terminates those with 15 | unencrypted volumes. 16 | mode: 17 | type: cloudtrail 18 | events: 19 | - RunInstances 20 | filters: 21 | - type: ebs 22 | key: Encrypted 23 | value: false 24 | actions: 25 | - stop --------------------------------------------------------------------------------