From 4af0f4443ada3f656603aef00a892b6523a532a6 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:56:05 +0500 Subject: [PATCH] Revised keyVaultKeyExpiry (#2105) * Revised keyVaultKeyExpiry * Revised keyVaultKeyExpiry * Apply suggestions from code review * Update plugins/azure/keyvaults/keyVaultKeyExpiry.js * Update keyVaultKeyExpiry.js * Update keyVaultKeyExpiry.spec.js * Apply suggestions from code review * Update plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js * Update plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js * Update plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js --------- Co-authored-by: AkhtarAmir Co-authored-by: alphadev4 <113519745+alphadev4@users.noreply.github.com> --- plugins/azure/keyvaults/keyVaultKeyExpiry.js | 30 +++-- .../azure/keyvaults/keyVaultKeyExpiry.spec.js | 107 +++++++----------- 2 files changed, 60 insertions(+), 77 deletions(-) diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.js index d6a64304b8..4d1cfeda43 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.js @@ -2,13 +2,13 @@ var async = require('async'); var helpers = require('../../../helpers/azure'); module.exports = { - title: 'Key Vault Key Expiry', + title: 'Key Vault Key Expiry RBAC', category: 'Key Vaults', domain: 'Application Integration', severity: 'High', - description: 'Proactively check for Key Vault keys expiry date and rotate them before expiry date is reached.', - more_info: 'After expiry date has reached for Key Vault key, it cannot be used for cryptographic operations anymore.', - recommended_action: 'Ensure that Key Vault keys are rotated before they get expired.', + description: 'Ensures that expiration date is set for all keys in RBAC Key Vaults.', + more_info: 'Setting an expiration date on keys helps in key lifecycle management and ensures that keys are rotated regularly.', + recommended_action: 'Modify keys in RBAC Key Vaults to have an expiration date set.', link: 'https://learn.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates', apis: ['vaults:list', 'vaults:getKeys'], settings: { @@ -45,14 +45,22 @@ module.exports = { return rcb(); } - vaults.data.forEach(function(vault){ + vaults.data.forEach(function(vault) { + if (!vault || !vault.properties) { + helpers.addResult(results, 3, 'Unable to read vault properties', location, vault.id); + return; + } + if (!vault.properties.enableRbacAuthorization) { + return; + } + var keys = helpers.addSource(cache, source, ['vaults', 'getKeys', location, vault.id]); if (!keys || keys.err || !keys.data) { helpers.addResult(results, 3, 'Unable to query for Key Vault keys: ' + helpers.addError(keys), location, vault.id); } else if (!keys.data.length) { - helpers.addResult(results, 0, 'No Key Vault keys found', location, vault.id); + helpers.addResult(results, 0, 'No Key Vault keys found in RBAC vault', location, vault.id); } else { keys.data.forEach(function(key) { var keyName = key.kid.substring(key.kid.lastIndexOf('/') + 1); @@ -60,23 +68,23 @@ module.exports = { if (!key.attributes || !key.attributes.enabled) { helpers.addResult(results, 0, - 'Key is not enabled', location, keyId); + 'Key in RBAC vault is not enabled', location, keyId); } else if (key.attributes && (key.attributes.expires || key.attributes.exp)) { let keyExpiry = key.attributes.exp ? key.attributes.exp * 1000 : key.attributes.expires; let difference = Math.round((new Date(keyExpiry).getTime() - (new Date).getTime())/(24*60*60*1000)); if (difference > config.key_vault_key_expiry_fail) { helpers.addResult(results, 0, - `Key expires in ${difference} days`, location, keyId); + `Key in RBAC vault expires in ${difference} days`, location, keyId); } else if (difference > 0){ helpers.addResult(results, 2, - `Key expires in ${difference} days`, location, keyId); + `Key in RBAC vault expires in ${difference} days`, location, keyId); } else { helpers.addResult(results, 2, - `Key expired ${Math.abs(difference)} days ago`, location, keyId); + `Key in RBAC vault expired ${Math.abs(difference)} days ago`, location, keyId); } } else { helpers.addResult(results, 0, - 'Key expiration is not enabled', location, keyId); + 'Key expiration is not enabled in RBAC vault', location, keyId); } }); } diff --git a/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js b/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js index 6ecdff0c49..2227db5dc7 100644 --- a/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js +++ b/plugins/azure/keyvaults/keyVaultKeyExpiry.spec.js @@ -12,48 +12,38 @@ keyExpired.setMonth(keyExpired.getMonth() - 1); const listKeyVaults = [ { - id: '/subscriptions/abcdfget-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test', - name: 'nauman-test', + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-vault', + name: 'test-vault', type: 'Microsoft.KeyVault/vaults', location: 'eastus', - tags: { owner: 'kubernetes' }, - sku: { family: 'A', name: 'Standard' }, - tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', - accessPolicies: [ - { - tenantId: '2d4f0836-5935-47f5-954c-14e713119ac2', - objectId: 'b4062000-c33b-448b-817e-fa0f17bef4b9', - permissions: { - keys: ['Get', 'List'], - secrets: ['Get', 'List'], - certificates: ['Get', 'List'] - } - } - ], - enableSoftDelete: true, - softDeleteRetentionInDays: 7, - enableRbacAuthorization: false, - vaultUri: 'https://nauman-test.vault.azure.net/', - provisioningState: 'Succeeded' - } - ]; - - const getKeys = [ + properties: { + enableRbacAuthorization: true, + vaultUri: 'https://test-vault.vault.azure.net/' + } + }, + { + id: '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-vault-2', + name: 'test-vault-2', + type: 'Microsoft.KeyVault/vaults', + location: 'eastus', + properties: { + enableRbacAuthorization: false, + vaultUri: 'https://test-vault-2.vault.azure.net/' + } + } +]; + +const getKeys = [ { "attributes": { "created": "2022-04-10T17:57:43+00:00", "enabled": true, "expires": null, "notBefore": null, - "recoveryLevel": "CustomizedRecoverable+Purgeable", "updated": "2022-04-10T17:57:43+00:00" }, - "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", - "managed": null, - "name": "nauman-test", - "tags": { - "hello": "world" - } + "kid": "https://test-vault.vault.azure.net/keys/test-key", + "name": "test-key" }, { "attributes": { @@ -61,15 +51,10 @@ const listKeyVaults = [ "enabled": true, "expires": keyExpiryPass, "notBefore": null, - "recoveryLevel": "CustomizedRecoverable+Purgeable", "updated": "2022-04-10T17:57:43+00:00" }, - "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", - "managed": null, - "name": "nauman-test", - "tags": { - "hello": "world" - } + "kid": "https://test-vault.vault.azure.net/keys/test-key-2", + "name": "test-key-2" }, { "attributes": { @@ -77,15 +62,10 @@ const listKeyVaults = [ "enabled": true, "expires": keyExpiryFail, "notBefore": null, - "recoveryLevel": "CustomizedRecoverable+Purgeable", "updated": "2022-04-10T17:57:43+00:00" }, - "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", - "managed": null, - "name": "nauman-test", - "tags": { - "hello": "world" - } + "kid": "https://test-vault.vault.azure.net/keys/test-key-3", + "name": "test-key-3" }, { "attributes": { @@ -93,15 +73,10 @@ const listKeyVaults = [ "enabled": true, "expires": keyExpired, "notBefore": null, - "recoveryLevel": "CustomizedRecoverable+Purgeable", "updated": "2022-04-10T17:57:43+00:00" }, - "kid": "https://nauman-test.vault.azure.net/keys/nauman-test", - "managed": null, - "name": "nauman-test", - "tags": { - "hello": "world" - } + "kid": "https://test-vault.vault.azure.net/keys/test-key-4", + "name": "test-key-4" } ]; @@ -116,7 +91,7 @@ const createCache = (err, list, keys) => { }, getKeys: { 'eastus': { - '/subscriptions/abcdfget-ebf6-437f-a3b0-28fc0d22111e/resourceGroups/akhtar-rg/providers/Microsoft.KeyVault/vaults/nauman-test': { + '/subscriptions/123/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-vault': { err: err, data: keys } @@ -126,9 +101,9 @@ const createCache = (err, list, keys) => { } }; -describe('keyVaultKeyExpiry', function() { +describe('keyVaultKeyExpiryRbac', function() { describe('run', function() { - it('should give passing result if no keys found', function(done) { + it('should give passing result if no key vaults found', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -144,7 +119,7 @@ describe('keyVaultKeyExpiry', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Key expiration is not enabled'); + expect(results[0].message).to.include('Key expiration is not enabled in RBAC vault'); expect(results[0].region).to.equal('eastus'); done() }; @@ -156,36 +131,36 @@ describe('keyVaultKeyExpiry', function() { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); - expect(results[0].message).to.include('Key expires in'); + expect(results[0].message).to.include('Key in RBAC vault expires in'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, [getKeys[1]]), { key_vault_key_expiry_fail: '30' }, callback); + auth.run(createCache(null, [listKeyVaults[0]], [getKeys[1]]), { key_vault_key_expiry_fail: '30' }, callback); }); - it('should give failing results if the key has reached', function(done) { + it('should give failing results if the key has expired', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Key expired'); + expect(results[0].message).to.include('Key in RBAC vault expired'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, [getKeys[3]]), { key_vault_key_expiry_fail: '40' }, callback); + auth.run(createCache(null, [listKeyVaults[0]], [getKeys[3]]), { key_vault_key_expiry_fail: '40' }, callback); }); - it('should give failing results if the key expired within failure expiry date', function(done) { + it('should give failing result if the key expires within failure expiry date', function(done) { const callback = (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - expect(results[0].message).to.include('Key expires'); + expect(results[0].message).to.include('Key in RBAC vault expires'); expect(results[0].region).to.equal('eastus'); done() }; - auth.run(createCache(null, listKeyVaults, [getKeys[2]]), { key_vault_key_expiry_fail: '40' }, callback); + auth.run(createCache(null, [listKeyVaults[0]], [getKeys[2]]), { key_vault_key_expiry_fail: '40' }, callback); }); }); -}); +});