diff --git a/plugins/aws/kinesisvideo/videostreamDataEncrypted.js b/plugins/aws/kinesisvideo/videostreamDataEncrypted.js index a1146e4225..940cefd8ca 100644 --- a/plugins/aws/kinesisvideo/videostreamDataEncrypted.js +++ b/plugins/aws/kinesisvideo/videostreamDataEncrypted.js @@ -11,7 +11,7 @@ module.exports = { 'It is recommended to use customer-managed keys (CMKs) for encryption in order to gain more granular control over encryption/decryption process.', recommended_action: 'Encrypt Kinesis Video Streams data with customer-manager keys (CMKs).', link: 'https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/how-kms.html', - apis: ['KinesisVideo:listStreams', 'KMS:describeKey', 'KMS:listKeys'], + apis: ['KinesisVideo:listStreams', 'KMS:describeKey', 'KMS:listKeys', 'KMS:listAliases'], settings: { video_stream_data_desired_encryption_level: { name: 'Kinesis Video Streams Data Target Encryption Level', @@ -59,16 +59,39 @@ module.exports = { return rcb(); } + var listAliases = helpers.addSource(cache, source, + ['kms', 'listAliases', region]); + + if (!listAliases || listAliases.err || !listAliases.data) { + helpers.addResult(results, 3, + 'Unable to query for KMS aliases: ' + helpers.addError(listAliases), + region); + return rcb(); + } + + var keyArn; + var kmsAliasArnMap = {}; + listAliases.data.forEach(function(alias) { + keyArn = alias.AliasArn.replace(/:alias\/.*/, ':key/' + alias.TargetKeyId); + kmsAliasArnMap[alias.AliasName] = keyArn; + }); + for (let streamData of listStreams.data) { if (!streamData.StreamARN) continue; let resource = streamData.StreamARN; if (streamData.KmsKeyId) { - var kmsKeyId = streamData.KmsKeyId.split('/')[1] ? streamData.KmsKeyId.split('/')[1] : streamData.KmsKeyId; + + let aliasKey = streamData.KmsKeyId.includes('alias/') ? streamData.KmsKeyId.split(':').pop() : streamData.KmsKeyId; + let kmsKeyArn = (aliasKey.startsWith('alias/')) + ? (kmsAliasArnMap[aliasKey] ? kmsAliasArnMap[aliasKey] : streamData.KmsKeyId) + : streamData.KmsKeyId; + var kmsKeyId = kmsKeyArn.split('/')[1] ? kmsKeyArn.split('/')[1] : kmsKeyArn; + var describeKey = helpers.addSource(cache, source, - ['kms', 'describeKey', region, kmsKeyId]); + ['kms', 'describeKey', region, kmsKeyId]); if (!describeKey || describeKey.err || !describeKey.data || !describeKey.data.KeyMetadata) { helpers.addResult(results, 3, diff --git a/plugins/aws/kinesisvideo/videostreamDataEncrypted.spec.js b/plugins/aws/kinesisvideo/videostreamDataEncrypted.spec.js index 3dc7073d33..0c7177eecc 100644 --- a/plugins/aws/kinesisvideo/videostreamDataEncrypted.spec.js +++ b/plugins/aws/kinesisvideo/videostreamDataEncrypted.spec.js @@ -21,6 +21,14 @@ const listKeys = [ } ]; +const listAliases = [ + { + "AliasName": "alias/my-kinesis-key", + "AliasArn": "arn:aws:kms:us-east-1:000011112222:alias/my-kinesis-key", + "TargetKeyId": "ad013a33-b01d-4d88-ac97-127399c18b3e" + } +]; + const describeKey = [ { "KeyMetadata": { @@ -60,7 +68,7 @@ const describeKey = [ } ]; -const createCache = (streamData, keys, describeKey, streamDataErr, keysErr, describeKeyErr) => { +const createCache = (streamData, keys, aliases, describeKey, streamDataErr, keysErr, aliasesErr, describeKeyErr) => { var keyId = (keys && keys.length ) ? keys[0].KeyId : null; return { kinesisvideo: { @@ -78,6 +86,12 @@ const createCache = (streamData, keys, describeKey, streamDataErr, keysErr, desc err: keysErr } }, + listAliases: { + 'us-east-1': { + data: aliases, + err: aliasesErr + } + }, describeKey: { 'us-east-1': { [keyId]: { @@ -95,8 +109,8 @@ const createCache = (streamData, keys, describeKey, streamDataErr, keysErr, desc describe('videostreamDataEncrypted', function () { describe('run', function () { - it('should PASS if Kinesis Video Streams data is using desired encryption level', function (done) { - const cache = createCache(listStreams, listKeys, describeKey[0]); + it('should PASS if Kinesis Video Streams data is using customer-managed encryption (awscmk)', function (done) { + const cache = createCache(listStreams, listKeys, listAliases, describeKey[0]); videostreamDataEncrypted.run(cache, { video_stream_data_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -106,9 +120,9 @@ describe('videostreamDataEncrypted', function () { }); - it('should FAIL if Kinesis Video Streams data is using desired encyption level', function (done) { - const cache = createCache(listStreams, listKeys, describeKey[1]); - videostreamDataEncrypted.run(cache, { video_stream_data_desired_encryption_level:'awscmk' }, (err, results) => { + it('should FAIL if Kinesis Video Streams data is using AWS managed encryption (awskms)', function (done) { + const cache = createCache(listStreams, listKeys, listAliases, describeKey[1]); + videostreamDataEncrypted.run(cache, { video_stream_data_desired_encryption_level: 'awscmk' }, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); expect(results[0].message).to.include('Kinesis Video Streams data is using awskms'); @@ -117,7 +131,7 @@ describe('videostreamDataEncrypted', function () { }); - it('should PASS if no Kinesis Video Streams found', function (done) { + it('should PASS if no Kinesis Video Streams are found', function (done) { const cache = createCache([]); videostreamDataEncrypted.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -128,7 +142,7 @@ describe('videostreamDataEncrypted', function () { }); it('should UNKNOWN if unable to list Kinesis Video Streams', function (done) { - const cache = createCache(null, null, null, { message: "Unable to list Kinesis Video Streams encryption" }); + const cache = createCache(null, null, null, null, { message: "Unable to list Kinesis Video Streams" }); videostreamDataEncrypted.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); @@ -138,7 +152,16 @@ describe('videostreamDataEncrypted', function () { }); it('should UNKNOWN if unable to list KMS keys', function (done) { - const cache = createCache(null, null, null, null, { message: "Unable to list KMS keys" }); + const cache = createCache(null, null, null, null, null, { message: "Unable to list KMS keys" }); + videostreamDataEncrypted.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should UNKNOWN if unable to retrieve KMS alias data', function (done) { + const cache = createCache(listStreams, listKeys, null, describeKey[0], null, null, { message: "Unable to list KMS aliases" }); videostreamDataEncrypted.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3);