Skip to content

Commit 2d6914d

Browse files
committed
Merge branch 'improvement/ZENKO-5054' into q/2.13
2 parents bc3ddfa + ef5f304 commit 2d6914d

File tree

26 files changed

+5504
-2602
lines changed

26 files changed

+5504
-2602
lines changed

tests/ctst/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
"scubaclient": "git+https://github.com/scality/scubaclient#^1.1.2"
2222
},
2323
"devDependencies": {
24-
"@aws-sdk/client-iam": "^3.582.0",
25-
"@aws-sdk/client-s3": "^3.583.0",
26-
"@aws-sdk/client-sts": "^3.583.0",
24+
"@aws-sdk/client-iam": "^3.901.0",
25+
"@aws-sdk/client-s3": "^3.901.0",
26+
"@aws-sdk/client-sts": "^3.901.0",
2727
"@eslint/compat": "^1.1.1",
2828
"cli-testing": "github:scality/cli-testing.git#1.2.4",
2929
"eslint": "^9.9.1",

tests/ctst/yarn.lock

Lines changed: 1097 additions & 35 deletions
Large diffs are not rendered by default.
Lines changed: 97 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,83 @@
1-
const async = require('async');
21
const 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');
416
const vaultclient = require('vaultclient');
517
const 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

13083
class 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
}
257209
module.exports = VaultClient;

0 commit comments

Comments
 (0)