Skip to content

Commit

Permalink
Create new stack name rule.
Browse files Browse the repository at this point in the history
  • Loading branch information
Max-Huneshagen committed Nov 9, 2023
1 parent edca534 commit 8ed41e8
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
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
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)."
)

0 comments on commit 8ed41e8

Please sign in to comment.