Skip to content

Commit 8cc3f68

Browse files
authored
Merge pull request #293 from kmcquade/fix/GH-288-argument-flags
Fixes #288 - adds abbreviated argument flags for power users
2 parents 979b244 + 4718073 commit 8cc3f68

File tree

4 files changed

+51
-34
lines changed

4 files changed

+51
-34
lines changed

policy_sentry/command/create_template.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
short_help="Create write-policy YML template files",
1717
)
1818
@click.option(
19-
"--output-file",
19+
"--output-file", "-o",
2020
type=str,
2121
required=True,
2222
help="Relative path to output file where we want to store policy_sentry YML files.",
2323
)
2424
@click.option(
25-
"--template-type",
25+
"--template-type", "-t",
2626
type=click.Choice(["actions", "crud"], case_sensitive=False),
2727
required=True,
2828
help="Type of write_policy template to create - actions or CRUD. Case insensitive.",

policy_sentry/command/initialize.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,21 @@
3939
required=False,
4040
default=False,
4141
help="Specify this flag to fetch the HTML Docs directly from the AWS website. This will be helpful if the docs "
42-
"in the Git repository are behind the live docs and you need to use the latest version of the docs right "
43-
"now.",
42+
"in the Git repository are behind the live docs and you need to use the latest version of the docs right "
43+
"now.",
4444
)
4545
@click.option(
4646
"--build",
4747
is_flag=True,
4848
required=False,
4949
default=False,
5050
help="Build the IAM data file from the HTML files rather than copying the data file from "
51-
"the python package. Defaults to false",
51+
"the python package. Defaults to false",
5252
)
5353
@click.option(
5454
'--verbose', '-v',
5555
type=click.Choice(['critical', 'error', 'warning', 'info', 'debug'],
56-
case_sensitive=False))
56+
case_sensitive=False))
5757
def initialize_command(access_level_overrides_file, fetch, build, verbose):
5858
"""
5959
CLI command for initializing the local data file

policy_sentry/command/query.py

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,32 +39,35 @@ def query():
3939

4040
@query.command(
4141
short_help="Query the action table based on access levels, conditions, or actions that only support wildcard "
42-
"resources."
42+
"resources."
4343
)
4444
@click.option(
45-
"--service", type=str, required=True, help="Filter according to AWS service."
45+
"--service", "-s",
46+
type=str,
47+
required=True,
48+
help="Filter according to AWS service."
4649
)
4750
@click.option(
48-
"--name",
51+
"--name", "-n",
4952
type=str,
5053
required=False,
5154
help='The name of IAM Action. For example, if the action is "iam:ListUsers", supply "ListUsers" here.',
5255
)
5356
@click.option(
54-
"--access-level",
57+
"--access-level", "-a",
5558
type=click.Choice(["read", "write", "list", "tagging", "permissions-management"]),
5659
required=False,
5760
help="Filter according to CRUD levels. "
58-
"Acceptable values are read, write, list, tagging, permissions-management",
61+
"Acceptable values are read, write, list, tagging, permissions-management",
5962
)
6063
@click.option(
61-
"--condition",
64+
"--condition", "-c",
6265
type=str,
6366
required=False,
6467
help="Supply a condition key to show a list of all IAM actions that support the condition key.",
6568
)
6669
@click.option(
67-
"--resource-type",
70+
"--resource-type", "-r",
6871
type=str,
6972
required=False,
7073
help="Supply a resource type to show a list of all IAM actions that support the resource type.",
@@ -79,7 +82,7 @@ def query():
7982
@click.option(
8083
'--verbose', '-v',
8184
type=click.Choice(['critical', 'error', 'warning', 'info', 'debug'],
82-
case_sensitive=False))
85+
case_sensitive=False))
8386
def action_table(name, service, access_level, condition, resource_type, fmt, verbose):
8487
"""Query the Action Table from the Policy Sentry database"""
8588
if verbose:
@@ -95,7 +98,8 @@ def query_action_table(
9598
"""Query the Action Table from the Policy Sentry database.
9699
Use this one when leveraging Policy Sentry as a library."""
97100
if os.path.exists(LOCAL_DATASTORE_FILE_PATH):
98-
logger.info(f"Using the Local IAM definition: {LOCAL_DATASTORE_FILE_PATH}. To leverage the bundled definition instead, remove the folder $HOME/.policy_sentry/")
101+
logger.info(
102+
f"Using the Local IAM definition: {LOCAL_DATASTORE_FILE_PATH}. To leverage the bundled definition instead, remove the folder $HOME/.policy_sentry/")
99103
else:
100104
# Otherwise, leverage the datastore inside the python package
101105
logger.debug("Leveraging the bundled IAM Definition.")
@@ -171,19 +175,22 @@ def query_action_table(
171175

172176
@query.command(
173177
short_help="Query the ARN table to show RAW ARNs, like `aws:s3:::bucket/object`. "
174-
"Use --list-arn-types ARN types, like `object`."
178+
"Use --list-arn-types ARN types, like `object`."
175179
)
176180
@click.option(
177-
"--service", type=str, required=True, help="Filter according to AWS service."
181+
"--service", "-s",
182+
type=str,
183+
required=True,
184+
help="Filter according to AWS service."
178185
)
179186
@click.option(
180-
"--name",
187+
"--name", "-n",
181188
type=str,
182189
required=False,
183190
help="The short name of the resource ARN type. For example, `bucket` under service `s3`.",
184191
)
185192
@click.option(
186-
"--list-arn-types",
193+
"--list-arn-types", "-l",
187194
is_flag=True,
188195
required=False,
189196
help="Show the short names of ARN Types. If empty, this will show RAW ARNs only.",
@@ -198,7 +205,7 @@ def query_action_table(
198205
@click.option(
199206
'--verbose', '-v',
200207
type=click.Choice(['critical', 'error', 'warning', 'info', 'debug'],
201-
case_sensitive=False))
208+
case_sensitive=False))
202209
def arn_table(name, service, list_arn_types, fmt="json", verbose=None):
203210
"""Query the ARN Table from the Policy Sentry database"""
204211
if verbose:
@@ -210,7 +217,8 @@ def arn_table(name, service, list_arn_types, fmt="json", verbose=None):
210217
def query_arn_table(name, service, list_arn_types, fmt):
211218
"""Query the ARN Table from the Policy Sentry database. Use this one when leveraging Policy Sentry as a library."""
212219
if os.path.exists(LOCAL_DATASTORE_FILE_PATH):
213-
logger.info(f"Using the Local IAM definition: {LOCAL_DATASTORE_FILE_PATH}. To leverage the bundled definition instead, remove the folder $HOME/.policy_sentry/")
220+
logger.info(
221+
f"Using the Local IAM definition: {LOCAL_DATASTORE_FILE_PATH}. To leverage the bundled definition instead, remove the folder $HOME/.policy_sentry/")
214222
else:
215223
# Otherwise, leverage the datastore inside the python package
216224
logger.debug("Leveraging the bundled IAM Definition.")
@@ -236,14 +244,17 @@ def query_arn_table(name, service, list_arn_types, fmt):
236244

237245
@query.command(short_help="Query the condition table.")
238246
@click.option(
239-
"--name",
247+
"--name", "-n",
240248
type=str,
241249
required=False,
242250
help="Get details on a specific condition key. Leave this blank to get a list of all condition keys "
243-
"available to the service.",
251+
"available to the service.",
244252
)
245253
@click.option(
246-
"--service", type=str, required=True, help="Filter according to AWS service."
254+
"--service", "-s",
255+
type=str,
256+
required=True,
257+
help="Filter according to AWS service."
247258
)
248259
@click.option(
249260
"--fmt",
@@ -255,7 +266,7 @@ def query_arn_table(name, service, list_arn_types, fmt):
255266
@click.option(
256267
'--verbose', '-v',
257268
type=click.Choice(['critical', 'error', 'warning', 'info', 'debug'],
258-
case_sensitive=False))
269+
case_sensitive=False))
259270
def condition_table(name, service, fmt, verbose):
260271
"""Query the condition table from the Policy Sentry database"""
261272
if verbose:
@@ -268,7 +279,8 @@ def query_condition_table(name, service, fmt="json"):
268279
"""Query the condition table from the Policy Sentry database.
269280
Use this one when leveraging Policy Sentry as a library."""
270281
if os.path.exists(LOCAL_DATASTORE_FILE_PATH):
271-
logger.info(f"Using the Local IAM definition: {LOCAL_DATASTORE_FILE_PATH}. To leverage the bundled definition instead, remove the folder $HOME/.policy_sentry/")
282+
logger.info(
283+
f"Using the Local IAM definition: {LOCAL_DATASTORE_FILE_PATH}. To leverage the bundled definition instead, remove the folder $HOME/.policy_sentry/")
272284
else:
273285
# Otherwise, leverage the datastore inside the python package
274286
logger.debug("Leveraging the bundled IAM Definition.")

policy_sentry/command/write_policy.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,26 @@
1212

1313
logger = logging.getLogger(__name__)
1414

15+
1516
# adapted from
1617
# https://stackoverflow.com/questions/40753999/python-click-make-option-value-optional
1718

1819
class RegisterLengthOption(click.Option):
1920
""" Mark this option as getting a _length option """
2021
register_length = True
2122

23+
2224
class RegisterLengthOptionHelp(click.Option):
2325
""" Translate help for the hidden _length suffix """
26+
2427
def get_help_record(self, ctx):
2528
help_text = super().get_help_record(ctx)
2629
return (help_text[0].replace('_length ', ' '),) + help_text[1:]
2730

31+
2832
class RegisterMinimizeLengthCommand(click.Command):
2933
""" Translate any opt= to opt_length= as needed """
34+
3035
def parse_args(self, ctx, args):
3136
options = [o for o in ctx.command.params
3237
if getattr(o, 'register_length', None)]
@@ -37,12 +42,12 @@ def parse_args(self, ctx, args):
3742
if a[0] in prefixes:
3843
if len(a) > 1:
3944
args[i] = a[0]
40-
args.insert(i+1, a[0] + '_length=' + a[1])
45+
args.insert(i + 1, a[0] + '_length=' + a[1])
4146
else:
4247
# check if next argument is naked
43-
if len(args) > i+1 and not args[i+1].startswith('--'):
44-
value = args[i+1]
45-
args[i+1] = a[0] + '_length=' + value
48+
if len(args) > i + 1 and not args[i + 1].startswith('--'):
49+
value = args[i + 1]
50+
args[i + 1] = a[0] + '_length=' + value
4651
return super().parse_args(ctx, args)
4752

4853

@@ -52,12 +57,12 @@ def parse_args(self, ctx, args):
5257
)
5358
# pylint: disable=duplicate-code
5459
@click.option(
55-
"--input-file",
60+
"--input-file", "-i",
5661
type=str,
5762
help="Path of the YAML File used for generating policies",
5863
)
5964
@click.option(
60-
"--minimize",
65+
"--minimize", "-m",
6166
cls=RegisterLengthOption,
6267
is_flag=True,
6368
required=False,
@@ -82,7 +87,7 @@ def parse_args(self, ctx, args):
8287
@click.option(
8388
'--verbose', '-v',
8489
type=click.Choice(['critical', 'error', 'warning', 'info', 'debug'],
85-
case_sensitive=False))
90+
case_sensitive=False))
8691
def write_policy(input_file, minimize, minimize_length, fmt, verbose):
8792
"""
8893
Write least-privilege IAM policies, restricting all actions to resource ARNs.
@@ -111,7 +116,7 @@ def write_policy(input_file, minimize, minimize_length, fmt, verbose):
111116
indent = 4 if fmt == "json" else None
112117
policy_str = json.dumps(policy, indent=indent)
113118
if fmt == "terraform":
114-
obj = { 'policy': policy_str }
119+
obj = {'policy': policy_str}
115120
policy_str = json.dumps(obj)
116121
print(policy_str)
117122

0 commit comments

Comments
 (0)