-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RDSSecurityGroupIngressOpenToWorldRule (#226)
* RDSSecurityGroupIngressOpenToWorldRule * Rename template files * Improve naming * Update cfripper/rules/rds_security_group.py Co-authored-by: Ramon <w0rmr1d3r@users.noreply.github.com> * Update cfripper/rules/rds_security_group.py Co-authored-by: Ramon <w0rmr1d3r@users.noreply.github.com> * Update tests/rules/test_RDSSecurityGroupIngressOpenToWorldRule.py Co-authored-by: Ramon <w0rmr1d3r@users.noreply.github.com> * Update tests/rules/test_RDSSecurityGroupIngressOpenToWorldRule.py Co-authored-by: Ramon <w0rmr1d3r@users.noreply.github.com> * fix lint * bump pycfmodel in requirements Co-authored-by: Ramon <w0rmr1d3r@users.noreply.github.com> Co-authored-by: Ramon <ramon.guimera@skyscanner.net>
- Loading branch information
1 parent
8c8c924
commit 5dc729b
Showing
8 changed files
with
202 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
from typing import Optional, Union | ||
|
||
from pycfmodel.model.resources.security_group import RDSDBSecurityGroup | ||
from pycfmodel.model.resources.security_group_ingress import RDSDBSecurityGroupIngress | ||
|
||
from cfripper.model.enums import RuleGranularity, RuleMode, RuleRisk | ||
from cfripper.model.result import Result | ||
from cfripper.rules import ResourceSpecificRule | ||
|
||
|
||
class RDSSecurityGroupIngressOpenToWorldRule(ResourceSpecificRule): | ||
""" | ||
Checks if RDS native security groups have an ingress IP that is open to the world. | ||
Fix: | ||
Most security groups only need to be [accessed privately](https://en.wikipedia.org/wiki/Private_network), and | ||
this can typically be done by specifying the CIDR of a Security Group's ingress to `10.0.0.0/8` or similar. | ||
Unless required, do not use the following IP ranges in your Security Group Ingress: | ||
- `0.0.0.0/0`. | ||
- Any `/8` that does not start with 10. | ||
- `172/8` or `192/8` (use `172.16/12` and `192.168/16` ranges, per RFC1918 specification). | ||
As per RFC4193, `fd00::/8` IPv6 addresses should be used to define a private network. | ||
Code example: | ||
````yaml | ||
Resources: | ||
CompliantRDSSecurityGroup: | ||
Type: AWS::RDS::DBSecurityGroup | ||
Properties: | ||
EC2VpcId: "vpc-id" | ||
DBSecurityGroupIngress: | ||
- CIDRIP: 10.0.0.0/8 | ||
GroupDescription: Compliant RDS security group | ||
NonCompliantRDSSecurityGroup: | ||
Type: AWS::RDS::DBSecurityGroup | ||
Properties: | ||
EC2VpcId: "vpc-id" | ||
DBSecurityGroupIngress: | ||
- CIDRIP: 0.0.0.0/0 | ||
GroupDescription: Risky RDS security group | ||
```` | ||
Filters context: | ||
| Parameter | Type | Description | | ||
|:-----------------------:|:----------------------------------------------:|:--------------------------------------------------------------:| | ||
|`config` | str | `config` variable available inside the rule | | ||
|`extras` | str | `extras` variable available inside the rule | | ||
|`logical_id` | str | ID used in Cloudformation to refer the resource being analysed | | ||
|`resource` | `RDSDBSecurityGroup/RDSDBSecurityGroupIngress` | Resource that is being addressed | | ||
|`ingress_obj` | `DBSecurityGroupIngressProp` | DBSecurityGroupIngress being checked found in the Resource | | ||
""" | ||
|
||
GRANULARITY = RuleGranularity.RESOURCE | ||
RESOURCE_TYPES = (RDSDBSecurityGroup, RDSDBSecurityGroupIngress) | ||
RULE_MODE = RuleMode.BLOCKING | ||
RISK_VALUE = RuleRisk.HIGH | ||
REASON = "RDS DB Security group {} should not have ingress open to the world" | ||
|
||
def resource_invoke( | ||
self, | ||
resource: Union[RDSDBSecurityGroup, RDSDBSecurityGroupIngress], | ||
logical_id: str, | ||
extras: Optional[dict] = None, | ||
) -> Result: | ||
result = Result() | ||
|
||
if isinstance(resource, RDSDBSecurityGroupIngress): | ||
ingress_collection = [resource.Properties] | ||
else: # isinstance(resource, RDSDBSecurityGroup) | ||
ingress_collection = resource.Properties.DBSecurityGroupIngress | ||
|
||
for ingress_entry in ingress_collection: | ||
if ingress_entry.is_public(): | ||
self.add_failure_to_result( | ||
result, | ||
self.REASON.format(logical_id), | ||
resource_ids={logical_id}, | ||
resource_types={resource.Type}, | ||
context={ | ||
"config": self._config, | ||
"extras": extras, | ||
"logical_id": logical_id, | ||
"resource": resource, | ||
"cirdip": ingress_entry.CIDRIP, | ||
}, | ||
) | ||
return result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
tests/rules/test_RDSSecurityGroupIngressOpenToWorldRule.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
from pytest import fixture | ||
|
||
from cfripper.model.enums import RuleGranularity, RuleMode, RuleRisk | ||
from cfripper.model.result import Failure | ||
from cfripper.rules import RDSSecurityGroupIngressOpenToWorldRule | ||
from tests.utils import compare_lists_of_failures, get_cfmodel_from | ||
|
||
|
||
@fixture() | ||
def rds_sg(): | ||
return get_cfmodel_from("rules/RDSSecurityGroupIngressOpenToWorldRule/rds_sg.yaml").resolve() | ||
|
||
|
||
@fixture() | ||
def rds_sg_ingress(): | ||
return get_cfmodel_from("rules/RDSSecurityGroupIngressOpenToWorldRule/rds_sg_ingress.yaml").resolve() | ||
|
||
|
||
def test_dangerous_rds_securitygroup(rds_sg): | ||
rule = RDSSecurityGroupIngressOpenToWorldRule(None) | ||
result = rule.invoke(rds_sg) | ||
|
||
assert not result.valid | ||
assert compare_lists_of_failures( | ||
result.failures, | ||
[ | ||
Failure( | ||
actions=None, | ||
granularity=RuleGranularity.RESOURCE, | ||
reason=( | ||
"RDS DB Security group NonCompliantRDSSecurityGroup " + "should not have ingress open to the world" | ||
), | ||
risk_value=RuleRisk.HIGH, | ||
rule="RDSSecurityGroupIngressOpenToWorldRule", | ||
rule_mode=RuleMode.BLOCKING, | ||
resource_ids={"NonCompliantRDSSecurityGroup"}, | ||
resource_types={"AWS::RDS::DBSecurityGroup"}, | ||
) | ||
], | ||
) | ||
|
||
|
||
def test_dangerous_rds_securitygroup_ingress(rds_sg_ingress): | ||
rule = RDSSecurityGroupIngressOpenToWorldRule(None) | ||
result = rule.invoke(rds_sg_ingress) | ||
|
||
assert not result.valid | ||
assert compare_lists_of_failures( | ||
result.failures, | ||
[ | ||
Failure( | ||
actions=None, | ||
granularity=RuleGranularity.RESOURCE, | ||
reason=( | ||
"RDS DB Security group NonCompliantRDSSecurityGroupIngress " | ||
+ "should not have ingress open to the world" | ||
), | ||
risk_value=RuleRisk.HIGH, | ||
rule="RDSSecurityGroupIngressOpenToWorldRule", | ||
rule_mode=RuleMode.BLOCKING, | ||
resource_ids={"NonCompliantRDSSecurityGroupIngress"}, | ||
resource_types={"AWS::RDS::DBSecurityGroupIngress"}, | ||
) | ||
], | ||
) | ||
|
||
|
||
def test_rule_supports_filter_config(rds_sg, default_allow_all_config): | ||
rule = RDSSecurityGroupIngressOpenToWorldRule(default_allow_all_config) | ||
result = rule.invoke(rds_sg) | ||
|
||
assert result.valid | ||
assert compare_lists_of_failures(result.failures, []) |
15 changes: 15 additions & 0 deletions
15
tests/test_templates/rules/RDSSecurityGroupIngressOpenToWorldRule/rds_sg.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Resources: | ||
CompliantRDSSecurityGroup: | ||
Type: AWS::RDS::DBSecurityGroup | ||
Properties: | ||
EC2VpcId: "vpc-id" | ||
DBSecurityGroupIngress: | ||
- CIDRIP: 10.0.0.0/8 | ||
GroupDescription: Compliant RDS security group | ||
NonCompliantRDSSecurityGroup: | ||
Type: AWS::RDS::DBSecurityGroup | ||
Properties: | ||
EC2VpcId: "vpc-id" | ||
DBSecurityGroupIngress: | ||
- CIDRIP: 0.0.0.0/0 | ||
GroupDescription: Risky RDS security group |
11 changes: 11 additions & 0 deletions
11
tests/test_templates/rules/RDSSecurityGroupIngressOpenToWorldRule/rds_sg_ingress.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
Resources: | ||
CompliantRDSSecurityGroupIngress: | ||
Type: AWS::RDS::DBSecurityGroupIngress | ||
Properties: | ||
CIDRIP: 10.0.0.0/8 | ||
DBSecurityGroupName: RDS security group ingress open to a private range | ||
NonCompliantRDSSecurityGroupIngress: | ||
Type: AWS::RDS::DBSecurityGroupIngress | ||
Properties: | ||
CIDRIP: 0.0.0.0/0 | ||
DBSecurityGroupName: Risky RDS security group ingress |