diff --git a/README.md b/README.md index 8794c84..6b444da 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,7 @@ Supported pseudo parameters: - AWS::AccountId - AWS::Partition - AWS::StackName (returns the literal string "StackName") +- AWS::StackId (returns a dummy StackId) - AWS::NoValue [Dynamic SSM references](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html) are supported, but must have a version number. This is to help ensure the same parameter that is validated is the one that is deployed. This restriction can be overridden with the --allow-dynamic-ref-without-version argument. diff --git a/cfn_policy_validator/parsers/utils/intrinsic_functions/ref_evaluator.py b/cfn_policy_validator/parsers/utils/intrinsic_functions/ref_evaluator.py index 5a5a6b1..ac20605 100644 --- a/cfn_policy_validator/parsers/utils/intrinsic_functions/ref_evaluator.py +++ b/cfn_policy_validator/parsers/utils/intrinsic_functions/ref_evaluator.py @@ -55,6 +55,11 @@ def evaluate(self, resource_logical_name_or_param, visited_nodes=None): # just return some default value, we won't know this in advance return "StackName" + if resource_logical_name_or_param == "AWS::StackId": + # build a well-formatted default StackId, we won't know this in advance + return ":".join(["arn", self.account_config.partition, "cloudformation", self.account_config.region, + self.account_config.account_id, "stack/StackName/00000000-0000-0000-0000-000000000000"]) + if resource_logical_name_or_param == "AWS::NoValue": return NoValue() diff --git a/cfn_policy_validator/tests/parsers_tests/utils_tests/intrinsic_functions_tests/test_ref_evaluator.py b/cfn_policy_validator/tests/parsers_tests/utils_tests/intrinsic_functions_tests/test_ref_evaluator.py index 546707c..9d3aa1d 100644 --- a/cfn_policy_validator/tests/parsers_tests/utils_tests/intrinsic_functions_tests/test_ref_evaluator.py +++ b/cfn_policy_validator/tests/parsers_tests/utils_tests/intrinsic_functions_tests/test_ref_evaluator.py @@ -72,7 +72,7 @@ def test_returns_the_region(self): class WhenEvaluatingAPolicyWithARefToStackName(unittest.TestCase): @mock_node_evaluator_setup() - def test_returns_the_partition(self): + def test_returns_the_stack_name(self): template = load_resources({ 'ResourceA': { 'Type': 'AWS::Random::Service', @@ -89,6 +89,27 @@ def test_returns_the_partition(self): result = node_evaluator.eval(template['Resources']['ResourceA']['Properties']['PropertyA']) self.assertEqual(result, 'StackName') +class WhenEvaluatingAPolicyWithARefToStackId(unittest.TestCase): + @mock_node_evaluator_setup() + def test_returns_the_stack_id(self): + template = load_resources({ + 'ResourceA': { + 'Type': 'AWS::Random::Service', + 'Properties': { + 'PropertyA': { + "Ref": "AWS::StackId" + } + } + } + }) + + node_evaluator = build_node_evaluator(template) + + result = node_evaluator.eval(template['Resources']['ResourceA']['Properties']['PropertyA']) + self.assertEqual(result, ":".join(["arn", account_config.partition, "cloudformation", + account_config.region, account_config.account_id, + "stack/StackName/00000000-0000-0000-0000-000000000000"])) + class WhenEvaluatingAPolicyWithARefToAnArn(unittest.TestCase): @mock_node_evaluator_setup() diff --git a/scripts/run_all_tests.sh b/scripts/run_all_tests.sh old mode 100644 new mode 100755 diff --git a/scripts/run_integration_tests.sh b/scripts/run_integration_tests.sh old mode 100644 new mode 100755 diff --git a/scripts/run_unit_tests.sh b/scripts/run_unit_tests.sh old mode 100644 new mode 100755 diff --git a/test_files/test_file_2.json b/test_files/test_file_2.json index a4ad783..1d8a6da 100644 --- a/test_files/test_file_2.json +++ b/test_files/test_file_2.json @@ -29,7 +29,15 @@ "BucketName": { "Fn::Sub": "${EnvironmentName}-app-artifacts" }, - "AccessControl": "BucketOwnerFullControl" + "AccessControl": "BucketOwnerFullControl", + "Tags": [ + { + "Key": "parentStackId", + "Value": { + "Ref": "AWS::StackId" + } + } + ] } }, "MyTopic": { diff --git a/test_files/test_file_2.yml b/test_files/test_file_2.yml index abfaa87..787f754 100644 --- a/test_files/test_file_2.yml +++ b/test_files/test_file_2.yml @@ -20,6 +20,9 @@ Resources: Properties: BucketName: !Sub ${EnvironmentName}-app-artifacts AccessControl: BucketOwnerFullControl + Tags: + - Key: 'ParentStackId' + Value: !Ref AWS::StackId MyTopic: Type: AWS::SNS::Topic