Skip to content

Commit 8c8d21d

Browse files
Merge pull request #165 from Cloud-Architects/refactoring
Moved out AWS specific code to separate files
2 parents 8f3d89e + 99a15f2 commit 8c8d21d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+525
-488
lines changed

cloudiscovery/__init__.py

Lines changed: 5 additions & 279 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,26 @@
1414
limitations under the License.
1515
"""
1616

17-
import argparse
1817
import gettext
1918
import sys
2019
from os.path import dirname
2120
from typing import List
2221

2322
import pkg_resources
2423

24+
from provider.aws.command import aws_main
25+
from shared.parameters import generate_parser
26+
2527
"""path to pip package"""
2628
sys.path.append(dirname(__file__))
2729

2830
# pylint: disable=wrong-import-position
29-
30-
from provider.policy.command import Policy
31-
from provider.vpc.command import Vpc
32-
from provider.iot.command import Iot
33-
from provider.all.command import All
34-
from provider.limit.command import Limit
35-
from provider.security.command import Security
36-
3731
from shared.common import (
3832
exit_critical,
3933
Filterable,
4034
parse_filters,
41-
message_handler,
4235
)
43-
from shared.common_aws import aws_verbose, generate_session
4436

45-
# pylint: enable=wrong-import-position
4637
# Check version
4738
if sys.version_info < (3, 8):
4839
print("Python 3.8 or newer is required", file=sys.stderr)
@@ -51,139 +42,6 @@
5142
__version__ = "2.3"
5243

5344
AVAILABLE_LANGUAGES = ["en_US", "pt_BR"]
54-
DEFAULT_REGION = "us-east-1"
55-
DEFAULT_PARTITION_CODE = "aws"
56-
57-
58-
def str2bool(v):
59-
if isinstance(v, bool):
60-
return v
61-
# pylint: disable=no-else-return
62-
if v.lower() in ("yes", "true", "t", "y", "1"):
63-
return True
64-
elif v.lower() in ("no", "false", "f", "n", "0"):
65-
return False
66-
else:
67-
raise argparse.ArgumentTypeError("Boolean value expected.")
68-
69-
70-
def generate_parser():
71-
parser = argparse.ArgumentParser()
72-
73-
subparsers = parser.add_subparsers(help="commands", dest="command")
74-
75-
vpc_parser = subparsers.add_parser("aws-vpc", help="Analyze VPCs")
76-
add_default_arguments(vpc_parser)
77-
vpc_parser.add_argument(
78-
"-v",
79-
"--vpc-id",
80-
required=False,
81-
help="Inform VPC to analyze. If not informed, script will check all vpcs.",
82-
)
83-
84-
iot_parser = subparsers.add_parser("aws-iot", help="Analyze IoTs")
85-
add_default_arguments(iot_parser)
86-
iot_parser.add_argument(
87-
"-t",
88-
"--thing-name",
89-
required=False,
90-
help="Inform Thing Name to analyze. If not informed, script will check all things inside a region.",
91-
)
92-
93-
policy_parser = subparsers.add_parser("aws-policy", help="Analyze policies")
94-
add_default_arguments(policy_parser, is_global=True)
95-
96-
all_parser = subparsers.add_parser("aws-all", help="Analyze all resources")
97-
add_default_arguments(all_parser, diagram_enabled=False)
98-
add_services_argument(all_parser)
99-
100-
limit_parser = subparsers.add_parser(
101-
"aws-limit", help="Analyze aws limit resources."
102-
)
103-
add_default_arguments(limit_parser, diagram_enabled=False, filters_enabled=False)
104-
add_services_argument(limit_parser)
105-
limit_parser.add_argument(
106-
"-t",
107-
"--threshold",
108-
required=False,
109-
help="Select the %% of resource threshold between 0 and 100. \
110-
For example: --threshold 50 will report all resources with more than 50%% threshold.",
111-
)
112-
113-
security_parser = subparsers.add_parser(
114-
"aws-security", help="Analyze aws several security checks."
115-
)
116-
add_default_arguments(security_parser, diagram_enabled=False, filters_enabled=False)
117-
security_parser.add_argument(
118-
"-c",
119-
"--commands",
120-
action="append",
121-
required=False,
122-
help='Select the security check command that you want to run. \
123-
To see available commands, please type "-c list". \
124-
If not passed, command will check all services.',
125-
)
126-
127-
return parser
128-
129-
130-
def add_services_argument(limit_parser):
131-
limit_parser.add_argument(
132-
"-s",
133-
"--services",
134-
required=False,
135-
help='Define services that you want to check, use "," (comma) to separate multiple names. \
136-
If not passed, command will check all services.',
137-
)
138-
139-
140-
def add_default_arguments(
141-
parser, is_global=False, diagram_enabled=True, filters_enabled=True
142-
):
143-
if not is_global:
144-
parser.add_argument(
145-
"-r",
146-
"--region-name",
147-
required=False,
148-
help='Inform REGION NAME to analyze or "all" to check on all regions. \
149-
If not informed, try to get from config file',
150-
)
151-
parser.add_argument(
152-
"-p", "--profile-name", required=False, help="Profile to be used"
153-
)
154-
parser.add_argument(
155-
"-l", "--language", required=False, help="Available languages: pt_BR, en_US"
156-
)
157-
parser.add_argument(
158-
"--verbose",
159-
"--verbose",
160-
type=str2bool,
161-
nargs="?",
162-
const=True,
163-
default=False,
164-
help="Enable debug mode to sdk calls (default false)",
165-
)
166-
if filters_enabled:
167-
parser.add_argument(
168-
"-f",
169-
"--filters",
170-
action="append",
171-
required=False,
172-
help="filter resources (tags only for now, you must specify name and values); multiple filters "
173-
"are possible to pass with -f <filter_1> -f <filter_2> approach, values can be separated by : sign; "
174-
"example: Name=tags.costCenter;Value=20000:'20001:1'",
175-
)
176-
if diagram_enabled:
177-
parser.add_argument(
178-
"-d",
179-
"--diagram",
180-
type=str2bool,
181-
nargs="?",
182-
const=True,
183-
default=True,
184-
help="print diagram with resources (need Graphviz installed). Pass true/y[es] to "
185-
"view image or false/n[o] not to generate image. Default true",
186-
)
18745

18846

18947
# pylint: disable=too-many-branches,too-many-statements,too-many-locals
@@ -197,10 +55,6 @@ def main():
19755

19856
args = parser.parse_args()
19957

200-
# Check if verbose mode is enabled
201-
if args.verbose:
202-
aws_verbose()
203-
20458
if args.language is None or args.language not in AVAILABLE_LANGUAGES:
20559
language = "en_US"
20660
else:
@@ -228,83 +82,8 @@ def main():
22882
if args.filters is not None:
22983
filters = parse_filters(args.filters)
23084

231-
# aws profile check
232-
if "region_name" not in args:
233-
session = generate_session(profile_name=args.profile_name, region_name=None)
234-
else:
235-
session = generate_session(
236-
profile_name=args.profile_name, region_name=args.region_name
237-
)
238-
239-
session.get_credentials()
240-
region_name = session.region_name
241-
242-
partition_code = get_partition(session, region_name)
243-
244-
if "region_name" not in args:
245-
region_names = [DEFAULT_REGION]
246-
else:
247-
# checking region configuration
248-
check_region_profile(
249-
arg_region_name=args.region_name, profile_region_name=region_name
250-
)
251-
252-
# assuming region parameter precedes region configuration
253-
if args.region_name is not None:
254-
region_name = args.region_name
255-
256-
# get regions
257-
region_names = check_region(
258-
region_parameter=args.region_name,
259-
region_name=region_name,
260-
session=session,
261-
partition_code=partition_code,
262-
)
263-
264-
if "threshold" in args:
265-
if args.threshold is not None:
266-
if args.threshold.isdigit() is False:
267-
exit_critical(_("Threshold must be between 0 and 100"))
268-
else:
269-
if int(args.threshold) < 0 or int(args.threshold) > 100:
270-
exit_critical(_("Threshold must be between 0 and 100"))
271-
272-
if args.command == "aws-vpc":
273-
command = Vpc(
274-
vpc_id=args.vpc_id,
275-
region_names=region_names,
276-
session=session,
277-
partition_code=partition_code,
278-
)
279-
elif args.command == "aws-policy":
280-
command = Policy(
281-
region_names=region_names, session=session, partition_code=partition_code
282-
)
283-
elif args.command == "aws-iot":
284-
command = Iot(
285-
thing_name=args.thing_name,
286-
region_names=region_names,
287-
session=session,
288-
partition_code=partition_code,
289-
)
290-
elif args.command == "aws-all":
291-
command = All(
292-
region_names=region_names, session=session, partition_code=partition_code
293-
)
294-
elif args.command == "aws-limit":
295-
command = Limit(
296-
region_names=region_names,
297-
session=session,
298-
threshold=args.threshold,
299-
partition_code=partition_code,
300-
)
301-
elif args.command == "aws-security":
302-
command = Security(
303-
region_names=region_names,
304-
session=session,
305-
commands=args.commands,
306-
partition_code=partition_code,
307-
)
85+
if args.command.startswith("aws"):
86+
command = aws_main(args)
30887
else:
30988
raise NotImplementedError("Unknown command")
31089

@@ -316,28 +95,6 @@ def main():
31695
command.run(diagram, args.verbose, services, filters)
31796

31897

319-
def get_partition(session, region_name):
320-
partition_code = DEFAULT_PARTITION_CODE # assume it's always default partition, even if we can't find a region
321-
partition_name = "AWS Standard"
322-
# pylint: disable=protected-access
323-
loader = session._session.get_component("data_loader")
324-
endpoints = loader.load_data("endpoints")
325-
for partition in endpoints["partitions"]:
326-
for region, _ in partition["regions"].items():
327-
if region == region_name:
328-
partition_code = partition["partition"]
329-
partition_name = partition["partitionName"]
330-
331-
if partition_code != DEFAULT_PARTITION_CODE:
332-
message_handler(
333-
"Found non-default partition: {} ({})".format(
334-
partition_code, partition_name
335-
),
336-
"HEADER",
337-
)
338-
return partition_code
339-
340-
34198
def check_diagram_version(diagram):
34299
if diagram:
343100
# Checking diagram version. Must be 0.13 or higher
@@ -348,37 +105,6 @@ def check_diagram_version(diagram):
348105
)
349106

350107

351-
def check_region_profile(arg_region_name, profile_region_name):
352-
if arg_region_name is None and profile_region_name is None:
353-
exit_critical("Neither region parameter nor region config were passed")
354-
355-
356-
def check_region(region_parameter, region_name, session, partition_code):
357-
"""
358-
Region us-east-1 as a default region here, if not aws partition, just return asked region
359-
360-
This is just to list aws regions, doesn't matter default region
361-
"""
362-
if partition_code != "aws":
363-
return [region_name]
364-
365-
client = session.client("ec2", region_name=DEFAULT_REGION)
366-
367-
valid_region_names = [
368-
region["RegionName"]
369-
for region in client.describe_regions(AllRegions=True)["Regions"]
370-
]
371-
372-
if region_parameter != "all":
373-
if region_name not in valid_region_names:
374-
message = "There is no region named: {0}".format(region_name)
375-
exit_critical(message)
376-
else:
377-
valid_region_names = [region_name]
378-
379-
return valid_region_names
380-
381-
382108
if __name__ == "__main__":
383109
try:
384110
main()
File renamed without changes.
File renamed without changes.

cloudiscovery/provider/all/command.py renamed to cloudiscovery/provider/aws/all/command.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import List
22

3+
from provider.aws.common_aws import BaseAwsOptions, BaseAwsCommand, AwsCommandRunner
34
from shared.common import Filterable, BaseOptions
4-
from shared.common_aws import BaseAwsOptions, BaseAwsCommand, AwsCommandRunner
55
from shared.diagram import NoDiagram
66

77

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)