@@ -81,6 +81,8 @@ def fetch_roles_data():
8181 for page in paginator .paginate ():
8282 response .extend (page ['Roles' ])
8383 # save
84+ with open ('imported/roles.json' , 'w' ) as f :
85+ json .dump (response , f , indent = 2 , default = str )
8486 return [('iam' , j ['RoleName' ]) for j in response ]
8587 except Exception as e :
8688 print ("Error fetching vpc data:" , e )
@@ -158,42 +160,59 @@ def fetch_policies_data():
158160
159161 return True
160162
161- def build_secondary_lists (id ):
163+ def build_secondary_lists (id = None ):
162164 if id is None :
163165 st1 = datetime .datetime .now ()
164166 print ("Building secondary IAM resource lists ..." )
165- globals .esttime = (len (globals .rolelist )* 3 )/ 4
166- globals .tracking_message = "Stage 2 of 10, Building secondary IAM resource lists ..."
167- client = boto3 .client ('iam' )
168- # attached_role_policies
169- rcl = len (globals .rolelist )
170- rc = 1
171- for rn in globals .rolelist .keys ():
172- response = []
173- response1 = []
174- #paginator = client.get_paginator('list_attached_role_policies')
175- #paginator2 = client.get_paginator('list_role_policies')
167+ globals .esttime = (len (globals .rolelist ) * 3 ) / 4
168+ globals .tracking_message = "Stage 2 of 10, Building secondary IAM resource lists ..."
169+
170+ def fetch_role_policies (role_name ):
171+ client = boto3 .client ('iam' )
176172 try :
177- response = client .list_attached_role_policies (RoleName = rn )
178- response1 = client .list_role_policies (RoleName = rn )
179- except Exception as e :
180- print (f"{ e = } " )
181- #print(str(response)+"\n")
182- if response ['AttachedPolicies' ] == []:
183- globals .attached_role_policies_list [rn ]= False
184- else :
185- globals .attached_role_policies_list [rn ]= response ['AttachedPolicies' ]
173+ # Get attached policies
174+ attached_policies = client .list_attached_role_policies (RoleName = role_name )
175+
176+ # Get inline policies
177+ inline_policies = client .list_role_policies (RoleName = role_name )
178+
179+ return {
180+ 'role_name' : role_name ,
181+ 'attached_policies' : attached_policies ['AttachedPolicies' ] if attached_policies ['AttachedPolicies' ] else False ,
182+ 'inline_policies' : inline_policies ['PolicyNames' ] if inline_policies ['PolicyNames' ] else False
183+ }
184+ except Exception as e :
185+ print (f"Error fetching policies for role { role_name } : { e } " )
186+ return {
187+ 'role_name' : role_name ,
188+ 'attached_policies' : False ,
189+ 'inline_policies' : False
190+ }
191+
192+ # Use ThreadPoolExecutor to parallelize API calls
193+ rcl = len (globals .rolelist )
194+ with concurrent .futures .ThreadPoolExecutor (max_workers = globals .cores ) as executor :
195+ # Submit all role policy fetch tasks
196+ future_to_role = {
197+ executor .submit (fetch_role_policies , role_name ): role_name
198+ for role_name in globals .rolelist .keys ()
199+ }
186200
187- if response1 ['PolicyNames' ] == []:
188- globals .role_policies_list [rn ]= False
189- else :
190- globals .role_policies_list [rn ]= response1 ['PolicyNames' ]
191-
192- globals .tracking_message = "Stage 2 of 10, Building secondary IAM resource lists... " + str (rc )+ " of " + str (rcl )
193- rc = rc + 1
194-
201+ # Process results as they complete
202+ completed = 0
203+ for future in concurrent .futures .as_completed (future_to_role ):
204+ completed += 1
205+ globals .tracking_message = f"Stage 2 of 10, Building secondary IAM resource lists... { completed } of { rcl } "
206+
207+ try :
208+ result = future .result ()
209+ role_name = result ['role_name' ]
210+ globals .attached_role_policies_list [role_name ] = result ['attached_policies' ]
211+ globals .role_policies_list [role_name ] = result ['inline_policies' ]
212+ except Exception as e :
213+ print (f"Error processing result: { e } " )
195214
196215 st2 = datetime .datetime .now ()
197- print ("secondary lists built in " + str (st2 - st1 ))
198-
216+ print ("secondary lists built in " + str (st2 - st1 ))
217+
199218 return
0 commit comments