AWS Config Rules Blessed with Cloudformation cfn-guard Support!
They said it was coming, and here it is! Support for defining custom cfn-guard rules for AWS Config via Cloudformation.
Build AWS Config rules using AWS CloudFormation Guard
For some background on cfn-guard and AWS Config, check out this post.
The magic has been enabled within Cloudformation here.
We now have an additional CustomPolicyDetails section as follows
{
"EnableDebugLogDelivery" : Boolean,
"PolicyRuntime" : String,
"PolicyText" : String
}
While I have a fondness for Cloudformation, running up a new resource configuration is a little troublesome so here are some examples.
They are all available in the /github.com/sjramblings/cfn-guard-example GitHub repo and I'll be continuing to populate with more examples. PRs always welcome so go check it out.
SecurityGroupNoIngressAny
This rule will pick up on lazy people who just didn't have the time to work out what was needed.
Rule intent
- SecurityGroup should not have an ingress rule for 0.0.0.0/0
Expectations
- SKIP when there are no AWS::EC2::SecurityGroup resources
- PASS when there are no cidrIp ingress entries to 0.0.0.0/0
- FAIL otherwise
---
AWSTemplateFormatVersion: 2010-09-09
Description: Example Stack to deploy Guard Security Group Policies
Resources:
SecurityGroupNoIngressAny:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: SecurityGroupNoIngressAny
Scope:
ComplianceResourceTypes:
- "AWS::EC2::SecurityGroup"
Source:
Owner: "CUSTOM_POLICY"
CustomPolicyDetails:
EnableDebugLogDelivery: false
PolicyRuntime: guard-2.x.x
PolicyText:
!Sub |
rule check_resource_type_and_status {
resourceType == /AWS::EC2::SecurityGroup/
}
rule check_no_access_ingress_any when check_resource_type_and_status {
#
# select all cidrIp entries that point to '0.0.0.0/0'
#
let any_ip_permissions = configuration.ipPermissions[
#
# if either ipv4 or ipv6 that allows access from any address
#
some ipv4Ranges[*].cidrIp == '0.0.0.0/0' or
some ipv6Ranges[*].cidrIpv6 == '::/0']
%any_ip_permissions empty
}
Owner: CUSTOM_POLICY
SourceDetails:
-
EventSource: aws.config
MessageType: ConfigurationItemChangeNotification
SecurityGroupNoEgressAny
This rule will pick up on the annoying default imposed on us from AWS, allowing outbound anything. Please fix that one day...
Rule intent
- SecurityGroup should not have an egress rule for 0.0.0.0/0
Expectations
- SKIP when there are no AWS::EC2::SecurityGroup resources
- PASS when there are no cidrIp egress entries to 0.0.0.0/0 - FAIL otherwise
---
AWSTemplateFormatVersion: 2010-09-09
Description: Example Stack to deploy Guard Security Group Policies
Resources:
SecurityGroupNoEgressAny:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: SecurityGroupNoEgressAny
Scope:
ComplianceResourceTypes:
- "AWS::EC2::SecurityGroup"
Source:
Owner: "CUSTOM_POLICY"
CustomPolicyDetails:
EnableDebugLogDelivery: false
PolicyRuntime: guard-2.x.x
PolicyText:
!Sub |
rule check_resource_type_and_status {
resourceType == /AWS::EC2::SecurityGroup/
}
rule check_no_access_egress_any when check_resource_type_and_status {
#
# select all cidrIp entries that point to '0.0.0.0/0'
#
let any_ip_permissions = configuration.ipPermissionsEgress[
#
# if either ipv4 or ipv6 that allows access from any address
#
some ipv4Ranges[*].cidrIp == '0.0.0.0/0' or
some ipv6Ranges[*].cidrIpv6 == '::/0']
%any_ip_permissions empty
}
Owner: CUSTOM_POLICY
SourceDetails:
-
EventSource: aws.config
MessageType: ConfigurationItemChangeNotification
SecurityGroupNoIngressAnyMgmtPort
This one already exists in AWS Config as a managed rule; however, adding as a reference.
Rule intent
- SecurityGroup should not have ingress management ports rule for 0.0.0.0/0
Expectations
- SKIP when there are no AWS::EC2::SecurityGroup resources
- PASS when there are no management ports ingress entries to 0.0.0.0/0 - FAIL otherwise
---
AWSTemplateFormatVersion: 2010-09-09
Description: Example Stack to deploy Guard Security Group Policies
Resources:
SecurityGroupNoIngressAnyMgmtPort:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: SecurityGroupNoIngressAnyMgmtPort
Scope:
ComplianceResourceTypes:
- "AWS::EC2::SecurityGroup"
Source:
Owner: "CUSTOM_POLICY"
CustomPolicyDetails:
EnableDebugLogDelivery: false
PolicyRuntime: guard-2.x.x
PolicyText:
!Sub |
rule check_resource_type_and_status {
resourceType == /AWS::EC2::SecurityGroup/
}
rule check_no_access_ingress_any_mgmt_port when check_resource_type_and_status {
let management_ports = [22, 3389]
#
# select all ipPermission instances that can be reached by ANY IP address
# IPv4 or IPv6 and not UDP
#
let any_ip_permissions = configuration.ipPermissions[
#
# if either ipv4 or ipv6 that allows access from any address
#
some ipv4Ranges[*].cidrIp == '0.0.0.0/0' or
some ipv6Ranges[*].cidrIpv6 == '::/0'
#
# the ipProtocol is not UDP
#
ipProtocol != 'udp' ]
when %any_ip_permissions !empty
{
%any_ip_permissions {
ipProtocol != '-1'
when fromPort exists
toPort exists
{
let each_any_ip_perm = this
%management_ports {
this != %each_any_ip_perm.fromPort or
this != %each_any_ip_perm.toPort
}
}
}
}
}
Owner: CUSTOM_POLICY
SourceDetails:
-
EventSource: aws.config
MessageType: ConfigurationItemChangeNotification
SecurityGroupNoIngressAnyMgmtPortRestrictedVpcs
Building on the previous example, we may only want to restrict management ports to VPCs connected to the corporate network. If someone has a detached VPC then maybe we allow direct access to management ports and live dangerously!
Rule intent
- SecurityGroup should not have ingress management ports rule for 0.0.0.0/0 for restricted VPCs
Expectations
- SKIP when there are no AWS::EC2::SecurityGroup resources
- PASS when there are no management ports ingress entries to 0.0.0.0/0 for none restricted VPCs
- FAIL otherwise
---
AWSTemplateFormatVersion: 2010-09-09
Description: Example Stack to deploy Guard Security Group Policies
Resources:
SecurityGroupNoIngressAnyMgmtPortRestrictedVpcs:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: SecurityGroupNoIngressAnyMgmtPortRestrictedVpcs
Scope:
ComplianceResourceTypes:
- "AWS::EC2::SecurityGroup"
Source:
Owner: "CUSTOM_POLICY"
CustomPolicyDetails:
EnableDebugLogDelivery: false
PolicyRuntime: guard-2.x.x
PolicyText:
!Sub |
rule check_resource_type_and_status {
resourceType == /AWS::EC2::SecurityGroup/
}
rule check_no_access_ingress_any_mgmt_port_restricted_vpcs when check_resource_type_and_status {
let management_ports = [22, 3389]
let restricted_vpcs = ['vpc-0cbee09e78864b987']
#
# select only restricted VPCs
#
let any_restricted_vpc = configuration[
vpcId IN %restricted_vpcs]
when %any_restricted_vpc !empty
{
#
# select all ipPermission instances that can be reached by ANY IP address
# IPv4 or IPv6 and not UDP
#
let any_ip_permissions = configuration.ipPermissions[
#
# if either ipv4 or ipv6 that allows access from any address
#
some ipv4Ranges[*].cidrIp == '0.0.0.0/0' or
some ipv6Ranges[*].cidrIpv6 == '::/0'
#
# the ipProtocol is not UDP
#
ipProtocol != 'udp' ]
when %any_ip_permissions !empty
{
%any_ip_permissions {
ipPermissions.ipProtocol != '-1'
when ipPermissions.fromPort exists
ipPermissions.toPort exists
{
let each_any_ip_perm = this
%management_ports {
this != %each_any_ip_perm.ipPermissions.fromPort or
this != %each_any_ip_perm.ipPermissions.toPort
}
}
}
}
}
}
Owner: CUSTOM_POLICY
SourceDetails:
-
EventSource: aws.config
MessageType: ConfigurationItemChangeNotification
Hope this helps someone else!
Cheers
For more articles on AWS Config click here!](https://sjramblings.io/tag/config)
Did you find this article valuable?
Support Stephen Jones by becoming a sponsor. Any amount is appreciated!