reverse-diagrams 0.2.5__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/aws/describe_sso.py CHANGED
@@ -1,53 +1,166 @@
1
- import boto3
2
1
  import logging
3
2
 
3
+ from boto3 import client
4
4
 
5
- def list_instances(client=boto3.client('sso-admin', region_name="us-east-2")):
6
- response = client.list_instances(
7
5
 
8
- )
6
+ def list_instances(region: str):
7
+ """
8
+ List all instances in the region.
9
+
10
+ :param region:
11
+ :return:
12
+ """
13
+ sso_client = client("sso-admin", region_name=region)
14
+ response = sso_client.list_instances()
9
15
 
10
16
  return response["Instances"]
11
17
 
12
18
 
13
- def list_account_assignments(instance_arn, account_id,
14
- permission_set_arn,
15
- client=boto3.client('sso-admin', region_name="us-east-2"), ):
16
- response = client.list_account_assignments(
19
+ # def list account assignments with pagination
20
+ def list_account_assignments_pag(
21
+ instance_arn, account_id, permission_set_arn, region, next_token
22
+ ):
23
+ """
24
+ List all account assignments.
25
+
26
+ :param instance_arn:
27
+ :param account_id:
28
+ :param permission_set_arn:
29
+ :param region:
30
+ :return:
31
+
32
+ """
33
+ sso_client = client("sso-admin", region_name=region)
34
+ paginator = sso_client.get_paginator("list_account_assignments")
35
+ response_iterator = paginator.paginate(
17
36
  InstanceArn=instance_arn,
18
37
  AccountId=account_id,
19
38
  PermissionSetArn=permission_set_arn,
20
-
39
+ PaginationConfig={
40
+ "MaxItems": 1000,
41
+ "PageSize": 20,
42
+ "StartingToken": next_token,
43
+ },
21
44
  )
45
+ return response_iterator["AccountAssignments"]
46
+
22
47
 
23
- return response["AccountAssignments"]
48
+ def list_account_assignments(instance_arn, account_id, permission_set_arn, region):
49
+ """
50
+ List all account assignments.
24
51
 
52
+ :param instance_arn:
53
+ :param account_id:
54
+ :param permission_set_arn:
55
+ :param region:
56
+ :return:
25
57
 
26
- def list_permissions_set(instance_arn, client=boto3.client('sso-admin', region_name="us-east-2"), ):
27
- response = client.list_permission_sets(
58
+ """
59
+ sso_client = client("sso-admin", region_name=region)
60
+ response = sso_client.list_account_assignments(
61
+ InstanceArn=instance_arn,
62
+ AccountId=account_id,
63
+ PermissionSetArn=permission_set_arn,
64
+ )
65
+ account_assignments = response["AccountAssignments"]
66
+ if len(response["AccountAssignments"]) >= 20:
67
+ logging.info("Paginating ...")
68
+ response_iterator = list_account_assignments_pag(
69
+ instance_arn,
70
+ account_id,
71
+ permission_set_arn,
72
+ region,
73
+ next_token=response["NextToken"],
74
+ )
75
+ for response in response_iterator:
76
+ logging.debug(response)
77
+ account_assignments.append(response["AccountAssignments"])
78
+ logging.info(response["AccountAssignments"])
79
+ return account_assignments
80
+
81
+
82
+ def list_permissions_set_pag(instance_arn, region, next_token):
83
+ """
84
+ List all permission set in a region.
85
+
86
+ :param instance_arn:
87
+ :param region:
88
+ :return:
89
+ """
90
+ sso_client = client("sso-admin", region_name=region)
91
+ paginator = sso_client.get_paginator("list_permission_sets")
92
+ response_iterator = paginator.paginate(
28
93
  InstanceArn=instance_arn,
94
+ PaginationConfig={
95
+ "MaxItems": 1000,
96
+ "PageSize": 20,
97
+ "StartingToken": next_token,
98
+ },
99
+ )
100
+ return response_iterator["PermissionSets"]
101
+
102
+
103
+ def list_permissions_set(instance_arn, region):
104
+ """
105
+ List all permission set in a region.
29
106
 
107
+ :param instance_arn:
108
+ :param region:
109
+ :return:
110
+ """
111
+ sso_client = client(
112
+ "sso-admin",
113
+ region_name=region,
30
114
  )
115
+ response = sso_client.list_permission_sets(InstanceArn=instance_arn, MaxResults=20)
31
116
  logging.debug(response)
32
- return response["PermissionSets"]
117
+ permissions_set = response["PermissionSets"]
118
+
119
+ if len(response["PermissionSets"]) >= 20:
120
+ logging.info("Paginating ...")
121
+ response_iterator = list_permissions_set_pag(
122
+ instance_arn, region, next_token=response["NextToken"]
123
+ )
124
+ for response in response_iterator:
125
+ logging.debug(response)
126
+ permissions_set.append(response["PermissionSets"])
127
+ logging.info(response["PermissionSets"])
128
+
129
+ return permissions_set
130
+
33
131
 
132
+ def list_permission_provisioned(account_id, instance_arn, region):
133
+ """
134
+ List permission provisioned.
34
135
 
35
- def list_permission_provisioned(account_id, instance_arn, client=boto3.client('sso-admin', region_name="us-east-2"), ):
36
- response = client.list_permission_sets_provisioned_to_account(
136
+ :param account_id:
137
+ :param instance_arn:
138
+ :param region:
139
+ :return:
140
+ """
141
+ l_client = client("sso-admin", region_name=region)
142
+ response = l_client.list_permission_sets_provisioned_to_account(
37
143
  InstanceArn=instance_arn,
38
144
  AccountId=account_id,
39
-
40
145
  )
41
146
  logging.debug(response)
42
147
  return response["PermissionSets"]
43
148
 
44
149
 
45
- def extends_permissions_set(permissions_sets, store_arn, client_sso=boto3.client('sso-admin', region_name="us-east-2")):
150
+ def extends_permissions_set(permissions_sets, store_arn, region):
151
+ """
152
+ List all permission set in a region
153
+
154
+ :param permissions_sets:
155
+ :param store_arn:
156
+ :param region:
157
+ :return:
158
+ """
159
+ sso_client = client("sso-admin", region_name=region)
46
160
  l_permissions_set_arn_name = {}
47
161
  for p in permissions_sets:
48
- response = client_sso.describe_permission_set(
49
- InstanceArn=store_arn,
50
- PermissionSetArn=p
162
+ response = sso_client.describe_permission_set(
163
+ InstanceArn=store_arn, PermissionSetArn=p
51
164
  )
52
165
 
53
166
  l_permissions_set_arn_name[p] = response["PermissionSet"]["Name"]
src/banner/banner.py CHANGED
@@ -2,7 +2,6 @@ from colorama import Fore
2
2
 
3
3
 
4
4
  banner = """Reverse Diagrams
5
-
6
5
  ##### ###### # # ###### ##### #### ######
7
6
  # # # # # # # # # #
8
7
  # # ##### # # ##### # # #### #####
@@ -21,7 +20,13 @@ banner = """Reverse Diagrams
21
20
 
22
21
 
23
22
  def get_version(version):
24
- print(Fore.BLUE + banner )
23
+ """
24
+ Get package version.
25
+
26
+ :param version:
27
+ :return:
28
+ """
29
+ print(Fore.BLUE + banner)
25
30
 
26
31
  print(version + Fore.RESET)
27
32
 
src/dgms/graph_mapper.py CHANGED
@@ -1,39 +1,49 @@
1
1
  import logging
2
2
  import os.path
3
3
  import re
4
+ from pathlib import Path
4
5
 
5
6
 
6
7
  def format_name_string(a_string, action=None):
7
8
  """
9
+ Format name strings to avoid no allowed characters.
8
10
 
9
11
  :param a_string:
10
12
  :param action:
11
13
  :return: sring --terragrunt-json-out
12
14
  """
13
- if action == 'split':
15
+ if action == "split":
14
16
  if len(a_string) > 17:
15
17
  a_string = a_string[:16] + "\\n" + a_string[16:]
16
- elif action == 'format':
17
-
18
- a_string = re.sub('[-!?@.+]', '', a_string)
19
- a_string = a_string.replace(" ", '')
18
+ elif action == "format":
19
+ a_string = re.sub("[-!?@.+]", "", a_string)
20
+ a_string = a_string.replace(" ", "")
20
21
  return a_string
21
22
 
22
23
 
23
24
  def create_sso_mapper_complete(template_file, acc_assignments, d_groups):
25
+ """
26
+ Create sso mapper.
27
+
28
+ :param template_file: Template file
29
+ :param acc_assignments:
30
+ :param d_groups:
31
+ :return:
32
+ """
24
33
 
25
- with open(template_file, 'a') as f:
34
+ with open(template_file, "a") as f:
26
35
  ident = " "
27
36
 
28
37
  for key, value in acc_assignments.items():
29
- print(f"\n with Cluster('Account: {key}'):", file=f)
30
38
  if len(value) > 0:
31
-
39
+ print(f"\n with Cluster('Account: {key}'):", file=f)
32
40
  for m in value:
33
41
  logging.debug(m)
34
42
 
35
43
  if "GroupName" in m.keys():
36
- print(f"\n{ident}with Cluster('Group: {m['GroupName']}'):", file=f)
44
+ print(
45
+ f"\n{ident}with Cluster('Group: {m['GroupName']}'):", file=f
46
+ )
37
47
  print(
38
48
  f"\n{ident}{ident}gg_{format_name_string(m['GroupName'], 'format')}=Users(\"{format_name_string(m['GroupName'], 'split')}\")\n"
39
49
  f"{ident}{ident}gg_{format_name_string(m['GroupName'], 'format')} \\\n"
@@ -43,31 +53,39 @@ def create_sso_mapper_complete(template_file, acc_assignments, d_groups):
43
53
  f"{ident}{ident}gg_{format_name_string(m['GroupName'], 'format')} \\\n"
44
54
  f"{ident}{ident}{ident}- Edge(color=\"darkgreen\", style=\"dotted\", label=\"Member\") \\\n"
45
55
  f"{ident}{ident}{ident}- mm_{format_name_string(m['GroupName'], 'format')} \n",
46
-
47
- file=f)
56
+ file=f,
57
+ )
48
58
 
49
59
  if "UserName" in m.keys():
50
- print(f"\n{ident}with Cluster('User: {m['UserName']}'):", file=f)
60
+ print(
61
+ f"\n{ident}with Cluster('User: {m['UserName']}'):", file=f
62
+ )
51
63
  print(
52
64
  f"\n{ident}{ident}uu_{format_name_string(m['UserName'], 'format')}=User(\"{format_name_string(m['UserName'], 'split')}\")\n"
53
65
  f"{ident}{ident}uu_{format_name_string(m['UserName'], 'format')} \\\n"
54
66
  f"{ident}{ident}{ident}- Edge(color=\"brown\", style=\"dotted\") \\\n"
55
67
  f"{ident}{ident}{ident}- IAMPermissions(\"{format_name_string(m['PermissionSetName'], 'split')}\")",
56
- file=f)
68
+ file=f,
69
+ )
57
70
  # print(f"\n{ident}ou >> uu_{format_name_string(m['UserName'])}\n", file=f)
58
71
  f.close()
59
72
 
60
73
 
61
74
  def create_file(template_content, file_name, directory_path="."):
62
75
  """
76
+ Create file into directory.
63
77
 
64
78
  :param template_content:
65
79
  :param file_name:
66
80
  :param directory_path:
67
81
  :return:
68
82
  """
69
- f_path=os.path.join(directory_path, file_name)
70
- with open(f_path, 'w') as f:
83
+ # create directory if not exists and is different from .
84
+ if not os.path.exists(directory_path):
85
+ os.makedirs(directory_path)
86
+ logging.debug(f"Directory {directory_path} created")
87
+ f_path = Path(os.path.join(directory_path, file_name))
88
+ with open(f_path, "w") as f:
71
89
  f.write(template_content)
72
90
  f.close()
73
91
 
@@ -79,44 +97,62 @@ def find_ou_name(ous, search_id):
79
97
 
80
98
 
81
99
  def create_mapper(template_file, org, root_id, list_ous, list_accounts):
82
- with open(template_file, 'a') as f:
100
+ with open(template_file, "a") as f:
83
101
  ident = " "
84
- print(f"\n with Cluster('Organizations'):", file=f)
85
- print(f"\n{ident}oo = Organizations('{org['Id']}\\n{org['MasterAccountId']}\\n{root_id}')", file=f)
102
+ print("\n with Cluster('Organizations'):", file=f)
103
+ print(
104
+ f"\n{ident}oo = Organizations('{org['Id']}\\n{org['MasterAccountId']}\\n{root_id}')",
105
+ file=f,
106
+ )
86
107
  for a, i in zip(list_ous, range(len(list_ous))):
87
108
  print(
88
109
  f"\n{ident}ou_{format_name_string(a['Name'], 'format')}= OrganizationsOrganizationalUnit(\"{a['Id']}\\n{a['Name']}\")",
89
- file=f)
110
+ file=f,
111
+ )
90
112
 
91
113
  for p in a["Parents"]:
92
- if p['Type'] == 'ROOT':
93
- print(f"\n{ident}oo>> ou_{format_name_string(a['Name'], 'format')}", file=f)
94
- if p['Type'] == 'ORGANIZATIONAL_UNIT':
114
+ if p["Type"] == "ROOT":
115
+ print(
116
+ f"\n{ident}oo>> ou_{format_name_string(a['Name'], 'format')}",
117
+ file=f,
118
+ )
119
+ if p["Type"] == "ORGANIZATIONAL_UNIT":
95
120
  print(
96
121
  f"\n{ident}ou_{format_name_string(find_ou_name(list_ous, p['Id']), 'format')}>> ou_{format_name_string(a['Name'], 'format')}",
97
- file=f)
122
+ file=f,
123
+ )
98
124
 
99
125
  for c, i in zip(list_accounts, range(len(list_accounts))):
100
126
  # print(f"\n aa_{i}= OrganizationsAccount(\"{c['account']}\")", file=f)
101
127
  for p in c["parents"]:
102
- if p['Type'] == 'ROOT':
103
- print(f"\n{ident}oo >> OrganizationsAccount(\"{c['account']}\\n{c['name']}\")", file=f)
128
+ if p["Type"] == "ROOT":
129
+ print(
130
+ f"\n{ident}oo >> OrganizationsAccount(\"{c['account']}\\n{c['name']}\")",
131
+ file=f,
132
+ )
104
133
 
105
134
  for o, j in zip(list_ous, range(len(list_ous))):
106
- if p['Id'] == o["Id"] and p['Type'] == 'ORGANIZATIONAL_UNIT':
135
+ if p["Id"] == o["Id"] and p["Type"] == "ORGANIZATIONAL_UNIT":
107
136
  print(
108
137
  f"\n{ident}ou_{format_name_string(o['Name'], 'format')}>> OrganizationsAccount(\"{c['account']}\\n{format_name_string(c['name'], action='split')}\")",
109
- file=f)
138
+ file=f,
139
+ )
110
140
 
111
141
  f.close()
112
142
 
113
143
 
114
144
  def create_sso_mapper(template_file, group_and_members):
115
- with open(template_file, 'a') as f:
145
+ """
146
+ Create sso mapper.
147
+
148
+ :param template_file:
149
+ :param group_and_members:
150
+ :return:
151
+ """
152
+ with open(template_file, "a") as f:
116
153
  ident = " "
117
- print(f"\n with Cluster('Groups'):", file=f)
154
+ print("\n with Cluster('Groups'):", file=f)
118
155
  for g, l in zip(group_and_members, range(len(group_and_members))):
119
-
120
156
  if len(g["members"]) > 0:
121
157
  print(f"\n{ident}with Cluster(\"{g['group_name']}\"):", file=f)
122
158
  users = "["
@@ -127,12 +163,20 @@ def create_sso_mapper(template_file, group_and_members):
127
163
  users += "]"
128
164
  print(f"\n{ident}{ident}gg_{l}= {users}", file=f)
129
165
  else:
130
- print(f"\n{ident}gg_{l}= Users(\"{format_name_string(g['group_name'], 'split')}\")", file=f)
166
+ print(
167
+ f"\n{ident}gg_{l}= Users(\"{format_name_string(g['group_name'], 'split')}\")",
168
+ file=f,
169
+ )
131
170
 
132
171
 
133
172
  def create_users_men(members):
134
- if len(members) > 0:
173
+ """
174
+ Create member users.
135
175
 
176
+ :param members:
177
+ :return:
178
+ """
179
+ if len(members) > 0:
136
180
  users = "["
137
181
  for m in members:
138
182
  user_name = m["MemberId"]["UserName"]
@@ -1,4 +1,4 @@
1
- graph_template= """
1
+ graph_template = """
2
2
  from diagrams import Diagram, Cluster
3
3
 
4
4
  from diagrams.aws.management import Organizations, OrganizationsAccount, OrganizationsOrganizationalUnit
@@ -7,7 +7,7 @@ with Diagram("Organizations-State", show=False, direction="TB"):
7
7
  ou = OrganizationsOrganizationalUnit("OU")
8
8
  oa = OrganizationsAccount("Account")
9
9
  """
10
- graph_template_sso= """
10
+ graph_template_sso = """
11
11
  from diagrams import Diagram, Cluster
12
12
 
13
13
  from diagrams.aws.management import Organizations, OrganizationsAccount, OrganizationsOrganizationalUnit
@@ -18,7 +18,7 @@ with Diagram("SSO-State", show=False, direction="TB"):
18
18
  uu= User("User")
19
19
  """
20
20
 
21
- graph_template_sso_complete="""
21
+ graph_template_sso_complete = """
22
22
  from diagrams import Diagram, Cluster, Edge
23
23
 
24
24
  from diagrams.aws.management import Organizations, OrganizationsAccount, OrganizationsOrganizationalUnit
@@ -29,4 +29,4 @@ with Diagram("IAM Identity Center", show=False, direction="LR"):
29
29
  uu = User("User")
30
30
  pp= IAMPermissions("PermissionsSet")
31
31
  ou = OrganizationsOrganizationalUnit("PermissionsAssignments")
32
- """
32
+ """
@@ -1,4 +1,5 @@
1
1
  import pandas as pd
2
2
 
3
- pdObj = pd.read_json('export.json', orient='index')
4
- print(pdObj)
3
+
4
+ pdObj = pd.read_json("export.json", orient="index")
5
+ print(pdObj)
@@ -0,0 +1,24 @@
1
+ """Save results."""
2
+ import json
3
+ import logging
4
+ from pathlib import Path
5
+
6
+ from colorama import Fore
7
+
8
+
9
+ def save_results(results, filename, directory_path="."):
10
+ """
11
+ Save results to a file.
12
+ :param results:
13
+ :param filename:
14
+
15
+ :return: None. Saves results to a file.
16
+ """
17
+ if not Path.exists(Path(directory_path)):
18
+ Path.mkdir(Path(directory_path))
19
+ logging.debug(f"Directory {directory_path} created")
20
+ with open(f"{directory_path}/{filename}", "w") as f:
21
+ json.dump(results, fp=f, indent=4)
22
+ print(
23
+ f"{Fore.YELLOW}ℹ️ The accounts are stored in {directory_path}/{filename} {Fore.RESET}"
24
+ )