forked from aquasecurity/cloudsploit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Alibaba ram user access keys rotation plugin with spec file (aquasecu…
…rity#722) * Alibaba plugin added for ram user access keys rotation with spec files * Messages updated * Lint error fixed * Update plugins/alibaba/ram/accessKeysRotation.js Co-authored-by: AkhtarAmir <makhtar.pucit@gmail.com> Co-authored-by: Gio Rodriguez <gioroddev@gmail.com>
- Loading branch information
1 parent
b67f778
commit e61b78e
Showing
4 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
var helpers = require('../../../helpers/alibaba'); | ||
|
||
module.exports = { | ||
title: 'Access Keys Rotation', | ||
category: 'RAM', | ||
description: 'Ensure that RAM user access keys are rotated after regular interval of time.', | ||
more_info: 'Access keys should be rotated to avoid having them accidentally exposed.', | ||
link: 'https://www.alibabacloud.com/help/doc-detail/152682.htm', | ||
recommended_action: 'Rotate the access keys every desired number of days', | ||
apis: ['RAM:ListUsers', 'RAM:ListAccessKeys', 'STS:GetCallerIdentity'], | ||
settings: { | ||
ram_access_keys_rotation_interval: { | ||
name: 'RAM User Access Keys Rotation Interval', | ||
description: 'Return a failing result when access keys exceed this number of days without being rotated', | ||
regex: '^[1-9]{1}[0-9]{0,3}$', | ||
default: '90' | ||
} | ||
}, | ||
|
||
run: function(cache, settings, callback) { | ||
var results = []; | ||
var source = {}; | ||
|
||
var accessKeyRotationInterval = parseInt(settings.ram_access_keys_rotation_interval || this.settings.ram_access_keys_rotation_interval.default); | ||
var region = helpers.defaultRegion(settings); | ||
var accountId = helpers.addSource(cache, source, ['sts', 'GetCallerIdentity', region, 'data']); | ||
var listUsers = helpers.addSource(cache, source, | ||
['ram', 'ListUsers', region]); | ||
|
||
if (!listUsers) return callback(null, results, source); | ||
|
||
if (listUsers.err || !listUsers.data) { | ||
helpers.addResult(results, 3, | ||
'Unable to query RAM users' + helpers.addError(listUsers), region); | ||
return callback(null, results, source); | ||
} | ||
|
||
if (!listUsers.data.length) { | ||
helpers.addResult(results, 0, 'No RAM users found', region); | ||
return callback(null, results, source); | ||
} | ||
|
||
for (var user of listUsers.data) { | ||
if (!user.UserName) continue; | ||
|
||
var getAccessKey = helpers.addSource(cache, source, | ||
['ram', 'ListAccessKeys', region, user.UserName]); | ||
|
||
if (getAccessKey.err || !getAccessKey.data) { | ||
helpers.addResult(results, 3, | ||
'Unable to query user access keys' + helpers.addError(getAccessKey), region); | ||
continue; | ||
} | ||
|
||
let resource = helpers.createArn('ram', accountId, 'user', user.UserName); | ||
if (getAccessKey.data.AccessKeys && getAccessKey.data.AccessKeys.AccessKey && getAccessKey.data.AccessKeys.AccessKey.length) { | ||
let activeKeyFound = false; | ||
for (var accessKey of getAccessKey.data.AccessKeys.AccessKey) { | ||
if (accessKey.Status && accessKey.Status == 'Active') { | ||
activeKeyFound = true; | ||
resource = resource + ':' + accessKey.AccessKeyId; | ||
let createDate = accessKey.CreateDate; | ||
var currentDate = new Date(); | ||
var createDateFormat = new Date(createDate); | ||
|
||
var diffInDays = helpers.daysBetween(currentDate, createDateFormat); | ||
if (diffInDays <= accessKeyRotationInterval) { | ||
helpers.addResult(results, 0, | ||
`RAM user access key was last rotated ${diffInDays} days ago which is equal to or less than ${accessKeyRotationInterval}`, region, resource); | ||
} else { | ||
helpers.addResult(results, 2, | ||
`RAM user access key was last rotated ${diffInDays} days ago which is greater than ${accessKeyRotationInterval}`, region, resource); | ||
} | ||
} | ||
} | ||
if (!activeKeyFound) { | ||
helpers.addResult(results, 0, | ||
'RAM user does not have any active access keys', region, resource); | ||
} | ||
} else { | ||
helpers.addResult(results, 0, | ||
'RAM user does not have any access keys', region, resource); | ||
} | ||
} | ||
|
||
callback(null, results, source); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
var expect = require('chai').expect; | ||
var helpers = require('../../../helpers/alibaba'); | ||
var accessKeysRotation = require('./accessKeysRotation') | ||
|
||
var passDate = new Date(); | ||
passDate.setMonth(passDate.getMonth() - 2); | ||
var failDate = new Date(); | ||
failDate.setMonth(failDate.getMonth() - 7); | ||
|
||
const listUsers = [ | ||
{ | ||
"UserName": "aqua", | ||
"UserId": "254529020129829608", | ||
}, | ||
{ | ||
"UserName": "cloudsploit", | ||
"UserId": "283806919721151694", | ||
} | ||
]; | ||
|
||
const getUserLoginProfile = [ | ||
{ | ||
AccessKeys: { | ||
AccessKey: [ | ||
{ | ||
Status: "Active", | ||
AccessKeyId: "LTAI5tD6ekrSssrWq5rNa4JQ", | ||
CreateDate: failDate, | ||
}, | ||
], | ||
}, | ||
}, | ||
{ | ||
AccessKeys: { | ||
AccessKey: [ | ||
{ | ||
Status: "Active", | ||
AccessKeyId: "LTAI5tD6ekrSssrWq5rNa4JQ", | ||
CreateDate: passDate, | ||
}, | ||
], | ||
}, | ||
}, | ||
{ | ||
AccessKeys: { | ||
AccessKey: [], | ||
}, | ||
} | ||
]; | ||
|
||
const createCache = (users, accessKeys, accessKeysError, error) => { | ||
let userName = (users && users.length) ? users[0].UserName : null; | ||
return { | ||
ram: { | ||
ListUsers: { | ||
'cn-hangzhou': { | ||
data: users, | ||
err: error | ||
} | ||
}, | ||
ListAccessKeys: { | ||
'cn-hangzhou': { | ||
[userName]: { | ||
data: accessKeys, | ||
err: accessKeysError | ||
} | ||
} | ||
}, | ||
} | ||
} | ||
} | ||
|
||
describe('accessKeysRotation', function () { | ||
describe('run', function () { | ||
it('should FAIL if RAM user access keys are not rotated every 90 days or less', function (done) { | ||
const cache = createCache([listUsers[0]], getUserLoginProfile[0], null, null); | ||
accessKeysRotation.run(cache, {}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(2); | ||
expect(results[0].message).to.include('which is greater than'); | ||
expect(results[0].region).to.equal('cn-hangzhou'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should PASS if RAM user access keys are not rotated every 90 days or less', function (done) { | ||
const cache = createCache([listUsers[0]], getUserLoginProfile[1], null, null); | ||
accessKeysRotation.run(cache, {}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].message).to.include('which is equal to or less than'); | ||
expect(results[0].region).to.equal('cn-hangzhou'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should PASS if RAM user does not have any access keys', function (done) { | ||
const cache = createCache([listUsers[1]], getUserLoginProfile[2], null, null); | ||
accessKeysRotation.run(cache, {}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].message).to.include('RAM user does not have any access keys'); | ||
expect(results[0].region).to.equal('cn-hangzhou'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should PASS if No RAM users found', function (done) { | ||
const cache = createCache([]); | ||
accessKeysRotation.run(cache, {}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].message).to.include('No RAM users found'); | ||
expect(results[0].region).to.equal('cn-hangzhou'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should UNKNOWN if unable to query user access keys', function (done) { | ||
const cache = createCache([listUsers[0]], null, [], null); | ||
accessKeysRotation.run(cache, {}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(3); | ||
expect(results[0].message).to.include('Unable to query user access keys'); | ||
expect(results[0].region).to.equal('cn-hangzhou'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should UNKNOWN if unable to query RAM users', function (done) { | ||
const cache = createCache(null, null, null, null); | ||
accessKeysRotation.run(cache, {}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(3); | ||
expect(results[0].message).to.include('Unable to query RAM users'); | ||
expect(results[0].region).to.equal('cn-hangzhou'); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
}) |