@@ -6,12 +6,13 @@ import { AWSError } from 'aws-sdk/lib/error'
66
77import IAM , {
88 AttachedPolicy ,
9+ GetAccountAuthorizationDetailsResponse ,
910 GetRoleResponse ,
1011 ListAttachedRolePoliciesResponse ,
11- ListRolePoliciesResponse ,
1212 ListRolesResponse ,
1313 ListRoleTagsResponse ,
1414 Role ,
15+ RoleDetail ,
1516} from 'aws-sdk/clients/iam'
1617import { Config } from 'aws-sdk/lib/config'
1718
@@ -38,10 +39,11 @@ const customRetrySettings = setAwsRetryOptions({
3839} )
3940
4041export interface RawAwsIamRole extends Omit < Role , 'Tags' > {
41- Policies : string [ ]
4242 ManagedPolicies : AttachedPolicy [ ]
4343 region : string
4444 Tags ?: TagMap
45+ PermissionsBoundaryArn : string
46+ InlinePolicies : Array < { name : string ; document : string } >
4547}
4648
4749const roleByRoleName = async (
@@ -99,68 +101,73 @@ const tagsByRoleName = async (
99101 )
100102 } )
101103
102- const policiesByRoleName = async (
104+ const managedPoliciesByRoleName = async (
103105 iam : IAM ,
104106 { RoleName } : Role
105- ) : Promise < { RoleName : string ; Policies : string [ ] } > =>
107+ ) : Promise < { RoleName : string ; ManagedPolicies : AttachedPolicy [ ] } > =>
106108 new Promise ( resolve => {
107- iam . listRolePolicies (
109+ iam . listAttachedRolePolicies (
108110 { RoleName } ,
109- ( err : AWSError , data : ListRolePoliciesResponse ) => {
111+ ( err : AWSError , data : ListAttachedRolePoliciesResponse ) => {
110112 if ( err ) {
111113 errorLog . generateAwsErrorLog ( {
112- functionName : 'iam:listRolePolicies ' ,
114+ functionName : 'iam:listAttachedRolePolicies ' ,
113115 err,
114116 } )
115117 }
116118
117119 if ( ! isEmpty ( data ) ) {
118- const { PolicyNames = [ ] } = data
120+ const { AttachedPolicies = [ ] } = data
119121
120- resolve ( { RoleName, Policies : PolicyNames } )
122+ resolve ( {
123+ RoleName,
124+ ManagedPolicies : AttachedPolicies ,
125+ } )
121126 }
122127
123128 resolve ( null )
124129 }
125130 )
126131 } )
127132
128- const managedPoliciesByRoleName = async (
133+ export const getAccountAuthorizationDetails = async (
129134 iam : IAM ,
130- { RoleName } : Role
131- ) : Promise < { RoleName : string ; ManagedPolicies : AttachedPolicy [ ] } > =>
135+ marker ?: string
136+ ) : Promise < RoleDetail [ ] > =>
132137 new Promise ( resolve => {
133- iam . listAttachedRolePolicies (
134- { RoleName } ,
135- ( err : AWSError , data : ListAttachedRolePoliciesResponse ) => {
138+ const result : RoleDetail [ ] = [ ]
139+ iam . getAccountAuthorizationDetails (
140+ { Filter : [ 'Role' ] , Marker : marker } ,
141+ async ( err : AWSError , data : GetAccountAuthorizationDetailsResponse ) => {
136142 if ( err ) {
137143 errorLog . generateAwsErrorLog ( {
138- functionName : 'iam:listAttachedRolePolicies ' ,
144+ functionName : 'iam:getAccountAuthorizationDetails ' ,
139145 err,
140146 } )
141147 }
142-
143- if ( ! isEmpty ( data ) ) {
144- const { AttachedPolicies = [ ] } = data
145-
146- resolve ( {
147- RoleName,
148- ManagedPolicies : AttachedPolicies ,
149- } )
148+ if ( ! isEmpty ( data ) && ! isEmpty ( data . RoleDetailList ) ) {
149+ const { Marker, IsTruncated, RoleDetailList } = data
150+ result . push ( ...RoleDetailList )
151+ if ( IsTruncated ) {
152+ result . push ( ...( await getAccountAuthorizationDetails ( iam , Marker ) ) )
153+ }
154+ resolve ( result )
150155 }
151-
152- resolve ( null )
153156 }
154157 )
155158 } )
156159
157- export const listIamRoles = async (
158- iam : IAM ,
160+ export const listIamRoles = async ( {
161+ iam,
162+ marker,
163+ roleAuthorizationDetails,
164+ } : {
165+ iam : IAM
159166 marker ?: string
160- ) : Promise < RawAwsIamRole [ ] > =>
167+ roleAuthorizationDetails : RoleDetail [ ]
168+ } ) : Promise < RawAwsIamRole [ ] > =>
161169 new Promise ( resolve => {
162170 const result : RawAwsIamRole [ ] = [ ]
163- const policiesByRoleNamePromises = [ ]
164171 const tagsByRoleNamePromises = [ ]
165172 const managedPoliciesByRoleNamePromises = [ ]
166173 const roleByRoleNamePromises : Promise < { RoleName : string ; Role : Role } > [ ] =
@@ -180,23 +187,27 @@ export const listIamRoles = async (
180187
181188 roles . map ( role => {
182189 tagsByRoleNamePromises . push ( tagsByRoleName ( iam , role ) )
183- policiesByRoleNamePromises . push ( policiesByRoleName ( iam , role ) )
184190 managedPoliciesByRoleNamePromises . push (
185191 managedPoliciesByRoleName ( iam , role )
186192 )
187193 roleByRoleNamePromises . push ( roleByRoleName ( iam , role ) )
188194 } )
189195
190196 const tags = await Promise . all ( tagsByRoleNamePromises )
191- const policies = await Promise . all ( policiesByRoleNamePromises )
192197 const managedPolicies = await Promise . all (
193198 managedPoliciesByRoleNamePromises
194199 )
195200 const detailedRoles = await Promise . all ( roleByRoleNamePromises )
196201
197202 result . push (
198203 ...roles . map (
199- ( { RoleName, AssumeRolePolicyDocument, Tags, ...role } ) => {
204+ ( {
205+ RoleName,
206+ AssumeRolePolicyDocument,
207+ PermissionsBoundary,
208+ Tags,
209+ ...role
210+ } ) => {
200211 return {
201212 RoleName,
202213 AssumeRolePolicyDocument : decodeURIComponent (
@@ -207,24 +218,33 @@ export const listIamRoles = async (
207218 RoleLastUsed : detailedRoles ?. find (
208219 r => r ?. RoleName === RoleName
209220 ) ?. Role . RoleLastUsed ,
210- Policies :
211- policies
212- ?. filter ( p => p ?. RoleName === RoleName )
213- . map ( p => p . Policies )
214- . reduce ( ( current , acc ) => [ ...acc , ...current ] , [ ] ) || [ ] ,
215221 ManagedPolicies :
216222 managedPolicies
217223 ?. filter ( p => p ?. RoleName === RoleName )
218224 . map ( p => p . ManagedPolicies )
219225 . reduce ( ( current , acc ) => [ ...acc , ...current ] , [ ] ) || [ ] ,
220226 Tags : tags . find ( t => t ?. RoleName === RoleName ) ?. Tags || { } ,
227+ PermissionsBoundaryArn :
228+ PermissionsBoundary . PermissionsBoundaryArn ,
229+ InlinePolicies : roleAuthorizationDetails
230+ . find ( rAD => rAD . RoleName === RoleName )
231+ . RolePolicyList . map ( rPl => ( {
232+ name : rPl . PolicyName ,
233+ document : rPl . PolicyDocument ,
234+ } ) ) ,
221235 }
222236 }
223237 )
224238 )
225239
226240 if ( IsTruncated ) {
227- result . push ( ...( await listIamRoles ( iam , Marker ) ) )
241+ result . push (
242+ ...( await listIamRoles ( {
243+ iam,
244+ marker : Marker ,
245+ roleAuthorizationDetails,
246+ } ) )
247+ )
228248 }
229249
230250 resolve ( result )
@@ -259,8 +279,12 @@ export default async ({
259279
260280 logger . debug ( lt . lookingForIamRoles )
261281
282+ // Fetch role authorization details first
283+ const roleAuthorizationDetails = await getAccountAuthorizationDetails (
284+ client
285+ )
262286 // Fetch IAM Roles
263- rolesData = await listIamRoles ( client )
287+ rolesData = await listIamRoles ( { iam : client , roleAuthorizationDetails } )
264288
265289 errorLog . reset ( )
266290 logger . debug ( lt . foundRoles ( rolesData . length ) )
0 commit comments