@@ -17,8 +17,11 @@ import IAM, {
1717 ListUserPoliciesResponse ,
1818 ListUsersResponse ,
1919 ListUserTagsResponse ,
20+ ListVirtualMFADevicesRequest ,
21+ ListVirtualMFADevicesResponse ,
2022 MFADevice ,
2123 User ,
24+ VirtualMFADevice ,
2225} from 'aws-sdk/clients/iam'
2326import { Config } from 'aws-sdk/lib/config'
2427
@@ -75,6 +78,7 @@ export interface RawAwsIamUserReport {
7578export interface RawAwsIamUser extends Omit < User , 'Tags' > {
7679 AccessKeyLastUsedData : RawAwsAccessKey [ ]
7780 MFADevices : MFADevice [ ]
81+ VirtualMFADevices ?: VirtualMFADevice [ ]
7882 Groups : string [ ]
7983 Policies : string [ ]
8084 ManagedPolicies : AttachedPolicy [ ]
@@ -286,6 +290,45 @@ export const listMFADevicesByUsername = async (
286290 )
287291 } )
288292
293+ export const listVirtualMFADevices = async (
294+ iam : IAM
295+ ) : Promise < VirtualMFADevice [ ] > =>
296+ new Promise ( resolve => {
297+ const virtualMFADeviceList : VirtualMFADevice [ ] = [ ]
298+ let args : ListVirtualMFADevicesRequest = { }
299+ const listAllVirtualMFADevices = ( marker ?: string ) => {
300+ if ( marker ) {
301+ args = { ...args , Marker : marker }
302+ }
303+ try {
304+ iam . listVirtualMFADevices (
305+ args ,
306+ async ( err : AWSError , data : ListVirtualMFADevicesResponse ) => {
307+ if ( err ) {
308+ errorLog . generateAwsErrorLog ( {
309+ functionName : 'iam:listVirtualMFADevices' ,
310+ err,
311+ } )
312+ }
313+
314+ const { VirtualMFADevices = [ ] , IsTruncated, Marker } = data
315+
316+ virtualMFADeviceList . push ( ...VirtualMFADevices )
317+
318+ if ( IsTruncated ) {
319+ listAllVirtualMFADevices ( Marker )
320+ }
321+
322+ resolve ( virtualMFADeviceList )
323+ }
324+ )
325+ } catch ( error ) {
326+ resolve ( [ ] )
327+ }
328+ }
329+ listAllVirtualMFADevices ( )
330+ } )
331+
289332export const listIamUsers = async (
290333 iam : IAM ,
291334 marker ?: string
@@ -446,6 +489,9 @@ export default async ({
446489 // Fetch IAM Report Credential
447490 const credentialReport = await getCredentialReportData ( client )
448491
492+ // Fetch all virtual MFA Devices
493+ const virtualMFADevices = await listVirtualMFADevices ( client )
494+
449495 usersData = credentialReport
450496 . map ( userReport => {
451497 const user = iamUsers . find ( u => u . Arn === userReport . Arn )
@@ -459,6 +505,9 @@ export default async ({
459505 CreateDate : new Date ( ) ,
460506 AccessKeyLastUsedData : [ ] ,
461507 MFADevices : [ ] ,
508+ VirtualMFADevices :
509+ virtualMFADevices ?. filter ( d => d . User ?. Arn === userReport . Arn ) ||
510+ [ ] ,
462511 Groups : [ ] ,
463512 Policies : [ ] ,
464513 ManagedPolicies : [ ] ,
@@ -471,8 +520,13 @@ export default async ({
471520 return undefined
472521 }
473522
523+ const { Arn, ...rest } = user
524+
474525 return {
475- ...user ,
526+ Arn,
527+ VirtualMFADevices :
528+ virtualMFADevices ?. filter ( d => d . User ?. Arn === Arn ) || [ ] ,
529+ ...rest ,
476530 ReportData : userReport ,
477531 }
478532 } )
0 commit comments