Skip to content

Commit e809687

Browse files
authored
Merge pull request #308 from kmcquade/fix/GH-292-hyperlinks-to-action-api-calls
Adds hyperlinks to AWS IAM Action metadata. Adds new query for get_api_documentation_link_for_action
2 parents 2051344 + c7bbe4f commit e809687

File tree

9 files changed

+18648
-9184
lines changed

9 files changed

+18648
-9184
lines changed

docs/contributing/testing.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,14 @@ Local Unit Testing and Integration Testing:
7676

7777
* File mapping: Unit test files map directly to the .py files in the Policy Sentry package
7878
* Folder mapping: Folder structure of the test files maps directly to the folder structure in the Policy Sentry package
79-
* GitHub issue mapping: Add unit tests that correspond directly to those GitHub issues to show that the fix work specifically for the issue raised. prefix test name with issue number.
79+
* GitHub issue mapping: Add unit tests that correspond directly to those GitHub issues to show that the fix work specifically for the issue raised. prefix test name with issue number.
8080
For example: [test_gh_211_write_with_empty_access_level_lists](https://github.com/salesforce/policy_sentry/blob/0b3398a365f4cf0901bd779c6156207688e7858b/test/writing/test_write_policy_library_usage.py#L269) is prefixed with issue number 111.
81-
* Adaptable to IAM Definition changes:
81+
* Adaptable to IAM Definition changes:
8282
* For tests that are dependent on current state of the IAM definition (aka the IAM Database, iam_definition.json), avoid doing equals comparision of the results with the expected_results.
8383
* Over time, as IAM definiton changes, chances are that such tests would fail.
8484
* Example: let's say that hypothetically the secretsmanager service had 4 actions at the "write" access level that could be restricted to the secret resource type. If I wrote the tests so that they tested the value of the generated policy, that works for the initial tests. But if AWS adds two new actions that can be restricted to that access level and resource type, then the tests would fail.
8585
* This only really applies for where the expected test values would be dependent on the current state of the IAM definition (aka the IAM Database, iam_definition.json) and the actions in there. So, validating the output of write-policy related commands, and query related commands.
86-
* After I realized that, I started writing my tests so that the expected output that showed what actions you'd want would be in the comments instead of the expected_results, so the human knows what's going on. And then I would just check that the size of the array holding the actions is greater than or equal to the size that it is currently at.
86+
* After I realized that, I started writing my tests so that the expected output that showed what actions you'd want would be in the comments instead of the expected_results, so the human knows what's going on. And then I would just check that the size of the array holding the actions is greater than or equal to the size that it is currently at.
8787
So, in the secretsmanager example above, the test would probably just check that the size of the actions is greater than or equal to 4.
8888

8989

@@ -101,8 +101,7 @@ folder.
101101
./utils/run_tests.sh
102102
```
103103

104-
It will execute all of the tests that would normally be run during the
105-
TravisCI build. If you want to see if it will pass TravisCI, you can
104+
It will execute all of the tests that would normally be run during the build. If you want to see if it will pass GitHub actions, you can
106105
just run that quick command on your machine.
107106

108107
Running the Test Suite

policy_sentry/bin/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"""
33
Policy Sentry is a tool for generating least-privilege IAM Policies.
44
"""
5-
__version__ = "0.11.1"
5+
__version__ = "0.11.2"
66
import click
77
from policy_sentry import command
88

policy_sentry/querying/actions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def get_action_data(service, action_name):
7979
"action": f"{service_prefix_data['prefix']}:{this_action_name}",
8080
"description": this_action_data["description"],
8181
"access_level": this_action_data["access_level"],
82+
"api_documentation_link": this_action_data.get("api_documentation_link"),
8283
"resource_arn_format": resource_arn_format,
8384
"condition_keys": condition_keys,
8485
"dependent_actions": dependent_actions,
@@ -448,3 +449,23 @@ def get_privilege_info(service_prefix, action):
448449
except KeyError as k_e:
449450
raise Exception("Unknown action {}:{}".format(service_prefix, action)) from k_e
450451
return privilege_info
452+
453+
454+
def get_api_documentation_link_for_action(service_prefix, action_name):
455+
"""
456+
Given a service, like `s3` and an action name, like `ListBucket`, return the documentation link about that specific
457+
API call.
458+
459+
Arguments:
460+
service_prefix: The service prefix, like `s3`
461+
action_name: An action name, like `ListBucket`
462+
463+
Returns:
464+
List: Link to the documentation about that API call
465+
"""
466+
rows = get_action_data(service_prefix, action_name)
467+
result = None
468+
for row in rows.get(service_prefix):
469+
if row.get("api_documentation_link"):
470+
result = row.get("api_documentation_link")
471+
return result

policy_sentry/shared/awsdocs.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,13 @@ def create_database(destination_directory, access_level_overrides_file):
242242
priv = ""
243243
# Get the privilege
244244
for link in cells[0].find_all("a"):
245-
if "href" not in link.attrs:
245+
if "href" not in link.attrs: # pylint: disable=no-else-continue
246246
# Skip the <a id='...'> tags
247+
api_documentation_link = None
247248
continue
249+
else:
250+
api_documentation_link = link.attrs.get('href')
251+
print(api_documentation_link)
248252
priv = chomp(link.text)
249253
if priv == "":
250254
priv = chomp(cells[0].text)
@@ -327,6 +331,7 @@ def create_database(destination_directory, access_level_overrides_file):
327331
"description": description,
328332
"access_level": access_level,
329333
"resource_types": resource_types,
334+
"api_documentation_link": api_documentation_link
330335
}
331336

332337
service_schema["privileges"][priv] = privilege_schema

0 commit comments

Comments
 (0)