Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create stack name example rule #244

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions cfripper/config/regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,18 @@
- sns:Get*
"""
REGEX_HAS_STAR_OR_STAR_AFTER_COLON = re.compile(r"^(\w*:)*[*?]+$")


"""
Check that stack name only consists of alphanumerical characters and hyphens.
Valid:
- abcdefg
- ABCDEFG
- abcdEFG
- aBc-DeFG
Invalid:
- abc_defg
- AB:cdefg
- !@£$$%aA
"""
REGEX_ALPHANUMERICAL_OR_HYPHEN = re.compile(r"^[A-Za-z0-9\-]+$")
2 changes: 2 additions & 0 deletions cfripper/rules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
SQSQueuePolicyNotPrincipalRule,
SQSQueuePolicyPublicRule,
)
from cfripper.rules.stack_name_matches_regex import StackNameMatchesRegexRule
from cfripper.rules.wildcard_policies import (
GenericResourceWildcardPolicyRule,
S3BucketPolicyWildcardActionRule,
Expand Down Expand Up @@ -94,6 +95,7 @@
SQSQueuePolicyNotPrincipalRule,
SQSQueuePolicyPublicRule,
SQSQueuePolicyWildcardActionRule,
StackNameMatchesRegexRule,
WildcardResourceRule,
)
}
Expand Down
41 changes: 41 additions & 0 deletions cfripper/rules/stack_name_matches_regex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import re
from typing import Dict, Optional

from pycfmodel.model.cf_model import CFModel

from cfripper.config.regex import REGEX_ALPHANUMERICAL_OR_HYPHEN
from cfripper.model.enums import RuleMode, RuleRisk
from cfripper.model.result import Result
from cfripper.rules.base_rules import Rule


class StackNameMatchesRegexRule(Rule):
"""
Checks that a given stack follows the naming convention given by a regex.
"""

RULE_MODE = RuleMode.DEBUG
RISK_VALUE = RuleRisk.LOW
REASON = (
"The stack name {} does not follow the naming convention (only alphanumerical characters and hyphens allowed)."
)

def _stack_name_matches_regex(self, stack_name: str) -> bool:
"""Check that stack name follows naming convention."""
return bool(REGEX_ALPHANUMERICAL_OR_HYPHEN.match(stack_name))

def invoke(self, cfmodel: CFModel, extras: Optional[Dict] = None) -> Result:
result = Result()
stack_name = self._config.stack_name
if not stack_name:
return result
if not extras:
extras = {}

if not self._stack_name_matches_regex(stack_name):
self.add_failure_to_result(
result,
self.REASON.format(stack_name),
context={"config": self._config, "extras": extras},
)
return result
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ pyyaml==6.0
s3transfer==0.5.2
six==1.16.0
typing-extensions==4.1.1
urllib3==1.26.17
urllib3==1.26.18
39 changes: 39 additions & 0 deletions tests/rules/test_StackNameMatchesRegexRule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pytest
from pycfmodel.model.cf_model import CFModel

from cfripper.config.config import Config
from cfripper.rules import StackNameMatchesRegexRule


@pytest.mark.parametrize(
"stack_name, expected_result",
[
("justlowercase", True),
("lowercase-with-hyphens", True),
("lowercaseANDUPPERCASE", True),
("lowercase-AND-UPPERCASE-with-hyphens", True),
("including_underscore", False),
("including space", False),
("including-other-symbols!@£$%^&*()", False),
],
)
def test_stack_name_matches_regex(stack_name, expected_result):
rule = StackNameMatchesRegexRule(Config(stack_name=stack_name, rules=["StackNameMatchesRegexRule"]))
assert rule._stack_name_matches_regex(stack_name) == expected_result


def test_works_with_extras():
rule = StackNameMatchesRegexRule(Config(stack_name="some-valid-stack-name", rules=["StackNameMatchesRegexRule"]))
extras = {"stack": {"tags": [{"key": "project", "value": "some_project"}]}}
result = rule.invoke(cfmodel=CFModel(), extras=extras)
assert result.valid


def test_failure_is_added_for_invalid_stack_name():
rule = StackNameMatchesRegexRule(Config(stack_name="some_invalid_stack_name", rules=["StackNameMatchesRegexRule"]))
result = rule.invoke(cfmodel=CFModel())
assert result.failures
assert (
result.failures[0].reason
== "The stack name some_invalid_stack_name does not follow the naming convention (only alphanumerical characters and hyphens allowed)."
)
Loading