From 0911af0e547d00a3e7e207956db649a0b95f5d56 Mon Sep 17 00:00:00 2001
From: Oscar Blanco <oscarbc1996@gmail.com>
Date: Tue, 11 Jun 2024 17:32:50 +0200
Subject: [PATCH 1/2] Upgrade to pydantic v2  (#286)

* wip

* wip

* Add changelog and bump pycfmodel

* Trigger build

---------

Co-authored-by: Ignacio Bolonio <>
---
 CHANGELOG.md                                  |  15 +
 cfripper/config/config.py                     |  14 +-
 cfripper/config/filter.py                     |   7 +-
 cfripper/model/result.py                      |   9 +-
 pyproject.toml                                |   2 +-
 requirements-dev.txt                          |  90 +++--
 requirements-docs.txt                         | 101 +++---
 requirements.txt                              |  22 +-
 .../test_S3LifecycleConfigurationRule.py      |   1 -
 tests/rules/test_WildcardResourceRule.py      | 336 ++++++++++--------
 ...ed_template_malformed_lifecycle_rules.yaml |  10 -
 11 files changed, 324 insertions(+), 283 deletions(-)
 delete mode 100644 tests/test_templates/rules/S3LifecycleConfiguration/allowed_template_malformed_lifecycle_rules.yaml

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53477741..c88e4332 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,21 @@
 # Changelog
 All notable changes to this project will be documented in this file.
 
+## [1.15.7]
+### Updates
+- Bumped pycfmodel to use pydantic v2
+
+## [1.15.6]
+## Fixes
+- Fix logo displayed in pypi
+### Updates
+- Bumped python used in readthedocs to 3.9
+
+## [1.15.5]
+### Changes
+- Add dependabot config
+- Migrate to `pyproject.toml`
+
 ## [1.15.4]
 ## Fixes
 - Fix `KMSKeyWildcardPrincipalRule` to work without a KMS policy
diff --git a/cfripper/config/config.py b/cfripper/config/config.py
index 61c4fa0c..7490c06f 100644
--- a/cfripper/config/config.py
+++ b/cfripper/config/config.py
@@ -8,7 +8,7 @@
 from pathlib import Path
 from typing import DefaultDict, Dict, List
 
-from pydantic import BaseModel
+from pydantic import RootModel
 
 from cfripper.config.constants import (
     AWS_CLOUDTRAIL_ACCOUNT_IDS,
@@ -201,7 +201,7 @@ def load_rules_config_file(self, rules_config_file: TextIOWrapper):
             spec.loader.exec_module(module)
             rules_config = vars(module).get("RULES_CONFIG")
             # Validate rules_config format
-            RulesConfigMapping(__root__=rules_config)
+            RulesConfigMapping.model_validate(rules_config)
             self.rules_config = rules_config
         except Exception:
             logger.exception(f"Failed to read config file: {filename}")
@@ -236,7 +236,7 @@ def get_filters_from_filename_path(cls, filename: Path) -> List[Filter]:
         spec.loader.exec_module(module)
         filters = vars(module).get("FILTERS") or []
         # Validate filters format
-        RulesFiltersMapping(__root__=filters)
+        RulesFiltersMapping.model_validate(filters)
         return filters
 
     def add_filters(self, filters: List[Filter]):
@@ -245,9 +245,5 @@ def add_filters(self, filters: List[Filter]):
                 self.rules_filters[rule].append(rule_filter)
 
 
-class RulesConfigMapping(BaseModel):
-    __root__: Dict[str, RuleConfig]
-
-
-class RulesFiltersMapping(BaseModel):
-    __root__: List[Filter]
+RulesConfigMapping = RootModel[Dict[str, RuleConfig]]
+RulesFiltersMapping = RootModel[List[Filter]]
diff --git a/cfripper/config/filter.py b/cfripper/config/filter.py
index 3f7c5870..40a4a2b1 100644
--- a/cfripper/config/filter.py
+++ b/cfripper/config/filter.py
@@ -2,7 +2,7 @@
 import re
 from typing import Any, Callable, Dict, List, Optional, Set, Union
 
-from pydantic import BaseModel, validator
+from pydantic import BaseModel, field_validator
 from pydash.objects import get
 
 from cfripper.model.enums import RuleMode, RuleRisk
@@ -83,9 +83,10 @@ class Filter(BaseModel):
     risk_value: Optional[RuleRisk] = None
     rules: Set[str] = None
 
-    @validator("eval", pre=True)
+    @field_validator("eval", mode="before")
+    @classmethod
     def set_eval(cls, eval, values):
-        return build_evaluator(eval, values["debug"])
+        return build_evaluator(eval, values.data["debug"])
 
     def __call__(self, **kwargs):
         if self.debug:
diff --git a/cfripper/model/result.py b/cfripper/model/result.py
index 1c1e51f6..7426f938 100644
--- a/cfripper/model/result.py
+++ b/cfripper/model/result.py
@@ -1,6 +1,6 @@
 from typing import Collection, List, Optional
 
-from pydantic import BaseModel, Extra
+from pydantic import BaseModel, ConfigDict
 
 from cfripper.model.enums import RuleGranularity, RuleMode, RuleRisk
 
@@ -15,8 +15,7 @@ class Failure(BaseModel):
     resource_ids: Optional[set] = set()
     resource_types: Optional[set] = set()
 
-    class Config(BaseModel.Config):
-        extra = Extra.forbid
+    model_config = ConfigDict(extra="forbid")
 
     def serializable(self):
         return {
@@ -32,9 +31,7 @@ def serializable(self):
 
 
 class Result(BaseModel):
-    class Config(BaseModel.Config):
-        extra = Extra.forbid
-        arbitrary_types_allowed = True
+    model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
 
     exceptions: List[Exception] = []
     failures: List[Failure] = []
diff --git a/pyproject.toml b/pyproject.toml
index a7171db5..6f33a24d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,7 +39,7 @@ dependencies = [
     "cfn_flip>=1.2.0",
     "click>=8.0.0",
     "pluggy~=0.13.1",
-    "pycfmodel>=0.22.0",
+    "pycfmodel>=1.0.0",
     "pydash>=4.7.6",
     "PyYAML>=4.2b1"
 ]
diff --git a/requirements-dev.txt b/requirements-dev.txt
index d3c3c977..ed2e71d7 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,80 +1,78 @@
 # This file was autogenerated by uv v0.1.2 via the following command:
-#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --extra dev --output-file requirements-dev.txt
+#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --upgrade --extra dev --output-file requirements-dev.txt
+annotated-types==0.7.0
+antlr4-python3-runtime==4.13.1
 attrs==23.2.0
-aws-sam-translator==1.85.0
-aws-xray-sdk==2.12.1
-boto3==1.34.44
-botocore==1.34.44
-certifi==2024.2.2
+aws-sam-translator==1.89.0
+aws-xray-sdk==2.14.0
+boto3==1.34.123
+botocore==1.34.123
+certifi==2024.6.2
 cffi==1.16.0
 cfn-flip==1.3.0
-cfn-lint==0.85.2
+cfn-lint==0.87.5
 charset-normalizer==3.3.2
 click==8.1.7
-coverage==7.4.1
-cryptography==42.0.4
-docker==7.0.0
-ecdsa==0.18.0
-exceptiongroup==1.2.0
+coverage==7.5.3
+cryptography==42.0.8
+docker==7.1.0
+exceptiongroup==1.2.1
 graphql-core==3.2.3
 idna==3.7
-importlib-resources==6.1.1
 iniconfig==2.0.0
-jinja2==3.1.3
+jinja2==3.1.4
 jmespath==1.0.1
+joserfc==0.11.1
 jschema-to-python==1.2.3
 jsondiff==2.0.0
 jsonpatch==1.33
-jsonpickle==3.0.2
-jsonpointer==2.4
-jsonschema==4.21.1
+jsonpath-ng==1.6.1
+jsonpickle==3.2.1
+jsonpointer==3.0.0
+jsonschema==4.22.0
 jsonschema-path==0.3.2
 jsonschema-specifications==2023.12.1
 junit-xml==1.9
 lazy-object-proxy==1.10.0
 markupsafe==2.1.5
-moto==5.0.1
+moto==5.0.9
 mpmath==1.3.0
 multipart==0.2.4
-networkx==3.1
+networkx==3.2.1
 openapi-schema-validator==0.6.2
 openapi-spec-validator==0.7.1
-packaging==23.2
+packaging==24.1
 pathable==0.4.3
 pbr==6.0.0
-pkgutil-resolve-name==1.3.10
 pluggy==0.13.1
-py-partiql-parser==0.5.1
-pyasn1==0.5.1
-pycfmodel==0.22.0
-pycparser==2.21
-pydantic==1.10.14
-pydash==7.0.7
-pyparsing==3.1.1
+ply==3.11
+py-partiql-parser==0.5.5
+pycfmodel==1.0.0
+pycparser==2.22
+pydantic==2.7.3
+pydantic-core==2.18.4
+pydash==8.0.1
+pyparsing==3.1.2
 pytest==7.4.4
-pytest-cov==4.1.0
-python-dateutil==2.8.2
-python-jose==3.3.0
-pyyaml==6.0.1
+pytest-cov==5.0.0
+python-dateutil==2.9.0.post0
+pyyaml==6.0.2rc1
 referencing==0.31.1
-regex==2023.12.25
-requests==2.31.0
-responses==0.25.0
+regex==2024.5.15
+requests==2.32.3
+responses==0.25.2
 rfc3339-validator==0.1.4
-rpds-py==0.18.0
-rsa==4.9
-ruff==0.2.1
-s3transfer==0.10.0
+rpds-py==0.18.1
+ruff==0.4.8
+s3transfer==0.10.1
 sarif-om==1.0.4
-setuptools==69.1.0
+setuptools==70.0.0
 six==1.16.0
-sshpubkeys==3.3.1
-sympy==1.12
+sympy==1.12.1
 tomli==2.0.1
-typing-extensions==4.9.0
+typing-extensions==4.12.2
 urllib3==1.26.18
-uv==0.1.2
-werkzeug==3.0.1
+uv==0.2.10
+werkzeug==3.0.3
 wrapt==1.16.0
 xmltodict==0.13.0
-zipp==3.17.0
diff --git a/requirements-docs.txt b/requirements-docs.txt
index 339aa3eb..29e77499 100644
--- a/requirements-docs.txt
+++ b/requirements-docs.txt
@@ -1,43 +1,45 @@
 # This file was autogenerated by uv v0.1.2 via the following command:
-#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --extra dev --extra docs --output-file requirements-docs.txt
+#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --upgrade --extra docs --extra dev --output-file requirements-docs.txt
+annotated-types==0.7.0
+antlr4-python3-runtime==4.13.1
 attrs==23.2.0
-aws-sam-translator==1.85.0
-aws-xray-sdk==2.12.1
-boto3==1.34.44
-botocore==1.34.44
-certifi==2024.2.2
+aws-sam-translator==1.89.0
+aws-xray-sdk==2.14.0
+boto3==1.34.123
+botocore==1.34.123
+certifi==2024.6.2
 cffi==1.16.0
 cfn-flip==1.3.0
-cfn-lint==0.85.2
+cfn-lint==0.87.5
 charset-normalizer==3.3.2
 click==8.1.7
-coverage==7.4.1
-cryptography==42.0.4
+coverage==7.5.3
+cryptography==42.0.8
 csscompressor==0.9.5
-docker==7.0.0
-ecdsa==0.18.0
-exceptiongroup==1.2.0
+docker==7.1.0
+exceptiongroup==1.2.1
 ghp-import==2.1.0
 graphql-core==3.2.3
 htmlmin==0.1.12
 idna==3.7
-importlib-metadata==7.0.1
-importlib-resources==6.1.1
+importlib-metadata==7.1.0
 iniconfig==2.0.0
-jinja2==3.1.3
+jinja2==3.1.4
 jmespath==1.0.1
+joserfc==0.11.1
 jschema-to-python==1.2.3
 jsmin==3.0.1
 jsondiff==2.0.0
 jsonpatch==1.33
-jsonpickle==3.0.2
-jsonpointer==2.4
-jsonschema==4.21.1
+jsonpath-ng==1.6.1
+jsonpickle==3.2.1
+jsonpointer==3.0.0
+jsonschema==4.22.0
 jsonschema-path==0.3.2
 jsonschema-specifications==2023.12.1
 junit-xml==1.9
 lazy-object-proxy==1.10.0
-markdown==3.5.2
+markdown==3.6
 markupsafe==2.1.5
 mergedeep==1.3.4
 mkdocs==1.3.0
@@ -45,53 +47,50 @@ mkdocs-macros-plugin==0.7.0
 mkdocs-material==8.2.8
 mkdocs-material-extensions==1.0.3
 mkdocs-minify-plugin==0.5.0
-moto==5.0.1
+moto==5.0.9
 mpmath==1.3.0
 multipart==0.2.4
-networkx==3.1
+networkx==3.2.1
 openapi-schema-validator==0.6.2
 openapi-spec-validator==0.7.1
-packaging==23.2
+packaging==24.1
 pathable==0.4.3
 pbr==6.0.0
-pkgutil-resolve-name==1.3.10
 pluggy==0.13.1
-py-partiql-parser==0.5.1
-pyasn1==0.5.1
-pycfmodel==0.22.0
-pycparser==2.21
-pydantic==1.10.14
-pydash==7.0.7
-pygments==2.17.2
-pymdown-extensions==10.7
-pyparsing==3.1.1
+ply==3.11
+py-partiql-parser==0.5.5
+pycfmodel==1.0.0
+pycparser==2.22
+pydantic==2.7.3
+pydantic-core==2.18.4
+pydash==8.0.1
+pygments==2.18.0
+pymdown-extensions==10.8.1
+pyparsing==3.1.2
 pytest==7.4.4
-pytest-cov==4.1.0
-python-dateutil==2.8.2
-python-jose==3.3.0
-pyyaml==6.0.1
+pytest-cov==5.0.0
+python-dateutil==2.9.0.post0
+pyyaml==6.0.2rc1
 pyyaml-env-tag==0.1
 referencing==0.31.1
-regex==2023.12.25
-requests==2.31.0
-responses==0.25.0
+regex==2024.5.15
+requests==2.32.3
+responses==0.25.2
 rfc3339-validator==0.1.4
-rpds-py==0.18.0
-rsa==4.9
-ruff==0.2.1
-s3transfer==0.10.0
+rpds-py==0.18.1
+ruff==0.4.8
+s3transfer==0.10.1
 sarif-om==1.0.4
-setuptools==69.1.0
+setuptools==70.0.0
 six==1.16.0
-sshpubkeys==3.3.1
-sympy==1.12
+sympy==1.12.1
 termcolor==2.4.0
 tomli==2.0.1
-typing-extensions==4.9.0
+typing-extensions==4.12.2
 urllib3==1.26.18
-uv==0.1.2
-watchdog==4.0.0
-werkzeug==3.0.1
+uv==0.2.10
+watchdog==4.0.1
+werkzeug==3.0.3
 wrapt==1.16.0
 xmltodict==0.13.0
-zipp==3.17.0
+zipp==3.19.2
diff --git a/requirements.txt b/requirements.txt
index 15c460e6..1051c38a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,17 +1,19 @@
 # This file was autogenerated by uv v0.1.2 via the following command:
-#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --output-file requirements.txt
-boto3==1.34.44
-botocore==1.34.44
+#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --upgrade --output-file requirements.txt
+annotated-types==0.7.0
+boto3==1.34.123
+botocore==1.34.123
 cfn-flip==1.3.0
 click==8.1.7
 jmespath==1.0.1
 pluggy==0.13.1
-pycfmodel==0.22.0
-pydantic==1.10.14
-pydash==7.0.7
-python-dateutil==2.8.2
-pyyaml==6.0.1
-s3transfer==0.10.0
+pycfmodel==1.0.0
+pydantic==2.7.3
+pydantic-core==2.18.4
+pydash==8.0.1
+python-dateutil==2.9.0.post0
+pyyaml==6.0.2rc1
+s3transfer==0.10.1
 six==1.16.0
-typing-extensions==4.9.0
+typing-extensions==4.12.2
 urllib3==1.26.18
diff --git a/tests/rules/test_S3LifecycleConfigurationRule.py b/tests/rules/test_S3LifecycleConfigurationRule.py
index 4d7f5751..0c1ef036 100644
--- a/tests/rules/test_S3LifecycleConfigurationRule.py
+++ b/tests/rules/test_S3LifecycleConfigurationRule.py
@@ -17,7 +17,6 @@ def bad_template_no_configuration():
     "template_path",
     [
         "rules/S3LifecycleConfiguration/good_template.yaml",
-        "rules/S3LifecycleConfiguration/allowed_template_malformed_lifecycle_rules.yaml",
     ],
 )
 def test_no_failures_are_raised(template_path):
diff --git a/tests/rules/test_WildcardResourceRule.py b/tests/rules/test_WildcardResourceRule.py
index 21c3fc42..b4b7df15 100644
--- a/tests/rules/test_WildcardResourceRule.py
+++ b/tests/rules/test_WildcardResourceRule.py
@@ -199,16 +199,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -221,16 +221,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -243,16 +243,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -265,16 +265,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -287,16 +287,38 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
+                    "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
                     "dynamodb:PutItem",
+                    "dynamodb:Get*",
+                },
+                resource_ids={"RolePolicy"},
+                resource_types={"AWS::IAM::Policy"},
+            ),
+            Failure(
+                granularity="ACTION",
+                reason='"RolePolicy" is using a wildcard resource in "TheExtremePolicy" for "dynamodb:DeleteResourcePolicy"',
+                risk_value="MEDIUM",
+                rule="WildcardResourceRule",
+                rule_mode="BLOCKING",
+                actions={
+                    "dynamodb:Update*",
                     "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
+                    "dynamodb:Query",
+                    "dynamodb:Delete*",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -309,16 +331,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -331,16 +353,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -353,16 +375,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -375,16 +397,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -397,16 +419,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -419,16 +441,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -441,16 +463,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -463,16 +485,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -485,16 +507,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -507,16 +529,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -529,16 +551,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -551,16 +573,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -573,16 +595,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -595,16 +617,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -617,16 +639,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -639,16 +661,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -661,16 +683,38 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
+                    "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
                     "dynamodb:PutItem",
+                    "dynamodb:Get*",
+                },
+                resource_ids={"RolePolicy"},
+                resource_types={"AWS::IAM::Policy"},
+            ),
+            Failure(
+                granularity="ACTION",
+                reason='"RolePolicy" is using a wildcard resource in "TheExtremePolicy" for "dynamodb:UpdateKinesisStreamingDestination"',
+                risk_value="MEDIUM",
+                rule="WildcardResourceRule",
+                rule_mode="BLOCKING",
+                actions={
+                    "dynamodb:Update*",
                     "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
+                    "dynamodb:Query",
+                    "dynamodb:Delete*",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -683,16 +727,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -705,16 +749,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
@@ -727,16 +771,16 @@ def test_multiple_resources_with_wildcard_resources_are_detected(user_and_policy
                 rule="WildcardResourceRule",
                 rule_mode="BLOCKING",
                 actions={
-                    "dynamodb:CreateTable",
-                    "dynamodb:BatchGet*",
-                    "dynamodb:Scan",
                     "dynamodb:Update*",
+                    "dynamodb:DescribeStream",
+                    "dynamodb:BatchGet*",
+                    "dynamodb:CreateTable",
                     "dynamodb:Query",
                     "dynamodb:Delete*",
-                    "dynamodb:PutItem",
-                    "dynamodb:DescribeStream",
-                    "dynamodb:DescribeTable",
                     "dynamodb:BatchWrite*",
+                    "dynamodb:DescribeTable",
+                    "dynamodb:Scan",
+                    "dynamodb:PutItem",
                     "dynamodb:Get*",
                 },
                 resource_ids={"RolePolicy"},
diff --git a/tests/test_templates/rules/S3LifecycleConfiguration/allowed_template_malformed_lifecycle_rules.yaml b/tests/test_templates/rules/S3LifecycleConfiguration/allowed_template_malformed_lifecycle_rules.yaml
deleted file mode 100644
index e7d158fe..00000000
--- a/tests/test_templates/rules/S3LifecycleConfiguration/allowed_template_malformed_lifecycle_rules.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-Resources:
-  OutputBucket:
-    Type: AWS::S3::Bucket
-    Properties:
-      BucketName: "foo"
-      AccessControl: BucketOwnerFullControl
-      LifecycleConfiguration:
-        # This is not valid for LifecycleConfiguration, but CFRipper will not parse it right now.
-        - aa
-        - bb

From c1a26ef5c2ce781accf87100157ce98094109d50 Mon Sep 17 00:00:00 2001
From: Ignacio Bolonio <>
Date: Tue, 11 Jun 2024 17:14:17 +0200
Subject: [PATCH 2/2] Fix Python 3.8 compatibility

---
 requirements-dev.txt  | 9 ++++++---
 requirements-docs.txt | 8 +++++---
 requirements.txt      | 4 ++--
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/requirements-dev.txt b/requirements-dev.txt
index ed2e71d7..cd492e3e 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,5 +1,5 @@
-# This file was autogenerated by uv v0.1.2 via the following command:
-#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --upgrade --extra dev --output-file requirements-dev.txt
+# This file was autogenerated by uv via the following command:
+#    uv pip compile --no-emit-index-url --no-annotate pyproject.toml --extra dev --output-file requirements-dev.txt
 annotated-types==0.7.0
 antlr4-python3-runtime==4.13.1
 attrs==23.2.0
@@ -19,6 +19,7 @@ docker==7.1.0
 exceptiongroup==1.2.1
 graphql-core==3.2.3
 idna==3.7
+importlib-resources==6.4.0
 iniconfig==2.0.0
 jinja2==3.1.4
 jmespath==1.0.1
@@ -38,12 +39,13 @@ markupsafe==2.1.5
 moto==5.0.9
 mpmath==1.3.0
 multipart==0.2.4
-networkx==3.2.1
+networkx==3.1
 openapi-schema-validator==0.6.2
 openapi-spec-validator==0.7.1
 packaging==24.1
 pathable==0.4.3
 pbr==6.0.0
+pkgutil-resolve-name==1.3.10
 pluggy==0.13.1
 ply==3.11
 py-partiql-parser==0.5.5
@@ -76,3 +78,4 @@ uv==0.2.10
 werkzeug==3.0.3
 wrapt==1.16.0
 xmltodict==0.13.0
+zipp==3.19.2
diff --git a/requirements-docs.txt b/requirements-docs.txt
index 29e77499..756af11f 100644
--- a/requirements-docs.txt
+++ b/requirements-docs.txt
@@ -1,5 +1,5 @@
-# This file was autogenerated by uv v0.1.2 via the following command:
-#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --upgrade --extra docs --extra dev --output-file requirements-docs.txt
+# This file was autogenerated by uv via the following command:
+#    uv pip compile --no-emit-index-url --no-annotate pyproject.toml --extra docs --extra dev --output-file requirements-docs.txt
 annotated-types==0.7.0
 antlr4-python3-runtime==4.13.1
 attrs==23.2.0
@@ -23,6 +23,7 @@ graphql-core==3.2.3
 htmlmin==0.1.12
 idna==3.7
 importlib-metadata==7.1.0
+importlib-resources==6.4.0
 iniconfig==2.0.0
 jinja2==3.1.4
 jmespath==1.0.1
@@ -50,12 +51,13 @@ mkdocs-minify-plugin==0.5.0
 moto==5.0.9
 mpmath==1.3.0
 multipart==0.2.4
-networkx==3.2.1
+networkx==3.1
 openapi-schema-validator==0.6.2
 openapi-spec-validator==0.7.1
 packaging==24.1
 pathable==0.4.3
 pbr==6.0.0
+pkgutil-resolve-name==1.3.10
 pluggy==0.13.1
 ply==3.11
 py-partiql-parser==0.5.5
diff --git a/requirements.txt b/requirements.txt
index 1051c38a..628f6b05 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
-# This file was autogenerated by uv v0.1.2 via the following command:
-#    uv pip compile --no-emit-index-url --no-annotate -v pyproject.toml --upgrade --output-file requirements.txt
+# This file was autogenerated by uv via the following command:
+#    uv pip compile --no-emit-index-url --no-annotate pyproject.toml --output-file requirements.txt
 annotated-types==0.7.0
 boto3==1.34.123
 botocore==1.34.123