Repository: salesforce/policy_sentry
Pull request #521 (2024-11-25 20:42:59)

feat: expand capability of '*' querying action table
## What does this PR do?

This change expands the capability of using `policy_sentry query action-table -s [service] -n "*"` to also be able to filter based on a prefix. Example:

```
policy_sentry query action-table -s s3 -n "GetObject*"                                                                                                            21:20:33
{
    "s3": [
        {
            "action": "s3:GetObject",
            "description": "Grants permission to retrieve objects from Amazon S3",
            "access_level": "Read",
            "api_documentation_link": "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html",
            "resource_arn_format": "arn:${Partition}:s3:::${BucketName}/${ObjectName}",
            "condition_keys": [],
            "dependent_actions": []
        },
        ...
        {
            "action": "s3:GetObjectAcl",
            "description": "Grants permission to return the access control list (ACL) of an object",
            "access_level": "Read",
            "api_documentation_link": "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html",
            "resource_arn_format": "arn:${Partition}:s3:::${BucketName}/${ObjectName}",
            "condition_keys": [],
            "dependent_actions": []
        },
        ...
}
```

Normally, I use something like `policy_sentry query action-table -s s3 | grep "s3:List*"` to see what permissions I give when using stars in my policies. But occasionally, I just need a little more information than just a plain text list.

## What gif best describes this PR or how it makes you feel?

![Just making a little adjustment. Bones.](https://y.yarn.co/d5e508db-f5e4-49dd-8b3a-0a31b468add4_text.gif)

## Completion checklist

- [x] Additions and changes have unit tests
- [ ] [Unit tests, Pylint, security testing, and Integration tests are passing.](https://github.com/salesforce/policy_sentry/actions). GitHub actions does this automatically
- [ ] The pull request has been appropriately labeled using the provided PR labels

Let me know if more tests are needed.


Scribbd: It looks like I am failing on a workflow that is using python 3.8. Is this intended and should I reimplement the change that is compatible with the eol python 3.8?
gruebel: let's wait till end of this month. then I will do a new release with an updated DB. After that I will remove Python 3.8 support.
gruebel: @Scribbd Ok, I dropped Python 3.8. So, feel free to rebase your PR.

Patch:
diff --git a/policy_sentry/querying/actions.py b/policy_sentry/querying/actions.py
index 86defa8c..15dd5c20 100644
--- a/policy_sentry/querying/actions.py
+++ b/policy_sentry/querying/actions.py
@@ -62,9 +62,12 @@ def get_action_data(service: str, action_name: str) -> dict[str, list[dict[str,
     action_data_results = {}
     try:
         service_prefix_data = get_service_prefix_data(service)
-        if action_name == "*":
+        if action_name.endswith("*"):
+            stripped_action_name = action_name.removesuffix("*")
             results = []
             for this_action_name, this_action_data in service_prefix_data["privileges"].items():
+                if not this_action_name.startswith(stripped_action_name):
+                    continue
                 if this_action_data:
                     entries = create_action_data_entries(
                         service_prefix_data=service_prefix_data,


Test patch:
diff --git a/test/querying/test_query_actions.py b/test/querying/test_query_actions.py
index 927b00b9..f4ad7c64 100644
--- a/test/querying/test_query_actions.py
+++ b/test/querying/test_query_actions.py
@@ -181,6 +181,33 @@ class QueryActionsTestCase(unittest.TestCase):
         self.maxDiff = None
         self.assertDictEqual(desired_output, output)
 
+    def test_get_action_data_with_glob(self):
+        """Query action-table with glob."""
+        desired_output = {
+            "sns": [
+                {
+                    "action": "sns:ListSubscriptions",
+                    "description": "Grants permission to return a list of the requester's subscriptions",
+                    "access_level": "List",
+                    "api_documentation_link": "https://docs.aws.amazon.com/sns/latest/api/API_ListSubscriptions.html",
+                    "resource_arn_format": "*",
+                    "condition_keys": [],
+                    "dependent_actions": [],
+                },
+                {
+                    "action": "sns:ListSubscriptionsByTopic",
+                    "description": "Grants permission to return a list of the subscriptions to a specific topic",
+                    "access_level": "List",
+                    "api_documentation_link": "https://docs.aws.amazon.com/sns/latest/api/API_ListSubscriptionsByTopic.html",
+                    "resource_arn_format": "arn:${Partition}:sns:${Region}:${Account}:${TopicName}",
+                    "condition_keys": ["aws:ResourceTag/${TagKey}"],
+                    "dependent_actions": [],
+                },
+            ]
+        }
+        results = get_action_data("sns", "ListSubscriptions*")
+        self.assertDictEqual(desired_output, results)
+
     def test_get_actions_that_support_wildcard_arns_only(self):
         """querying.actions.get_actions_that_support_wildcard_arns_only"""
         # Variant 1: Secrets manager