-
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.
Add S3ObjectVersioning rule to CFRipper (#193)
* Add S3ObjectVersioning rule to CFRipper * Change version * Use new pycfmodels from version 0.11.0 in this rule and previous S3 rules Co-authored-by: Oliver Crawford <oliver.crawford@skyscanner.net>
- Loading branch information
1 parent
fbb5577
commit 7448e8c
Showing
15 changed files
with
228 additions
and
154 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
VERSION = (1, 0, 9) | ||
VERSION = (1, 1, 0) | ||
|
||
__version__ = ".".join(map(str, VERSION)) |
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,62 @@ | ||
__all__ = ["S3ObjectVersioningRule"] | ||
|
||
from typing import Dict, Optional | ||
|
||
from pycfmodel.model.resources.s3_bucket import S3Bucket | ||
|
||
from cfripper.model.enums import RuleGranularity, RuleRisk | ||
from cfripper.model.result import Result | ||
from cfripper.rules.base_rules import ResourceSpecificRule | ||
|
||
|
||
class S3ObjectVersioningRule(ResourceSpecificRule): | ||
""" | ||
Checks if the S3 bucket has object versioning enabled or not. | ||
Risk: | ||
Not having this property enabled could make the bucket more vulnerable to ransomware attacks. | ||
Bucket versioning allows the automatic creation of multiple versions of an object. | ||
When an object is deleted with versioning turned on, it is only marked as deleted but is still retrievable. | ||
Fix: | ||
Add `VersioningConfiguration` property with the value `Enabled` to bucket as defined in the | ||
[AWS documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-versioningconfig.html). | ||
Code for fix: | ||
````yml | ||
Resources: | ||
S3Bucket: | ||
Type: AWS::S3::Bucket | ||
Properties: | ||
... | ||
VersioningConfiguration: | ||
Status: Enabled | ||
... | ||
```` | ||
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` | `S3Bucket` | Resource that is being addressed | | ||
""" | ||
|
||
ENABLED_STATUS = "Enabled" | ||
GRANULARITY = RuleGranularity.RESOURCE | ||
REASON = "S3 Bucket {} is required to have object versioning enabled" | ||
RESOURCE_TYPES = (S3Bucket,) | ||
RISK_VALUE = RuleRisk.LOW | ||
|
||
def resource_invoke(self, resource: S3Bucket, logical_id: str, extras: Optional[Dict] = None) -> Result: | ||
result = Result() | ||
version_configuration = resource.Properties.VersioningConfiguration | ||
if version_configuration is None or version_configuration.get("Status") != self.ENABLED_STATUS: | ||
self.add_failure_to_result( | ||
result, | ||
self.REASON.format(logical_id), | ||
resource_ids={logical_id}, | ||
context={"config": self._config, "extras": extras, "logical_id": logical_id, "resource": resource}, | ||
) | ||
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
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,41 @@ | ||
import pytest | ||
|
||
from cfripper.config.config import Config | ||
from cfripper.model.enums import RuleGranularity, RuleMode, RuleRisk | ||
from cfripper.model.result import Failure | ||
from cfripper.rules import S3ObjectVersioningRule | ||
from tests.utils import compare_lists_of_failures, get_cfmodel_from | ||
|
||
|
||
def test_rule_passing(): | ||
template_path = "rules/S3ObjectVersioning/good_template.yaml" | ||
rule = S3ObjectVersioningRule(None) | ||
result = rule.invoke(get_cfmodel_from(template_path).resolve()) | ||
|
||
assert result.valid | ||
assert compare_lists_of_failures(result.failures, []) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"template_path", | ||
["rules/S3ObjectVersioning/status_suspended.yaml", "rules/S3ObjectVersioning/no_versioning_defined.yaml"], | ||
) | ||
def test_failures_are_raised(template_path): | ||
rule = S3ObjectVersioningRule(Config()) | ||
result = rule.invoke(get_cfmodel_from(template_path).resolve()) | ||
|
||
assert not result.valid | ||
assert compare_lists_of_failures( | ||
result.failures, | ||
[ | ||
Failure( | ||
granularity=RuleGranularity.RESOURCE, | ||
reason="S3 Bucket VersionBucket is required to have object versioning enabled", | ||
risk_value=RuleRisk.LOW, | ||
rule="S3ObjectVersioningRule", | ||
rule_mode=RuleMode.BLOCKING, | ||
actions=None, | ||
resource_ids={"VersionBucket"}, | ||
) | ||
], | ||
) |
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
Oops, something went wrong.