reverse-diagrams 0.2.6__py3-none-any.whl → 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
src/reverse_diagrams.py CHANGED
@@ -1,169 +1,325 @@
1
- import os
2
-
3
- import boto3
4
- import argparse
5
- import logging
6
- import emoji
7
- from colorama import Fore
8
- from datetime import datetime
9
- from .aws.describe_organization import describe_organization, \
10
- list_accounts, index_accounts, list_roots, list_organizational_units, index_ous
11
- from .aws.describe_identity_store import order_accounts_assignments_list, extend_account_assignments, \
12
- list_groups, get_members, list_users, complete_group_members, add_users_and_groups_assign, l_groups_to_d_groups
13
- from .aws.describe_sso import list_instances, extends_permissions_set, list_permissions_set
14
- from .dgms.graph_mapper import create_mapper, create_sso_mapper_complete, create_sso_mapper, create_file
15
- from .dgms.graph_template import graph_template, graph_template_sso, graph_template_sso_complete
16
- from .banner.banner import get_version
17
-
18
- __version__ = "0.2.4"
19
-
20
-
21
- def main() -> int:
22
- """
23
- Crete architecture diagram from your current state
24
- :return:
25
- """
26
-
27
- # Initialize parser
28
- parser = argparse.ArgumentParser()
29
- parser.add_argument("-c", "--cloud",
30
- help="Cloud Provider, aws, gcp, azure", default="aws")
31
- parser.add_argument("-p", "--profile",
32
- help="AWS cli profile for Access Analyzer Api", default=None)
33
- parser.add_argument("-od", "--output_dir_path",
34
- help="Name of folder to save the diagrams python code files", default=None)
35
- parser.add_argument("-r", "--region",
36
- help="AWS cli profile for Access Analyzer Api", default="us-east-2")
37
- parser.add_argument("-o", "--graph_organization",
38
- help="Set if you want to create graph for your organization", action='store_true')
39
- parser.add_argument("-i", "--graph_identity",
40
- help="Set if you want to create graph for your IAM Center", action='store_true')
41
-
42
- parser.add_argument("-v", "--version",
43
- help="Show version", action='store_true')
44
- parser.add_argument("-d", "--debug",
45
- help="Debug Mode", action='store_true')
46
-
47
- # Read arguments from command line
48
- args = parser.parse_args()
49
- logging.info(f"The arguments are {args}")
50
- if args.debug:
51
- logging.basicConfig(level=logging.DEBUG)
52
-
53
- if args.output_dir_path:
54
- diagrams_path = args.output_dir_path
55
- else:
56
- diagrams_path = "."
57
-
58
- if args.cloud == "aws":
59
- if args.profile:
60
- profile = args.profile
61
- if profile is not None:
62
- boto3.setup_default_session(profile_name=profile)
63
-
64
- logging.info(f"Profile is: {profile}")
65
- if args.region:
66
- region = args.region
67
-
68
- if args.graph_organization:
69
- create_file(template_content=graph_template, file_name="graph_org.py", directory_path=diagrams_path)
70
-
71
- client_org = boto3.client('organizations')
72
- organization = describe_organization(client_org)
73
- print(Fore.BLUE + emoji.emojize(":sparkle: Getting Organization Info" + Fore.RESET))
74
- logging.debug(organization)
75
- logging.debug("The Roots Info")
76
- roots = list_roots(client=client_org)
77
- logging.debug(roots)
78
- print(Fore.BLUE + emoji.emojize(":sparkle: The Organizational Units list " + Fore.RESET))
79
- logging.debug("The Organizational Units list ")
80
- ous = list_organizational_units(parent_id=roots[0]["Id"], client=client_org)
81
- logging.debug(ous)
82
- logging.debug("The Organizational Units list with parents info")
83
- i_ous = index_ous(ous, client=client_org)
84
- logging.debug(i_ous)
85
- print(Fore.BLUE + emoji.emojize(":sparkle: Getting the Account list info" + Fore.RESET))
86
- l_accounts = list_accounts(client_org)
87
- logging.debug(l_accounts)
88
- logging.debug("The Account list with parents info")
89
- print(Fore.YELLOW + emoji.emojize(
90
- f":information: There are {len(l_accounts)} Accounts in your organization" + Fore.RESET))
91
- i_accounts = index_accounts(l_accounts)
92
- logging.debug(i_accounts)
93
-
94
- create_mapper(template_file="graph_org.py", org=organization, root_id=roots[0]["Id"], list_ous=ous,
95
- list_accounts=i_accounts)
96
-
97
- print(
98
- Fore.YELLOW + emoji.emojize(f":sparkles: Run -> python3 {diagrams_path}/graph_org.py " + Fore.RESET))
99
-
100
- if args.graph_identity:
101
- create_file(template_content=graph_template_sso, file_name="graph_sso.py", directory_path=diagrams_path)
102
- create_file(template_content=graph_template_sso_complete, file_name="graph_sso_complete.py",
103
- directory_path=diagrams_path)
104
-
105
- client_identity = boto3.client('identitystore', region_name=region)
106
- client_sso = boto3.client('sso-admin', region_name=region)
107
-
108
- store_instances = list_instances(client=client_sso)
109
- print(Fore.BLUE + emoji.emojize(":sparkle: Getting Identity store instance info" + Fore.RESET))
110
- logging.debug(store_instances)
111
- store_id = store_instances[0]["IdentityStoreId"]
112
- store_arn = store_instances[0]["InstanceArn"]
113
- print(Fore.BLUE + emoji.emojize(":sparkle: List groups" + Fore.RESET))
114
- l_groups = list_groups(store_id, client=client_identity)
115
- logging.debug(l_groups)
116
- print(Fore.YELLOW + emoji.emojize(
117
- f":information: There are {len(l_groups)} Groups in your Identity Store" + Fore.RESET))
118
-
119
- print(Fore.BLUE + emoji.emojize(":sparkle: Get groups and Users info" + Fore.RESET))
120
-
121
- m_groups = get_members(store_id, l_groups, client=client_identity)
122
-
123
- logging.debug(m_groups)
124
-
125
- logging.debug("Extend Group Members")
126
- l_users = list_users(store_id, client=client_identity)
127
- logging.debug(l_users)
128
- c_users_and_groups = complete_group_members(m_groups, l_users)
129
- d_groups = l_groups_to_d_groups(l_groups=c_users_and_groups)
130
-
131
- logging.debug(c_users_and_groups)
132
- # Get Account assingments
133
- permissions_set = list_permissions_set(instance_arn=store_arn, client=client_sso)
134
- l_permissions_set_arn_name = extends_permissions_set(permissions_sets=permissions_set, store_arn=store_arn,
135
- client_sso=client_sso)
136
-
137
- client_org = boto3.client('organizations')
138
- l_accounts = list_accounts(client_org)
139
- account_assignments = extend_account_assignments(accounts_list=l_accounts,
140
- permissions_sets=l_permissions_set_arn_name,
141
- client_sso=client_sso,
142
- store_arn=store_arn)
143
-
144
- account_assignments = add_users_and_groups_assign(account_assignments_list=account_assignments,
145
- user_and_group_list=c_users_and_groups,
146
- user_list=l_users,
147
- list_permissions_set_arn_name=l_permissions_set_arn_name)
148
- print(Fore.BLUE + emoji.emojize(":sparkle: Getting account assignments, users and groups" + Fore.RESET))
149
- f_accounts = order_accounts_assignments_list(accounts_dict=l_accounts,
150
- account_assignments=account_assignments)
151
- f_path= os.path.join(diagrams_path, "graph_sso_complete.py")
152
- create_sso_mapper_complete(template_file=f_path,
153
- acc_assignments=f_accounts,
154
- d_groups=d_groups)
155
-
156
- f_path = os.path.join(diagrams_path, "graph_sso.py")
157
- create_sso_mapper(template_file=f_path, group_and_members=c_users_and_groups)
158
- print(Fore.YELLOW + emoji.emojize(
159
- f":sparkles: Run -> python3 {diagrams_path}/graph_sso_complete.py " + Fore.RESET))
160
- else:
161
- print(Fore.RED + emoji.emojize(":warning: " + f"The cloud provider {args.cloud} is no available" + Fore.RESET))
162
- if args.version:
163
- get_version(version=__version__)
164
-
165
- return 0
166
-
167
-
168
- if __name__ == '__main__':
169
- main()
1
+ import argparse
2
+ import logging
3
+ import os
4
+
5
+ import argcomplete
6
+ import emoji
7
+ from boto3 import setup_default_session
8
+ from colorama import Fore
9
+
10
+ from .aws.describe_identity_store import (
11
+ add_users_and_groups_assign,
12
+ complete_group_members,
13
+ extend_account_assignments,
14
+ get_members,
15
+ l_groups_to_d_groups,
16
+ list_groups,
17
+ list_users,
18
+ order_accounts_assignments_list,
19
+ )
20
+ from .aws.describe_organization import (
21
+ describe_organization,
22
+ index_accounts,
23
+ index_ous,
24
+ list_accounts,
25
+ list_organizational_units,
26
+ list_roots,
27
+ )
28
+ from .aws.describe_sso import (
29
+ extends_permissions_set,
30
+ list_instances,
31
+ list_permissions_set,
32
+ )
33
+ from .banner.banner import get_version
34
+ from .dgms.graph_mapper import (
35
+ create_file,
36
+ create_mapper,
37
+ create_sso_mapper,
38
+ create_sso_mapper_complete,
39
+ )
40
+ from .dgms.graph_template import (
41
+ graph_template,
42
+ graph_template_sso,
43
+ graph_template_sso_complete,
44
+ )
45
+ from .reports.save_results import save_results
46
+ from .version import __version__
47
+
48
+
49
+ def graph_organizations(diagrams_path, region, auto):
50
+ """
51
+ Create organizations Graph.
52
+
53
+ :param diagrams_path:
54
+ :param region:
55
+ :return:
56
+ """
57
+ template_file = "graph_org.py"
58
+ code_path = f"{diagrams_path}/code"
59
+ json_path = f"{diagrams_path}/json"
60
+ create_file(
61
+ template_content=graph_template,
62
+ file_name=template_file,
63
+ directory_path=code_path,
64
+ )
65
+
66
+ organization = describe_organization(region=region)
67
+ print(Fore.BLUE + emoji.emojize(":sparkle: Getting Organization Info" + Fore.RESET))
68
+ logging.debug(organization)
69
+ logging.debug("The Roots Info")
70
+ roots = list_roots(region=region)
71
+ logging.debug(roots)
72
+
73
+ print(
74
+ Fore.BLUE
75
+ + emoji.emojize(":sparkle: Listing Organizational Units " + Fore.RESET)
76
+ )
77
+ logging.debug("The Organizational Units list ")
78
+ ous = list_organizational_units(parent_id=roots[0]["Id"], region=region)
79
+ logging.debug(ous)
80
+ logging.debug("The Organizational Units list with parents info")
81
+ i_ous = index_ous(ous, region=region)
82
+ logging.debug(i_ous)
83
+
84
+ print(
85
+ Fore.BLUE
86
+ + emoji.emojize(":sparkle: Getting the Account list info" + Fore.RESET)
87
+ )
88
+ l_accounts = list_accounts(region=region)
89
+ logging.debug(l_accounts)
90
+ logging.debug("The Account list with parents info")
91
+
92
+ print(
93
+ Fore.YELLOW
94
+ + emoji.emojize(
95
+ f":information: There are {len(l_accounts)} Accounts in your organization"
96
+ + Fore.RESET
97
+ )
98
+ )
99
+ i_accounts = index_accounts(l_accounts, region=region)
100
+ logging.debug(i_accounts)
101
+
102
+ file_name = "organizations.json"
103
+ save_results(results=i_accounts, filename=file_name, directory_path=json_path)
104
+
105
+ create_mapper(
106
+ template_file=f"{code_path}/{template_file}",
107
+ org=organization,
108
+ root_id=roots[0]["Id"],
109
+ list_ous=ous,
110
+ list_accounts=i_accounts,
111
+ )
112
+ if auto:
113
+ print(f"{Fore.GREEN} ❇️ Creating diagrams in {code_path}")
114
+ command = os.system(f"cd {code_path} && python3 {template_file}")
115
+ if command != 0:
116
+ print(Fore.RED + "❌ Error creating diagrams")
117
+ print(command)
118
+ else:
119
+ print(
120
+ Fore.YELLOW
121
+ + emoji.emojize(
122
+ f":sparkles: Run -> python3 {code_path}/graph_org.py " + Fore.RESET
123
+ )
124
+ )
125
+
126
+
127
+ def graph_identity_center(diagrams_path, region, auto):
128
+ """
129
+ Create Identity center diagram.
130
+
131
+ :param diagrams_path:
132
+ :param region:
133
+ :return:
134
+ """
135
+
136
+ template_file = "graph_sso.py"
137
+ template_file_complete = "graph_sso_complete.py"
138
+
139
+ code_path = f"{diagrams_path}/code"
140
+ json_path = f"{diagrams_path}/json"
141
+
142
+ create_file(
143
+ template_content=graph_template_sso,
144
+ file_name=template_file,
145
+ directory_path=code_path,
146
+ )
147
+ create_file(
148
+ template_content=graph_template_sso_complete,
149
+ file_name=template_file_complete,
150
+ directory_path=code_path,
151
+ )
152
+
153
+ store_instances = list_instances(region=region)
154
+ print(
155
+ Fore.BLUE
156
+ + emoji.emojize(":sparkle: Getting Identity store instance info" + Fore.RESET)
157
+ )
158
+ logging.debug(store_instances)
159
+ store_id = store_instances[0]["IdentityStoreId"]
160
+ store_arn = store_instances[0]["InstanceArn"]
161
+
162
+ print(Fore.BLUE + emoji.emojize(":sparkle: List groups" + Fore.RESET))
163
+ l_groups = list_groups(store_id, region=region)
164
+ logging.debug(l_groups)
165
+ print(
166
+ Fore.YELLOW
167
+ + emoji.emojize(
168
+ f":information: There are {len(l_groups)} Groups in your Identity Store"
169
+ + Fore.RESET
170
+ )
171
+ )
172
+
173
+ print(Fore.BLUE + emoji.emojize(":sparkle: Get groups and Users info" + Fore.RESET))
174
+ m_groups = get_members(store_id, l_groups, region=region)
175
+ logging.debug(m_groups)
176
+ logging.debug("Extend Group Members")
177
+ l_users = list_users(store_id, region=region)
178
+ logging.debug(l_users)
179
+ c_users_and_groups = complete_group_members(m_groups, l_users)
180
+ d_groups = l_groups_to_d_groups(l_groups=c_users_and_groups)
181
+
182
+ logging.debug(c_users_and_groups)
183
+ # Get Account assignments
184
+ permissions_set = list_permissions_set(instance_arn=store_arn, region=region)
185
+ l_permissions_set_arn_name = extends_permissions_set(
186
+ permissions_sets=permissions_set, store_arn=store_arn, region=region
187
+ )
188
+
189
+ l_accounts = list_accounts(region=region)
190
+ account_assignments = extend_account_assignments(
191
+ accounts_list=l_accounts,
192
+ permissions_sets=l_permissions_set_arn_name,
193
+ region=region,
194
+ store_arn=store_arn,
195
+ )
196
+
197
+ account_assignments = add_users_and_groups_assign(
198
+ account_assignments_list=account_assignments,
199
+ user_and_group_list=c_users_and_groups,
200
+ user_list=l_users,
201
+ list_permissions_set_arn_name=l_permissions_set_arn_name,
202
+ )
203
+
204
+ print(
205
+ Fore.BLUE
206
+ + emoji.emojize(
207
+ ":sparkle: Getting account assignments, users and groups" + Fore.RESET
208
+ )
209
+ )
210
+ f_accounts = order_accounts_assignments_list(
211
+ accounts_dict=l_accounts, account_assignments=account_assignments
212
+ )
213
+ f_path = os.path.join(code_path, template_file_complete)
214
+ create_sso_mapper_complete(
215
+ template_file=f_path, acc_assignments=f_accounts, d_groups=d_groups
216
+ )
217
+
218
+ save_results(
219
+ results=f_accounts,
220
+ filename="account_assignments.json",
221
+ directory_path=json_path,
222
+ )
223
+ save_results(results=d_groups, filename="groups.json", directory_path=json_path)
224
+
225
+ f_path = os.path.join(code_path, template_file)
226
+
227
+ create_sso_mapper(template_file=f_path, group_and_members=c_users_and_groups)
228
+
229
+ if auto:
230
+ print(f"{Fore.GREEN} ❇️ Creating diagrams in {code_path}")
231
+ command_1 = os.system(f"cd {code_path} && python3 {template_file}")
232
+ command = os.system(f"cd {code_path} && python3 {template_file_complete}")
233
+
234
+ if command != 0 or command_1 != 0:
235
+ print(Fore.RED + "❌ Error creating diagrams")
236
+ print(command)
237
+ else:
238
+ print(
239
+ Fore.YELLOW
240
+ + emoji.emojize(
241
+ f":sparkles: Run -> python3 {code_path}/{template_file_complete}"
242
+ f" or python3 {code_path}/{template_file}" + Fore.RESET
243
+ )
244
+ )
245
+
246
+
247
+ def main() -> int:
248
+ """
249
+ Crete architecture diagram from your current state.
250
+
251
+ :return:
252
+ """
253
+
254
+ # Initialize parser
255
+ parser = argparse.ArgumentParser()
256
+
257
+ parser.add_argument(
258
+ "-p", "--profile", help="AWS cli profile for AWS Apis", default=None
259
+ )
260
+ parser.add_argument(
261
+ "-od",
262
+ "--output_dir_path",
263
+ help="Name of folder to save the diagrams python code files",
264
+ default="diagrams",
265
+ )
266
+ parser.add_argument("-r", "--region", help="AWS region", default="us-east-2")
267
+ parser.add_argument(
268
+ "-o",
269
+ "--graph_organization",
270
+ help="Set if you want to create graph for your organization",
271
+ action="store_true",
272
+ )
273
+ parser.add_argument(
274
+ "-i",
275
+ "--graph_identity",
276
+ help="Set if you want to create graph for your IAM Center",
277
+ action="store_true",
278
+ )
279
+ parser.add_argument(
280
+ "-a",
281
+ "--auto_create",
282
+ help="Create Automatically diagrams",
283
+ action="store_true",
284
+ default=True,
285
+ )
286
+ parser.add_argument("-v", "--version", help="Show version", action="store_true")
287
+ parser.add_argument("-d", "--debug", help="Debug Mode", action="store_true")
288
+
289
+ # Read arguments from command line
290
+ args = parser.parse_args()
291
+ # Add autocomplete
292
+ argcomplete.autocomplete(parser)
293
+ logging.info(f"The arguments are {args}")
294
+ if args.debug:
295
+ logging.basicConfig(level=logging.DEBUG)
296
+
297
+ diagrams_path = args.output_dir_path
298
+
299
+ region = args.region
300
+
301
+ if args.profile:
302
+ profile = args.profile
303
+ if profile is not None:
304
+ setup_default_session(profile_name=profile)
305
+
306
+ logging.info(f"Profile is: {profile}")
307
+
308
+ if args.graph_organization:
309
+ graph_organizations(
310
+ diagrams_path=diagrams_path, region=region, auto=args.auto_create
311
+ )
312
+
313
+ if args.graph_identity:
314
+ graph_identity_center(
315
+ diagrams_path=diagrams_path, region=region, auto=args.auto_create
316
+ )
317
+
318
+ if args.version:
319
+ get_version(version=__version__)
320
+
321
+ return 0
322
+
323
+
324
+ if __name__ == "__main__":
325
+ main()
src/version.py ADDED
@@ -0,0 +1,2 @@
1
+ """Set version file."""
2
+ __version__ = "1.0.0"
@@ -1,17 +0,0 @@
1
- src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- src/reverse_diagrams.py,sha256=FIWMS9anHgfDkDJIUUtb6mnZZ11q3nX8Tlu5OgeFMys,8654
3
- src/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- src/aws/describe_identity_store.py,sha256=5LRtm1IwMKMRX6vRqxIUzna3VqZkHAWD2HylUHdeB1Y,7246
5
- src/aws/describe_organization.py,sha256=ki0o3VhtH6mMV6EmZzlKPRfL5SKKVZGweK3NEiChXfY,3053
6
- src/aws/describe_sso.py,sha256=AOob-7fQk6paWjBT3dBx0Fizb5IhjWp1IIrOIv6s-yQ,1720
7
- src/banner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- src/banner/banner.py,sha256=D4XgGeWINUEpaQeMNIyuU1gY54bgv4UhantsDRj7TBQ,901
9
- src/dgms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- src/dgms/graph_mapper.py,sha256=1YWY4eQPZzDlqahjmgBIQSmvmiCrmAdwZoOdggnI6zE,6259
11
- src/dgms/graph_template.py,sha256=4twiySM5MFl3oRpLkjTGgdswIwi2ee3lTjPmTx5SmG4,1170
12
- src/export_report/export_csv.py,sha256=6A3ZpoBnk6l1GVVmpH-_id6vKdd6JGipNCUwURtyIUs,88
13
- reverse_diagrams-0.2.6.dist-info/METADATA,sha256=FTOqse6qfcxYMrKjh4vIseE3a4QpojRe3jIcZ99Ohik,5395
14
- reverse_diagrams-0.2.6.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
15
- reverse_diagrams-0.2.6.dist-info/entry_points.txt,sha256=VZNkrc7qUDbddTCH3pGd83EhUT3PHTx9MzpAk6bb6qc,63
16
- reverse_diagrams-0.2.6.dist-info/licenses/LICENSE,sha256=IaXsSIrH5zPkhwGm3_eitFhOsUeh8vnvs_ZazfXa4fM,1095
17
- reverse_diagrams-0.2.6.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) [2023] [Alejandro Velez]
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.