From 2aaa2306ca88dd4ec84c0429c65c4b2e3aa6575c Mon Sep 17 00:00:00 2001 From: abdullahaslam306 Date: Thu, 23 Mar 2023 15:07:31 +0500 Subject: [PATCH 1/4] role level access --- exports.js | 1 + plugins/aws/backup/backupVaultRoleAccess.js | 91 +++++++++++ .../aws/backup/backupVaultRoleAccess.spec.js | 147 ++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 plugins/aws/backup/backupVaultRoleAccess.js create mode 100644 plugins/aws/backup/backupVaultRoleAccess.spec.js diff --git a/exports.js b/exports.js index 9d9cc67593..44246e8e79 100644 --- a/exports.js +++ b/exports.js @@ -592,6 +592,7 @@ module.exports = { 'backupDeletionProtection' : require(__dirname + '/plugins/aws/backup/backupDeletionProtection.js'), 'compliantLifecyleConfigured' : require(__dirname + '/plugins/aws/backup/compliantLifecyleConfigured.js'), 'backupVaultHasTags' : require(__dirname + '/plugins/aws/backup/backupVaultHasTags.js'), + 'backupVaultRoleAccess' : require(__dirname + '/plugins/aws/backup/backupVaultRoleAccess.js'), 'equipmentdatasetEncrypted' : require(__dirname + '/plugins/aws/lookout/equipmentdatasetEncrypted.js'), diff --git a/plugins/aws/backup/backupVaultRoleAccess.js b/plugins/aws/backup/backupVaultRoleAccess.js new file mode 100644 index 0000000000..8f242bca60 --- /dev/null +++ b/plugins/aws/backup/backupVaultRoleAccess.js @@ -0,0 +1,91 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Backup Vault Role Access', + category: 'Backup', + domain: 'Storage', + description: 'Ensure that AWS Backup Vault are accessed through roles.', + more_info: 'As a security best practice and to adhere to compliance standards, ensure only role level access is allowed on a Backup vault.', + recommended_action: 'Modify access policy and give only role level access to backup vault.', + link: 'https://docs.aws.amazon.com/aws-backup/latest/devguide/creating-a-vault-access-policy.html', + apis: ['Backup:listBackupVaults', 'Backup:getBackupVaultAccessPolicy'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.backup, function(region, rcb){ + var listBackupVaults = helpers.addSource(cache, source, + ['backup', 'listBackupVaults', region]); + + if (!listBackupVaults) return rcb(); + + if (listBackupVaults.err || !listBackupVaults.data) { + helpers.addResult(results, 3, + `Unable to query for Backup vault list: ${helpers.addError(listBackupVaults)}`, region); + return rcb(); + } + + if (!listBackupVaults.data.length) { + helpers.addResult(results, 0, 'No Backup vaults found', region); + return rcb(); + } + + for (let vault of listBackupVaults.data){ + if (!vault.BackupVaultArn || !vault.BackupVaultName) continue; + + let resource = vault.BackupVaultArn; + + let getBackupVaultAccessPolicy = helpers.addSource(cache, source, + ['backup', 'getBackupVaultAccessPolicy', region, vault.BackupVaultName]); + + if (getBackupVaultAccessPolicy && getBackupVaultAccessPolicy.err && getBackupVaultAccessPolicy.err.code && + getBackupVaultAccessPolicy.err.code == 'ResourceNotFoundException') { + helpers.addResult(results, 2, + 'No access policy found for Backup vault', region, resource); + continue; + } + + if (!getBackupVaultAccessPolicy || getBackupVaultAccessPolicy.err || !getBackupVaultAccessPolicy.data) { + helpers.addResult(results, 3, `Unable to get Backup vault access policy: ${helpers.addError(getBackupVaultAccessPolicy)}`, region, resource); + continue; + } + + var statements = helpers.normalizePolicyDocument(getBackupVaultAccessPolicy.data.Policy); + + if (!statements || !statements.length) { + helpers.addResult(results, 0, + 'The Backup Vault policy does not have trust relationship statements', + region, resource); + return; + } + + var actions = []; + let roleAccess = true; + for (var statement of statements) { + var principalEval = helpers.globalPrincipal(statement.Principal); + if (principalEval && statement.Effect.toUpperCase() === 'ALLOW') { + roleAccess = false; + break; + } + + } + + if (!roleAccess) { + helpers.addResult(results, 2, + 'Backup Vault does not have role level access only' + actions, + region, resource); + } else { + helpers.addResult(results, 0, + 'Backup Vault have role level access only', + region, resource); + } + } + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/backup/backupVaultRoleAccess.spec.js b/plugins/aws/backup/backupVaultRoleAccess.spec.js new file mode 100644 index 0000000000..455bf12f1e --- /dev/null +++ b/plugins/aws/backup/backupVaultRoleAccess.spec.js @@ -0,0 +1,147 @@ +var expect = require('chai').expect; +const backupVaultRoleAccess = require('./backupVaultRoleAccess'); + +const listBackupVaults = [ + { + "BackupVaultName": "test", + "BackupVaultArn": "arn:aws:backup:us-east-1:000011112222:backup-vault:test", + "CreationDate": "2021-11-26T17:05:36.477000+05:00", + "EncryptionKeyArn": "arn:aws:kms:us-east-1:000011112222:key/228d6374-d201-428d-b084-842fc7b2d148", + "CreatorRequestId": "Default", + "NumberOfRecoveryPoints": 0 + }, + { + "BackupVaultName": "test", + "BackupVaultArn": "arn:aws:backup:us-east-1:000011112222:backup-vault:test", + "CreationDate": "2022-01-21T23:05:24.095000+05:00", + "EncryptionKeyArn": "arn:aws:kms:us-east-1:000011112222:key/ad013a33-b01d-4d88-ac97-127399c18b3e", + "CreatorRequestId": "967e0cd4-59c5-471c-8d4d-582a9ee27433", + "NumberOfRecoveryPoints": 0 + } +]; + + +const getBackupVaultAccessPolicy =[ + { + "BackupVaultName": "test", + "BackupVaultArn": "arn:aws:backup:us-east-1:000011112222:backup-vault:test", + "Policy": { + "Version":"2012-10-17", + "Statement":[ + { + "Effect": 'Allow', + "Principal": 'arn:aws:iam::112233445566:role/MyRole', + "Action": [ 'backup:DeleteRecoveryPoint' ], + "Resource": [ '*' ] + }, + ], + } + } , + { + "BackupVaultName": "test", + "BackupVaultArn": "arn:aws:backup:us-east-1:000011112222:backup-vault:test", + "Policy": { + "Version":"2012-10-17", + "Statement":[ + { + "Effect": 'Allow', + "Principal": '*', + "Action": [ 'backup:CopyIntoBackupVault' ], + "Resource": [ '*' ], + }, + ], + } + } +]; + +const createCache = (listBackupVaults, getBackupVaultAccessPolicy, listBackupVaultsErr, getBackupVaultAccessPolicyErr) => { + let name = (listBackupVaults && listBackupVaults.length) ? listBackupVaults[0].BackupVaultName : null; + return { + backup: { + listBackupVaults: { + 'us-east-1': { + data: listBackupVaults, + err: listBackupVaultsErr + } + }, + getBackupVaultAccessPolicy: { + 'us-east-1': { + [name]: { + data: getBackupVaultAccessPolicy, + err: getBackupVaultAccessPolicyErr + } + } + } + } + } +}; + + +describe('backupVaultRoleAccess', function () { + describe('run', function () { + it('should PASS if Backup Vault have role level access only', function (done) { + const cache = createCache([listBackupVaults[1]], getBackupVaultAccessPolicy[0]); + backupVaultRoleAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Backup Vault have role level access only') + done(); + }); + }); + + it('should FAIL if Backup Vault does not have role level access only', function (done) { + const cache = createCache([listBackupVaults[0]], getBackupVaultAccessPolicy[1] ); + backupVaultRoleAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('Backup Vault does not have role level access only') + done(); + }); + }); + + it('should FAIL if no access policy found for Backup vault', function (done) { + const cache = createCache([listBackupVaults[0]], null , null, { message: 'An error occurred (ResourceNotFoundException) when calling the GetBackupVaultAccessPolicy operation', code : 'ResourceNotFoundException' } ); + backupVaultRoleAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('No access policy found for Backup vault') + done(); + }); + }); + + + it('should PASS if no Backup vault list found', function (done) { + const cache = createCache([]); + backupVaultRoleAccess.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + expect(results[0].region).to.equal('us-east-1'); + expect(results[0].message).to.include('No Backup vaults found') + done(); + }); + }); + + it('should UNKNOWN if Unable to query for Backup vault list', function (done) { + const cache = createCache(null, { message: 'Unable to query for Backup vault list' }); + backupVaultRoleAccess.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 for Backup vault list') + done(); + }); + }); + + it('should UNKNOWN if Unable to get Backup vault policy', function (done) { + const cache = createCache([listBackupVaults[0]], null, null, { message: 'Unable to get Backup vault policy' }); + backupVaultRoleAccess.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 get Backup vault policy') + done(); + }); + }); + }); +}); From f21adb20c70b1c3cf2eb5b979b6ce8ddc1c736b8 Mon Sep 17 00:00:00 2001 From: abdullahaslam306 Date: Tue, 4 Apr 2023 19:28:07 +0500 Subject: [PATCH 2/4] PR issues resolved --- plugins/aws/backup/backupVaultRoleAccess.js | 20 +++++-------------- .../aws/backup/backupVaultRoleAccess.spec.js | 12 ----------- 2 files changed, 5 insertions(+), 27 deletions(-) diff --git a/plugins/aws/backup/backupVaultRoleAccess.js b/plugins/aws/backup/backupVaultRoleAccess.js index 8f242bca60..712b28c900 100644 --- a/plugins/aws/backup/backupVaultRoleAccess.js +++ b/plugins/aws/backup/backupVaultRoleAccess.js @@ -5,7 +5,7 @@ module.exports = { title: 'Backup Vault Role Access', category: 'Backup', domain: 'Storage', - description: 'Ensure that AWS Backup Vault are accessed through roles.', + description: 'Ensure that AWS Backup Vaults are accessed through roles.', more_info: 'As a security best practice and to adhere to compliance standards, ensure only role level access is allowed on a Backup vault.', recommended_action: 'Modify access policy and give only role level access to backup vault.', link: 'https://docs.aws.amazon.com/aws-backup/latest/devguide/creating-a-vault-access-policy.html', @@ -40,15 +40,8 @@ module.exports = { let getBackupVaultAccessPolicy = helpers.addSource(cache, source, ['backup', 'getBackupVaultAccessPolicy', region, vault.BackupVaultName]); - - if (getBackupVaultAccessPolicy && getBackupVaultAccessPolicy.err && getBackupVaultAccessPolicy.err.code && - getBackupVaultAccessPolicy.err.code == 'ResourceNotFoundException') { - helpers.addResult(results, 2, - 'No access policy found for Backup vault', region, resource); - continue; - } - if (!getBackupVaultAccessPolicy || getBackupVaultAccessPolicy.err || !getBackupVaultAccessPolicy.data) { + if (!getBackupVaultAccessPolicy || getBackupVaultAccessPolicy.err || !getBackupVaultAccessPolicy.data || !getBackupVaultAccessPolicy.data.Policy) { helpers.addResult(results, 3, `Unable to get Backup vault access policy: ${helpers.addError(getBackupVaultAccessPolicy)}`, region, resource); continue; } @@ -59,10 +52,9 @@ module.exports = { helpers.addResult(results, 0, 'The Backup Vault policy does not have trust relationship statements', region, resource); - return; + continue; } - var actions = []; let roleAccess = true; for (var statement of statements) { var principalEval = helpers.globalPrincipal(statement.Principal); @@ -75,12 +67,10 @@ module.exports = { if (!roleAccess) { helpers.addResult(results, 2, - 'Backup Vault does not have role level access only' + actions, - region, resource); + 'Backup Vault does not have role level access only' , region, resource); } else { helpers.addResult(results, 0, - 'Backup Vault have role level access only', - region, resource); + 'Backup Vault have role level access only', region, resource); } } rcb(); diff --git a/plugins/aws/backup/backupVaultRoleAccess.spec.js b/plugins/aws/backup/backupVaultRoleAccess.spec.js index 455bf12f1e..faf9e5dcfc 100644 --- a/plugins/aws/backup/backupVaultRoleAccess.spec.js +++ b/plugins/aws/backup/backupVaultRoleAccess.spec.js @@ -101,18 +101,6 @@ describe('backupVaultRoleAccess', function () { }); }); - it('should FAIL if no access policy found for Backup vault', function (done) { - const cache = createCache([listBackupVaults[0]], null , null, { message: 'An error occurred (ResourceNotFoundException) when calling the GetBackupVaultAccessPolicy operation', code : 'ResourceNotFoundException' } ); - backupVaultRoleAccess.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); - expect(results[0].region).to.equal('us-east-1'); - expect(results[0].message).to.include('No access policy found for Backup vault') - done(); - }); - }); - - it('should PASS if no Backup vault list found', function (done) { const cache = createCache([]); backupVaultRoleAccess.run(cache, {}, (err, results) => { From f594275215b7c49e6f3b586b3043b2ba13f3cccc Mon Sep 17 00:00:00 2001 From: abdullahaslam306 Date: Tue, 4 Apr 2023 19:30:31 +0500 Subject: [PATCH 3/4] lambda run time update --- plugins/aws/lambda/lambdaOldRuntimes.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/lambda/lambdaOldRuntimes.spec.js b/plugins/aws/lambda/lambdaOldRuntimes.spec.js index e5ecabaade..6689e6fd27 100644 --- a/plugins/aws/lambda/lambdaOldRuntimes.spec.js +++ b/plugins/aws/lambda/lambdaOldRuntimes.spec.js @@ -5,7 +5,7 @@ const listFunctions = [ { "FunctionName": "test-lambda", "FunctionArn": "arn:aws:lambda:us-east-1:000011112222:function:test-lambda", - "Runtime": "nodejs12.x", + "Runtime": "nodejs14.x", "Role": "arn:aws:iam::000011112222:role/lambda-role", "Handler": "index.handler", "TracingConfig": { "Mode": "PassThrough" } From c3f6718172df73f8f18a7a3454ad9fb924ca0f65 Mon Sep 17 00:00:00 2001 From: alphadev4 <113519745+alphadev4@users.noreply.github.com> Date: Wed, 5 Apr 2023 16:01:00 +0500 Subject: [PATCH 4/4] Apply suggestions from code review --- plugins/aws/backup/backupVaultRoleAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/backup/backupVaultRoleAccess.js b/plugins/aws/backup/backupVaultRoleAccess.js index 712b28c900..5b87e16656 100644 --- a/plugins/aws/backup/backupVaultRoleAccess.js +++ b/plugins/aws/backup/backupVaultRoleAccess.js @@ -5,7 +5,7 @@ module.exports = { title: 'Backup Vault Role Access', category: 'Backup', domain: 'Storage', - description: 'Ensure that AWS Backup Vaults are accessed through roles.', + description: 'Ensure that AWS Backup vaults are accessed through roles.', more_info: 'As a security best practice and to adhere to compliance standards, ensure only role level access is allowed on a Backup vault.', recommended_action: 'Modify access policy and give only role level access to backup vault.', link: 'https://docs.aws.amazon.com/aws-backup/latest/devguide/creating-a-vault-access-policy.html',