Skip to content

Instantly share code, notes, and snippets.

@asvinours
Last active September 16, 2025 12:26
Show Gist options
  • Select an option

  • Save asvinours/34841e7fa5b02434f30df7f7b389b13b to your computer and use it in GitHub Desktop.

Select an option

Save asvinours/34841e7fa5b02434f30df7f7b389b13b to your computer and use it in GitHub Desktop.
Base cloud-custodian policy file
policies:
- name: rds-instance-encryption-disabled
description: Account {account_id} - Detect RDS instances that do not have storage encryption enabled
resource: rds
filters:
- type: value
key: StorageEncrypted
value: false
- name: rds-instance-publicly-accessible
description: Account {account_id} - Detect RDS instances that are publicly accessible
resource: rds
filters:
- type: value
key: PubliclyAccessible
value: true
- name: rds-cluster-encryption-disabled
description: Account {account_id} - Detect RDS clusters that do not have storage encryption enabled
resource: rds-cluster
filters:
- type: value
key: StorageEncrypted
value: false
- name: rds-cluster-publicly-accessible
description: Account {account_id} - Detect RDS clusters that are publicly accessible
resource: rds-cluster
filters:
- type: value
key: PubliclyAccessible
value: true
- name: redshift-cluster-tls-ssl-disabled
description: Account {account_id} - Detect Redshift clusters that do not enforce TLS/SSL connections
resource: redshift
filters:
- type: param
key: require_ssl
value: false
op: eq
- name: redis-are-in-transit-encrypted
description: Account {account_id} - Detect ElastiCache Redis replication groups without in-transit encryption enabled
resource: elasticache-group
filters:
- type: value
key: TransitEncryptionEnabled
value: true
op: not-equal
- name: redis-clusters-are-encrypted-at-rest
description: Account {account_id} - Detect ElastiCache Redis replication groups without encryption at rest enabled
resource: elasticache-group
filters:
- type: value
key: AtRestEncryptionEnabled
value: true
op: not-equal
- name: ebs-encryption-disabled
description: Account {account_id} - Detect EBS volumes that are not encrypted
resource: ebs
filters:
- type: value
key: Encrypted
value: false
- name: efs-encryption-disabled
description: Account {account_id} - Detect EFS file systems that are not encrypted at rest
resource: efs
filters:
- type: value
key: Encrypted
value: false
- name: sns-encrypted-at-rest
description: Account {account_id} - SNS topics should be encrypted at rest using AWS KMS
resource: aws.sns
filters:
- KmsMasterKeyId: absent
- name: sns-topic-publicly-accessible
resource: aws.sns
description: Account {account_id} - SNS topics should not allow public access
filters:
- type: cross-account
everyone_only: true
- name: sqs-queue-publicly-accessible
resource: aws.sqs
description: Account {account_id} - SQS queues should not allow public access
filters:
- type: cross-account
everyone_only: true
- name: alb-http2-not-enabled
description: Account {account_id} - Detect Application Load Balancers that do not have HTTP/2 enabled
resource: app-elb
filters:
- type: value
key: Type
value: application
- type: attributes
key: routing.http2.enabled
op: not-equal
value: true
- name: nlb-cross-zone-not-enabled
description: Account {account_id} - Detect Network Load Balancers that do not have cross-zone load balancing enabled
resource: app-elb
filters:
- type: value
key: Type
value: network
- type: attributes
key: load_balancing.cross_zone.enabled
op: not-equal
value: true
- name: elbv2-enabled-drop-http-headers
description: Account {account_id} - Detect Application Load Balancers that do not drop invalid HTTP headers
resource: app-elb
filters:
- type: attributes
key: "routing.http.drop_invalid_header_fields.enabled"
value: false
- name: app-elb-invalid-ssl-policy
description: Account {account_id} - Detect Application Load Balancers using insecure or outdated SSL policies
resource: app-elb
filters:
- type: listener
key: Protocol
value: HTTPS
- type: listener
key: SslPolicy
op: not-in
value:
- ELBSecurityPolicy-TLS13-1-3-2021-06
- ELBSecurityPolicy-TLS13-1-2-2021-06
- ELBSecurityPolicy-TLS13-1-2-Res-2021-06
matched: true
- name: iam-roles-with-long-session-duration
description: Account {account_id} - Detect IAM roles with max session duration longer than 2 hours (7200 seconds)
resource: iam-role
filters:
- type: value
key: MaxSessionDuration
op: greater-than
value: 7200
- name: s3-bucket-blockpublicacl-off
description: Account {account_id} - Detect S3 buckets without all block public access settings enabled
resource: s3
filters:
- type: check-public-block
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
- name: s3-bucket-public-write-acl
description: Account {account_id} - Detect S3 buckets that allow public or authenticated user write access via ACLs
resource: s3
filters:
- type: global-grants
permissions:
- WRITE
- WRITE_ACP
- FULL_CONTROL
allow_website: false
- name: s3-bucket-public-read-acl
description: Account {account_id} - Detect S3 buckets that allow public or authenticated user read access via ACLs
resource: s3
filters:
- type: global-grants
permissions:
- READ
- READ_ACP
allow_website: false
- name: s3-policy-enforces-encryption-in-transit
description: Account {account_id} - Detect S3 buckets missing a bucket policy statement enforcing encryption in transit
resource: s3
filters:
- type: missing-policy-statement
statement_ids:
- CustodianEncryptionInTransit
- name: opensearch-encrypted-tls-1-2
description: "Account {account_id} - Connections to OpenSearch/Elasticsearch domains should be encrypted using TLS 1.2"
resource: aws.elasticsearch
filters:
- type: value
key: DomainEndpointOptions.TLSSecurityPolicy
op: not-equal
value: "Policy-Min-TLS-1-2-2019-07"
- name: opensearch-at-rest-encryption-disabled
description: Account {account_id} - Detect OpenSearch/Elasticsearch domains without encryption at rest enabled
resource: aws.elasticsearch
filters:
- type: value
key: EncryptionAtRestOptions.Enabled
op: not-equal
value: true
- name: opensearch-n2n-encryption-disabled
description: Account {account_id} - Detect OpenSearch/Elasticsearch domains without node-to-node encryption enabled
resource: aws.elasticsearch
filters:
- type: value
key: NodeToNodeEncryptionOptions.Enabled
op: not-equal
value: true
- name: no-root-account-access-key-exists
description: Account {account_id} - Detect accounts where the root user has access keys
resource: account
filters:
- type: iam-summary
key: AccountAccessKeysPresent
value: true
op: eq
value_type: swap
- name: dynamodb-encrypted-aws-kms
description: Account {account_id} - Detect DynamoDB tables without AWS KMS encryption enabled
resource: aws.dynamodb-table
filters:
- and:
- type: value
key: SSEDescription.KMSMasterKeyArn
value: absent
- name: vpc-default-security-group-closed
description: Account {account_id} - Ensure default security group of any VPC does not allow inbound or outbound traffic
resource: aws.security-group
filters:
- type: value
key: "GroupName"
value: "default"
- or:
- type: value
key: IpPermissions
value: not-null
- type: value
key: IpPermissionsEgress
value: not-null
- name: cloudwatch-set-log-group-retention
description: Account {account_id} - Set log group retention on cloudwatch
resource: log-group
filters:
- or:
- type: value
key: retentionInDays
value: null
- name: iam-mfa-enable-users-with-console-password
description: Account {account_id} - Ensure MFA must be enabled for all user accounts that have a console password.
resource: aws.iam-user
filters:
- type: credential
key: password_enabled
value: true
- type: credential
key: mfa_active
value: false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment