Enable CMK Rotation

Violation ID: BC_AWS_LOGGING_8

Ensure Rotation for Customer Created CMKs is Enabled

Description

AWS Key Management Service (KMS) allows customers to rotate the backing key. This is where key material is stored within the KMS, and tied to the key ID of the Customer Created customer master key (CMK). The backing key is used to perform cryptographic operations such as encryption and decryption. Automated key rotation currently retains all prior backing keys, allowing decryption of encrypted data to take place transparently. It is recommended that CMK key rotation is enabled.

Rationale

Rotating encryption keys helps reduce the potential impact of a compromised key. Data encrypted with a new key cannot be accessed with a previous key, that may have been exposed.

Automated Remediation

Runtime Resource

The instruction below describes the steps taken by the Playbook for automated remediation of a violation of this policy.

CmkEnableRotation
Sets an annual rotation for the given keys.

/* eslint-disable no-param-reassign */
const AWS = require('aws-sdk');
const path = require('path');

const fileName = path.basename(__filename);

const transformResources = (arnList) => {
    try {
        const keys = {};
        arnList.forEach((arn) => {
            const region = arn.split(':')[3];
            if (!region) {
                throw new Error('Bad format of keys');
            }
            if (keys[region]) {
                keys[region].push(arn.split(':key/').pop());
            } else {
                keys[region] = [arn.split(':key/').pop()];
            }
        });
        return keys;
    } catch (e) {
        console.error('Keys should be provided as their ARNs, for example: arn:aws:kms:us-east-1:123456789012:key/58a78aca-9eb1-4371-8f21-8cc856644036\n');
        return null;
    }
};

const doRunRemediation = async (event) => {
    const keys = transformResources(event.resources);
    if (!keys) {
        console.log('No keys found in params');
        return Promise.reject({ code: 400, message: 'CmkEnableRotation requires a "keys" param' });
    }

    return Promise.all(Object.keys(keys).map(async (region) => {
        const regionKeys = keys[region];
        AWS.config.update({ region });
        const KMS = new AWS.KMS(event.sts);
        return Promise.all(regionKeys.map(async (key) => KMS.getKeyRotationStatus({ KeyId: key }).promise().then((statusResponse) => ({
            id: key,
            rotationStatus: statusResponse.KeyRotationEnabled
        })))).then(async (keysWithRotationStatus) => {
            const keysWithoutRotation = keysWithRotationStatus.filter((key) => !key.rotationStatus);
            return Promise.all(keysWithoutRotation.map(async (key) => KMS.enableKeyRotation({ KeyId: key.id }).promise().then(() => ({
                keyId: key.id,
                isSuccess: true,
                undoable: true,
                result: 'Key rotation set',
                startState: false,
                endState: true
            })).catch((error) => {
                console.error(error.message);
                return {
                    keyId: key.id,
                    isSuccess: false,
                    undoable: false,
                    result: `Failed to enable key rotation: ${error.message}`
                };
            })));
        });
    })).then((results) => results.reduce((acc, regionalResults) => acc.concat(regionalResults), []));
};

const getCli = (resources) => `npm i aws-sdk && node ${fileName} -k "${resources.join(',')}"`;

const undo = async (sts, results) => {
    const KMS = sts ? new AWS.KMS(sts) : new AWS.KMS();

    results = results.filter((key) => key.isSuccess);
    return Promise.all(results.map(async (key) => KMS.getKeyRotationStatus({ KeyId: key.keyId }).promise().then((statusResponse) => ({
        id: key.keyId,
        rotationStatus: statusResponse.KeyRotationEnabled
    })))).then(async (keysWithRotationStatus) => {
        const keysWithoutRotation = keysWithRotationStatus.filter((key) => key.rotationStatus);
        return Promise.all(keysWithoutRotation.map(async (key) => KMS.disableKeyRotation({ KeyId: key.id }).promise().then(Promise.resolve({ keyId: key.id, result: 'Success' }))));
    }).then(() => 'Success');
};

// Main endpoint
if (process.env.IS_LAMBDA) {
    console.log('Waiting for lambda trigger');
} else {
    const args = process.argv.slice(2, process.argv.length);
    let profile;
    let keysString;
    for (let i = 0; i < args.length; i++) {
        switch (args[i]) {
            case '-k':
            case '-keys':
                i++;
                keysString = args[i];
                break;
            case '-p':
            case '-profile':
                i++;
                profile = args[i];
                break;
            case '-h':
            case 'help':
            case '-help':
            default:
                console.error('Bad params\n');
                console.log('Synopsis:\n\nThis script adds an annual rotation to your customer managed keys (CMK).\n'
                + 'To launch it, supply the key IDs and the profile, as set in your AWS credentials file, as such:\n'
                + `node ${fileName}\n`
                + 'Parameters: \n-p / -profile\tThe AWS profile to be used, as defined in the AWS credentials file\n'
                + '-k / -keys\tA list of CMK ARNs, separated by commas, to be configured.\n\n\n'
                + `Example:\n node ${fileName} -p dev -k "arn:aws:kms:us-west-2:123456789012:key/888d0229-d60a-4e47-ae6a-f0e9b93c5e84,arn:aws:kms:us-west-2:123456789012:key/888d0229-d60a-4e47-ae6a-f0e9b93c5e84"\n`);
                process.exit(1);
        }
    }

    if (keysString) {
        if (profile) {
            console.log(`using profile: ${profile}`);
            AWS.config.credentials = new AWS.SharedIniFileCredentials({ profile });
        }
        doRunRemediation({ resources: keysString.split(',') }).then(console.log).catch(console.log);
    } else {
        console.error('\nMissing the keys parameter. Please add '
            + '-k YOUR_KEYS_STRING and try again\n'
            + `For example: node ${fileName} -k "arn:aws:kms:us-east-1:123456789012:key/58a78aca-9eb1-4371-8f21-8cc856644036,arn:aws:kms:us-west-2:123456789012:key/888d0229-d60a-4e47-ae6a-f0e9b93c5e84" -p prod\n\n`
            + `For help, type "node ${fileName} -h"\n`);
    }
}

const description = 'Sets an annual rotation for the given keys.';

const params = [];

const example = `npm i aws-sdk && node ${fileName} -k "arn:aws:kms:us-west-2:123456789012:key/888d0229-d60a-4e47-ae6a-f0e9b93c5e84,arn:aws:kms:us-east-1:123456789012:key/58a78aca-9eb1-4371-8f21-8cc856644036" -p dev`;

module.exports = {
    params,
    example,
    description,
    doRunRemediation,
    getCli,
    undo
};

Buildtime Resource

Terraform

Resource: aws_kms_key
Argument: enable_key_rotation - (Optional) Specifies whether key rotation is enabled. Defaults to false.
Example fix:

resource "aws_kms_key" "kms_key_1" {
  description             = "kms_key_1"
  deletion_window_in_days = 10
  key_usage               = "ENCRYPT_DECRYPT"
  is_enabled              = true
 + enable_key_rotation    = true
}

CloudFormation

Resource: AWS::KMS::Key
Attribute: EnableKeyRotation - (Optional) Specifies whether key rotation is enabled. Defaults to false.
Example fix (JSON):

{
  "Type" : "AWS::KMS::Key",
  "Properties" : {
      "Description" : "kms_key"1,
+     "EnableKeyRotation" : true,
    }
}

Example fix (YAML)

Type: AWS::KMS::Key
Properties: 
  Description: kms_key_1
+ EnableKeyRotation: true

Manual Remediation

Runtime Resource

Procedure

Via the Management Console:

  1. Login to the AWS Management Console at https://console.aws.amazon.com/.
  2. Open the KMS console.
  3. In the left navigation pane, select customer managed keys.
  4. Select the customer master key (CMK) in scope.
  5. Navigate to the Key Rotation tab.
  6. Select Rotate this key every year.
  7. Click Save.

CLI Command

Change the policy to enable key rotation using CLI command:

aws kms enable-key-rotation --key-id <kms_key_id>

Updated 4 months ago


Enable CMK Rotation


Violation ID: BC_AWS_LOGGING_8

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.