1- const async = require ( 'async' ) ;
21const fs = require ( 'fs' ) ;
3- const { IAM } = require ( 'aws-sdk' ) ;
2+ const {
3+ IAMClient,
4+ DetachUserPolicyCommand,
5+ DetachRolePolicyCommand,
6+ DeleteUserCommand,
7+ DeleteRoleCommand,
8+ DeletePolicyCommand,
9+ paginateListAttachedUserPolicies,
10+ paginateListAttachedRolePolicies,
11+ paginateListUsers,
12+ paginateListRoles,
13+ paginateListPolicies,
14+ } = require ( '@aws-sdk/client-iam' ) ;
15+ const { NodeHttpHandler } = require ( '@aws-sdk/node-http-handler' ) ;
416const vaultclient = require ( 'vaultclient' ) ;
517const https = require ( 'https' ) ;
618
7- function _deleteAttachedUserPolicies ( iamClient , userName , cb ) {
8- let truncated = true ;
9-
10- async . whilst (
11- ( ) => truncated ,
12- done => iamClient . listAttachedUserPolicies (
13- { UserName : userName } ,
14- ( err , res ) => {
15- if ( err ) {
16- return done ( err ) ;
17- }
18-
19- truncated = res . IsTruncated ;
20- return async . forEach (
21- res . AttachedPolicies ,
22- ( policy , next ) => iamClient . detachUserPolicy ( {
23- PolicyArn : policy . PolicyArn ,
24- UserName : userName ,
25- } , next ) ,
26- done ,
27- ) ;
28- } ,
29- ) ,
30- cb ,
31- ) ;
19+ async function _deleteAttachedUserPolicies ( iamClient , userName ) {
20+ const paginator = paginateListAttachedUserPolicies ( { client : iamClient } , { UserName : userName } ) ;
21+ // eslint-disable-next-line no-restricted-syntax
22+ for await ( const page of paginator ) {
23+ if ( page . AttachedPolicies && page . AttachedPolicies . length > 0 ) {
24+ await Promise . all ( page . AttachedPolicies . map ( policy => iamClient . send ( new DetachUserPolicyCommand ( {
25+ PolicyArn : policy . PolicyArn ,
26+ UserName : userName ,
27+ } ) ) ) ) ;
28+ }
29+ }
3230}
3331
34- function _deleteAttachedRolePolicies ( iamClient , roleName , cb ) {
35- let truncated = true ;
36-
37- async . whilst (
38- ( ) => truncated ,
39- done => iamClient . listAttachedRolePolicies (
40- { RoleName : roleName } ,
41- ( err , res ) => {
42- if ( err ) {
43- return done ( err ) ;
44- }
45-
46- truncated = res . IsTruncated ;
47- return async . forEach (
48- res . AttachedPolicies ,
49- ( policy , next ) => iamClient . detachRolePolicy ( {
50- PolicyArn : policy . PolicyArn ,
51- RoleName : roleName ,
52- } , next ) ,
53- done ,
54- ) ;
55- } ,
56- ) ,
57- cb ,
58- ) ;
32+ async function _deleteAttachedRolePolicies ( iamClient , roleName ) {
33+ const paginator = paginateListAttachedRolePolicies ( { client : iamClient } , { RoleName : roleName } ) ;
34+ // eslint-disable-next-line no-restricted-syntax
35+ for await ( const page of paginator ) {
36+ if ( page . AttachedPolicies && page . AttachedPolicies . length > 0 ) {
37+ await Promise . all ( page . AttachedPolicies . map ( policy => iamClient . send ( new DetachRolePolicyCommand ( {
38+ PolicyArn : policy . PolicyArn ,
39+ RoleName : roleName ,
40+ } ) ) ) ) ;
41+ }
42+ }
5943}
6044
61- function _deleteUsers ( iamClient , cb ) {
62- let truncated = true ;
63-
64- async . whilst (
65- ( ) => truncated ,
66- done => iamClient . listUsers ( ( err , res ) => {
67- if ( err ) {
68- return done ( err ) ;
69- }
70-
71- truncated = res . IsTruncated ;
72- return async . forEach (
73- res . Users ,
74- ( user , next ) => async . series ( [
75- next => _deleteAttachedUserPolicies ( iamClient , user . UserName , next ) ,
76- next => iamClient . deleteUser ( { UserName : user . UserName } , next ) ,
77- ] , next ) ,
78- done ,
79- ) ;
80- } ) ,
81- cb ,
82- ) ;
45+ async function _deleteUsers ( iamClient ) {
46+ const paginator = paginateListUsers ( { client : iamClient } , { } ) ;
47+ // eslint-disable-next-line no-restricted-syntax
48+ for await ( const page of paginator ) {
49+ if ( page . Users && page . Users . length > 0 ) {
50+ await Promise . all ( page . Users . map ( async user => {
51+ await _deleteAttachedUserPolicies ( iamClient , user . UserName ) ;
52+ await iamClient . send ( new DeleteUserCommand ( { UserName : user . UserName } ) ) ;
53+ } ) ) ;
54+ }
55+ }
8356}
8457
85- function _deleteRoles ( iamClient , cb ) {
86- let truncated = true ;
87-
88- async . whilst (
89- ( ) => truncated ,
90- done => iamClient . listRoles ( ( err , res ) => {
91- if ( err ) {
92- return done ( err ) ;
93- }
94-
95- truncated = res . IsTruncated ;
96- return async . forEach (
97- res . Roles ,
98- ( role , next ) => async . series ( [
99- next => _deleteAttachedRolePolicies ( iamClient , role . RoleName , next ) ,
100- next => iamClient . deleteRole ( { RoleName : role . RoleName } , next ) ,
101- ] , next ) ,
102- done ,
103- ) ;
104- } ) ,
105- cb ,
106- ) ;
58+ async function _deleteRoles ( iamClient ) {
59+ const paginator = paginateListRoles ( { client : iamClient } , { } ) ;
60+ // eslint-disable-next-line no-restricted-syntax
61+ for await ( const page of paginator ) {
62+ if ( page . Roles && page . Roles . length > 0 ) {
63+ await Promise . all ( page . Roles . map ( async role => {
64+ await _deleteAttachedRolePolicies ( iamClient , role . RoleName ) ;
65+ await iamClient . send ( new DeleteRoleCommand ( { RoleName : role . RoleName } ) ) ;
66+ } ) ) ;
67+ }
68+ }
10769}
10870
109- function _deletePolicies ( iamClient , cb ) {
110- let truncated = true ;
111-
112- async . whilst (
113- ( ) => truncated ,
114- done => iamClient . listPolicies ( ( err , res ) => {
115- if ( err ) {
116- return done ( err ) ;
117- }
118-
119- truncated = res . IsTruncated ;
120- return async . forEach (
121- res . Policies ,
122- ( policy , next ) => iamClient . deletePolicy ( { PolicyArn : policy . Arn } , next ) ,
123- done ,
124- ) ;
125- } ) ,
126- cb ,
127- ) ;
71+ async function _deletePolicies ( iamClient ) {
72+ const paginator = paginateListPolicies ( { client : iamClient } , { Scope : 'Local' } ) ;
73+ // eslint-disable-next-line no-restricted-syntax
74+ for await ( const page of paginator ) {
75+ if ( page . Policies && page . Policies . length > 0 ) {
76+ await Promise . all ( page . Policies . map ( policy => iamClient . send (
77+ new DeletePolicyCommand ( { PolicyArn : policy . Arn } ) ,
78+ ) ) ) ;
79+ }
80+ }
12881}
12982
13083class VaultClient {
@@ -140,40 +93,40 @@ class VaultClient {
14093 static getIamClient ( accessKey , secretKey , sessionToken ) {
14194 const endpoint = process . env . VAULT_ENDPOINT
14295 || 'http://localhost:8600' ;
143- let ca ;
144- let httpOptions ;
96+ const info = {
97+ endpoint,
98+ region : 'us-east-1' ,
99+ maxAttempts : 1 ,
100+ tls : false ,
101+ credentials : {
102+ accessKeyId : accessKey ,
103+ secretAccessKey : secretKey ,
104+ } ,
105+ } ;
106+
145107 if ( endpoint . startsWith ( 'https://' ) ) {
146- ca = fs . readFileSync (
108+ const ca = fs . readFileSync (
147109 process . env . VAULT_SSL_CA || '/conf/ca.crt' ,
148110 'ascii' ,
149111 ) ;
150- httpOptions = {
151- agent : new https . Agent ( {
112+ info . requestHandler = new NodeHttpHandler ( {
113+ httpsAgent : new https . Agent ( {
152114 ca : [ ca ] ,
153115 } ) ,
154- } ;
116+ } ) ;
117+ info . tls = true ;
155118 }
156- const info = {
157- endpoint,
158- httpOptions,
159- sslEnabled : httpOptions !== undefined ,
160- region : 'us-east-1' ,
161- apiVersion : '2010-05-08' ,
162- signatureVersion : 'v4' ,
163- accessKeyId : accessKey ,
164- secretAccessKey : secretKey ,
165- maxRetries : 0 ,
166- } ;
119+
167120 if ( sessionToken ) {
168- info . sessionToken = sessionToken ;
121+ info . credentials . sessionToken = sessionToken ;
169122 }
170- return new IAM ( info ) ;
123+ return new IAMClient ( info ) ;
171124 }
172125
173126 /**
174127 * Get endpoint information
175128 *
176- * @return {object } Vault endpoint information
129+ * @returns {object } Vault endpoint information
177130 */
178131 static getEndpointInformation ( ) {
179132 let host = '127.0.0.1' ;
@@ -215,7 +168,7 @@ class VaultClient {
215168 /**
216169 * Get an admin client
217170 *
218- * @return {vaultclient.Client } Vault client for admin calls
171+ * @returns {vaultclient.Client } Vault client for admin calls
219172 */
220173 static getAdminClient ( ) {
221174 const adminCredentials = {
@@ -241,17 +194,16 @@ class VaultClient {
241194 * @param {vaultclient.Client } adminClient - Vault client for admin calls
242195 * @param {object } iamClient - IAM client
243196 * @param {string } accountName - account name
244- * @param {function } cb - callback
245197 *
246- * @return { undefined }
198+ * @returns { Promise<void> } Promise that resolves when account deletion is complete
247199 */
248- static deleteVaultAccount ( adminClient , iamClient , accountName , cb ) {
249- async . waterfall ( [
250- next => _deleteUsers ( iamClient , next ) ,
251- next => _deleteRoles ( iamClient , next ) ,
252- next => _deletePolicies ( iamClient , next ) ,
253- next => adminClient . deleteAccount ( accountName , next ) ,
254- ] , cb ) ;
200+ static async deleteVaultAccount ( adminClient , iamClient , accountName ) {
201+ await _deleteUsers ( iamClient ) ;
202+ await _deleteRoles ( iamClient ) ;
203+ await _deletePolicies ( iamClient ) ;
204+ await new Promise ( ( resolve , reject ) => {
205+ adminClient . deleteAccount ( accountName , err => ( err ? reject ( err ) : resolve ( ) ) ) ;
206+ } ) ;
255207 }
256208}
257209module . exports = VaultClient ;
0 commit comments