---
policy: /ce/ca/aws/kms/symmetric-cmk-rotation
logic: /ce/ca/aws/kms/symmetric-cmk-rotation/prod.logic.yaml
executionTime: 2025-04-24T23:45:00.737561193Z
rows:
  - id: test1
    match: true
    status:
      expected: DISAPPEARED
      actual: DISAPPEARED
    conditionIndex:
      expected: 99
      actual: 99
    conditionText:
      expected: isDisappeared(CA10__disappearanceTime__c)
      actual: isDisappeared(CA10__disappearanceTime__c)
    runtimeError: {}
  - id: test2
    match: true
    status:
      expected: UNDETERMINED
      actual: UNDETERMINED
    conditionIndex:
      expected: 101
      actual: 101
    conditionText:
      expected: CA10__keySpec__c.delegatedTo(CA10__keySpec__c).isEmpty()
      actual: CA10__keySpec__c.delegatedTo(CA10__keySpec__c).isEmpty()
    runtimeError: {}
  - id: test3
    match: true
    status:
      expected: INAPPLICABLE
      actual: INAPPLICABLE
    conditionIndex:
      expected: 199
      actual: 199
    conditionText:
      expected: extract('CA10__keySpec__c') != 'SYMMETRIC_DEFAULT'
      actual: extract('CA10__keySpec__c') != 'SYMMETRIC_DEFAULT'
    runtimeError: {}
  - id: test4
    match: true
    status:
      expected: INCOMPLIANT
      actual: INCOMPLIANT
    conditionIndex:
      expected: 299
      actual: 299
    conditionText:
      expected: extract('CA10__rotationEnabled__c') == false
      actual: extract('CA10__rotationEnabled__c') == false
    runtimeError: {}
  - id: test5
    match: true
    status:
      expected: COMPLIANT
      actual: COMPLIANT
    conditionIndex:
      expected: 399
      actual: 399
    conditionText:
      expected: extract('CA10__rotationEnabled__c') == true
      actual: extract('CA10__rotationEnabled__c') == true
    runtimeError: {}
usedFiles:
  - path: /ce/ca/aws/kms/symmetric-cmk-rotation/policy.yaml
    md5Hash: 6F2242A039FA7087F1FCDAF1665BCAB1
    content: |
      ---
      names:
        full: AWS KMS Symmetric CMK Rotation is not enabled
        contextual: Symmetric CMK Rotation is not enabled
      description: AWS KMS allows customers to rotate the backing key which is key material
        stored within the KMS which is tied to the key ID of the customer-created CMK. It
        is the backing key that is used to perform cryptographic operations such as encryption
        and decryption. Automated key rotation currently retains all prior backing keys
        so that decryption of encrypted data can take place transparently. It is recommended
        that CMK key rotation be enabled for symmetric keys.
      type: COMPLIANCE_POLICY
      categories:
        - SECURITY
        - RELIABILITY
      frameworkMappings:
        - "/frameworks/cis-aws-v5.0.0/03/06"
        - "/frameworks/cloudaware/secret-and-certificate-governance/expiration-management"
      similarPolicies:
        internal:
          - dec-x-4d6fee7a
        cloudConformity:
          - url: https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/KMS/key-rotation-enabled.html
            name: Key Rotation Enabled
  - path: /ce/ca/aws/kms/symmetric-cmk-rotation/prod.logic.yaml
    md5Hash: 4EC2BF63083300DF9F5A7101D5C20FA0
    content: |-
      ---
      inputType: "CA10__CaAwsKmsKey__c"
      testData:
        - file: "test-data.json"
      importExtracts:
        - file: "/types/CA10__CaAwsKmsKey__c/object.extracts.yaml"
      conditions:
        - status: "INAPPLICABLE"
          currentStateMessage: "KMS Key rotation can not be enabled for any asymmetric CMK."
          check:
            NOT_EQUAL:
              left:
                EXTRACT: "CA10__keySpec__c"
              right:
                TEXT: "SYMMETRIC_DEFAULT"
        - status: "INCOMPLIANT"
          currentStateMessage: "AWS KMS Key rotation is disabled."
          remediationMessage: "Consider enabling KMS Key rotation."
          check:
            IS_EQUAL:
              left:
                EXTRACT: "CA10__rotationEnabled__c"
              right:
                BOOLEAN: false
        - status: "COMPLIANT"
          currentStateMessage: "AWS KMS Key rotation is enabled."
          check:
            IS_EQUAL:
              left:
                EXTRACT: "CA10__rotationEnabled__c"
              right:
                BOOLEAN: true
      otherwise:
        status: "UNDETERMINED"
        currentStateMessage: "Unexpected values in the fields."
  - path: /ce/ca/aws/kms/symmetric-cmk-rotation/test-data.json
    md5Hash: 9050D3738F3334C60BFAA8A9FFCD46E9
    content: |-
      [
          {
              "expectedResult": {
                  "status": "DISAPPEARED",
                  "conditionIndex": "99",
                  "conditionText": "isDisappeared(CA10__disappearanceTime__c)",
                  "runtimeError": null
              },
              "context": {
                  "snapshotTime": "2024-05-28T17:35:50Z"
              },
              "Id": "test1",
              "CA10__disappearanceTime__c": "2024-05-28T17:35:50Z"
          },
          {
              "expectedResult": {
                  "status": "UNDETERMINED",
                  "conditionIndex": "101",
                  "conditionText": "CA10__keySpec__c.delegatedTo(CA10__keySpec__c).isEmpty()",
                  "runtimeError": null
              },
              "context": {
                  "snapshotTime": "2024-05-28T17:35:50Z"
              },
              "Id": "test2",
              "CA10__disappearanceTime__c": null,
              "CA10__keySpec__c": "",
              "CA10__rotationEnabled__c": true
          },
          {
              "expectedResult": {
                  "status": "INAPPLICABLE",
                  "conditionIndex": "199",
                  "conditionText": "extract('CA10__keySpec__c') != 'SYMMETRIC_DEFAULT'",
                  "runtimeError": null
              },
              "context": {
                  "snapshotTime": "2024-05-28T17:35:50Z"
              },
              "Id": "test3",
              "CA10__disappearanceTime__c": null,
              "CA10__keySpec__c": "RSA_2048",
              "CA10__rotationEnabled__c": false
          },
          {
              "expectedResult": {
                  "status": "INCOMPLIANT",
                  "conditionIndex": "299",
                  "conditionText": "extract('CA10__rotationEnabled__c') == false",
                  "runtimeError": null
              },
              "context": {
                  "snapshotTime": "2024-05-28T17:35:50Z"
              },
              "Id": "test4",
              "CA10__disappearanceTime__c": null,
              "CA10__keySpec__c": "SYMMETRIC_DEFAULT",
              "CA10__rotationEnabled__c": false
          },
          {
              "expectedResult": {
                  "status": "COMPLIANT",
                  "conditionIndex": "399",
                  "conditionText": "extract('CA10__rotationEnabled__c') == true",
                  "runtimeError": null
              },
              "context": {
                  "snapshotTime": "2024-05-28T17:35:50Z"
              },
              "Id": "test5",
              "CA10__disappearanceTime__c": null,
              "CA10__keySpec__c": "SYMMETRIC_DEFAULT",
              "CA10__rotationEnabled__c": true
          }
      ]
  - path: /types/CA10__CaAwsKmsKey__c/object.extracts.yaml
    md5Hash: 0B059DB01E1D6F7518BF61709BB65A29
    content: "---\nextracts:\n# Values: Creating, Enabled, Disabled, PendingDeletion,\
      \ PendingImport, PendingReplicaDeletion, Unavailable, Updating. Not nullable.\n\
      \  - name: \"CA10__state__c\"\n    value: \n      FIELD:\n        path: \"CA10__state__c\"\
      \n        undeterminedIf:\n          noAccessDelegate: \n            path: \"\
      CA10__state__c\"\n            currentStateMessage: \"Unable to determine Key\
      \ state. Possible permission issue with kms:DescribeKey.\"\n          isEmpty:\
      \ \"KMS Key state is not populated yet.\"\n# Values: RSA_2048, RSA_3072, RSA_4096,\
      \ ECC_NIST_P256, ECC_NIST_P384, ECC_NIST_P521, ECC_SECG_P256K1, SYMMETRIC_DEFAULT,\
      \ HMAC_224, HMAC_256, HMAC_384, HMAC_512, SM2\n# Not nullable\n  - name: \"\
      CA10__keySpec__c\"\n    value: \n      FIELD:\n        path: \"CA10__keySpec__c\"\
      \n        undeterminedIf:\n          noAccessDelegate: \n            path: \"\
      CA10__keySpec__c\"\n            currentStateMessage: \"Unable to determine Key\
      \ state. Possible permission issue with kms:DescribeKey.\"\n          isEmpty:\
      \ \"KMS Key state is not populated yet.\"\n# Checkbox.\n  - name: \"CA10__rotationEnabled__c\"\
      \n    value: \n      FIELD:\n        path: \"CA10__rotationEnabled__c\"\n  \
      \      undeterminedIf:\n          noAccessDelegate:\n            path: \"CA10__rotationEnabled__c\"\
      \n            currentStateMessage: \"Unable to determine Key Rotation status.\
      \ Possible permission issue with kms:GetKeyRotationStatus.\"\n"
script: |-
  CREATE TEMP FUNCTION mock_ExpectedResult()
  RETURNS ARRAY<STRUCT<
          Id STRING,
          expectedResult STRUCT<status STRING, conditionIndex DECIMAL, conditionText STRING, runtimeError STRING>
      >>
  DETERMINISTIC
  LANGUAGE js
  AS r"""
    return [ {
    "Id" : "test1",
    "expectedResult" : {
      "status" : "DISAPPEARED",
      "conditionIndex" : "99",
      "conditionText" : "isDisappeared(CA10__disappearanceTime__c)",
      "runtimeError" : null
    }
  }, {
    "Id" : "test2",
    "expectedResult" : {
      "status" : "UNDETERMINED",
      "conditionIndex" : "101",
      "conditionText" : "CA10__keySpec__c.delegatedTo(CA10__keySpec__c).isEmpty()",
      "runtimeError" : null
    }
  }, {
    "Id" : "test3",
    "expectedResult" : {
      "status" : "INAPPLICABLE",
      "conditionIndex" : "199",
      "conditionText" : "extract('CA10__keySpec__c') != 'SYMMETRIC_DEFAULT'",
      "runtimeError" : null
    }
  }, {
    "Id" : "test4",
    "expectedResult" : {
      "status" : "INCOMPLIANT",
      "conditionIndex" : "299",
      "conditionText" : "extract('CA10__rotationEnabled__c') == false",
      "runtimeError" : null
    }
  }, {
    "Id" : "test5",
    "expectedResult" : {
      "status" : "COMPLIANT",
      "conditionIndex" : "399",
      "conditionText" : "extract('CA10__rotationEnabled__c') == true",
      "runtimeError" : null
    }
  } ];
  """;

  CREATE TEMP FUNCTION mock_CA10__CaAwsKmsKey__c()
  RETURNS ARRAY<STRUCT<
      Id STRING,
      CA10__disappearanceTime__c TIMESTAMP,
      CA10__keySpec__c STRING,
      CA10__rotationEnabled__c BOOLEAN,
      context STRUCT<
          snapshotTime TIMESTAMP
      >
  >>
  DETERMINISTIC
  LANGUAGE js
  AS r"""
    return [ {
    "context" : {
      "snapshotTime" : new Date("2024-05-28T17:35:50Z")
    },
    "Id" : "test1",
    "CA10__disappearanceTime__c" : new Date("2024-05-28T17:35:50Z"),
    "CA10__keySpec__c" : null,
    "CA10__rotationEnabled__c" : null
  }, {
    "context" : {
      "snapshotTime" : new Date("2024-05-28T17:35:50Z")
    },
    "Id" : "test2",
    "CA10__keySpec__c" : "",
    "CA10__rotationEnabled__c" : true
  }, {
    "context" : {
      "snapshotTime" : new Date("2024-05-28T17:35:50Z")
    },
    "Id" : "test3",
    "CA10__keySpec__c" : "RSA_2048",
    "CA10__rotationEnabled__c" : false
  }, {
    "context" : {
      "snapshotTime" : new Date("2024-05-28T17:35:50Z")
    },
    "Id" : "test4",
    "CA10__keySpec__c" : "SYMMETRIC_DEFAULT",
    "CA10__rotationEnabled__c" : false
  }, {
    "context" : {
      "snapshotTime" : new Date("2024-05-28T17:35:50Z")
    },
    "Id" : "test5",
    "CA10__keySpec__c" : "SYMMETRIC_DEFAULT",
    "CA10__rotationEnabled__c" : true
  } ];
  """;

  CREATE TEMP FUNCTION process_CA10__CaAwsKmsKey__c(
      obj STRUCT<
          Id STRING,
          CA10__disappearanceTime__c TIMESTAMP,
          CA10__keySpec__c STRING,
          CA10__rotationEnabled__c BOOLEAN
      >,
      snapshotTime TIMESTAMP
  )
  RETURNS STRUCT<status STRING, conditionIndex DECIMAL, conditionText STRING, currentStateMessage STRING, currentStateReferences STRING, remediation STRING, runtimeError STRING>
  DETERMINISTIC
  LANGUAGE js
  AS r"""
      var TextLib = new function () {
          this.normalize = function(arg) {
              return arg == null ? '' : arg.replace(/\s+/g, ' ').trim().toLowerCase();
          };
          this.isEmpty = function(arg) {
              return this.normalize(arg) == '';
          };
          this.isNotEmpty = function(arg) {
              return this.normalize(arg) != '';
          };
          this.equal = function(left, right) {
              return this.normalize(left) == this.normalize(right);
          };
          this.notEqual = function(left, right) {
              return this.normalize(left) != this.normalize(right);
          };
          this.startsWith = function(arg, substring) {
              return this.normalize(arg).startsWith(this.normalize(substring));
          };
          this.endsWith = function(arg, substring) {
              return this.normalize(arg).endsWith(this.normalize(substring));
          };
          this.contains = function(arg, substring) {
              return this.normalize(arg).includes(this.normalize(substring));
          };
      }();
      var IsEmptyLib = new function () {
          this.simpleIsEmpty = function(arg) {
              return arg == null;
          };
          this.simpleIsNotEmpty = function(arg) {
              return arg != null;
          };
      }();
      var references1 = [];
      // condition[0], conditionIndex:[0..99]
      references1.push('Deleted From AWS [CA10__disappearanceTime__c]: ' + obj.CA10__disappearanceTime__c);
      if (obj.CA10__disappearanceTime__c != null) {
          return {status: 'DISAPPEARED', conditionIndex: 99, conditionText: "isDisappeared(CA10__disappearanceTime__c)", currentStateMessage: "Object is deleted in the source", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null};
      }
      // condition[1], conditionIndex:[100..199]
      function fieldChecked4() {
          if (TextLib.isEmpty(obj.CA10__keySpec__c)) {
              throw new Error("UNDETERMINED condition:101", {cause: {status: 'UNDETERMINED', conditionIndex: 101, conditionText: "CA10__keySpec__c.delegatedTo(CA10__keySpec__c).isEmpty()", currentStateMessage: "Unable to determine Key state. Possible permission issue with kms:DescribeKey.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}});
          }
          if (TextLib.isEmpty(obj.CA10__keySpec__c)) {
              throw new Error("UNDETERMINED condition:102", {cause: {status: 'UNDETERMINED', conditionIndex: 102, conditionText: "CA10__keySpec__c.isEmpty()", currentStateMessage: "KMS Key state is not populated yet.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}});
          }
          return obj.CA10__keySpec__c;
      }
      function extract3() { if (!this.out) { this.out = fieldChecked4(); } return this.out; };
      references1.push('Key Spec [obj.CA10__keySpec__c]: ' + obj.CA10__keySpec__c);
      try {
          if (TextLib.notEqual(extract3.call(extract3), 'SYMMETRIC_DEFAULT')) {
              return {status: 'INAPPLICABLE', conditionIndex: 199, conditionText: "extract('CA10__keySpec__c') != 'SYMMETRIC_DEFAULT'", currentStateMessage: "KMS Key rotation can not be enabled for any asymmetric CMK.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null};
          }
      } catch (err) {
          if (err.cause && err.cause.status) { return err.cause; } else { throw err; }
      }
      // condition[2], conditionIndex:[200..299]
      function fieldChecked7() {
          if (IsEmptyLib.simpleIsEmpty(obj.CA10__rotationEnabled__c)) {
              throw new Error("UNDETERMINED condition:201", {cause: {status: 'UNDETERMINED', conditionIndex: 201, conditionText: "CA10__rotationEnabled__c.delegatedTo(CA10__rotationEnabled__c).isEmpty()", currentStateMessage: "Unable to determine Key Rotation status. Possible permission issue with kms:GetKeyRotationStatus.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}});
          }
          return obj.CA10__rotationEnabled__c;
      }
      function extract6() { if (!this.out) { this.out = fieldChecked7(); } return this.out; };
      references1.push('Rotation Enabled [obj.CA10__rotationEnabled__c]: ' + obj.CA10__rotationEnabled__c);
      try {
          if (extract6.call(extract6) == false) {
              return {status: 'INCOMPLIANT', conditionIndex: 299, conditionText: "extract('CA10__rotationEnabled__c') == false", currentStateMessage: "AWS KMS Key rotation is disabled.", currentStateReferences: references1.join('\n'), remediation: "Consider enabling KMS Key rotation.", runtimeError: null};
          }
      } catch (err) {
          if (err.cause && err.cause.status) { return err.cause; } else { throw err; }
      }
      // condition[3], conditionIndex:[300..399]
      function fieldChecked10() {
          if (IsEmptyLib.simpleIsEmpty(obj.CA10__rotationEnabled__c)) {
              throw new Error("UNDETERMINED condition:301", {cause: {status: 'UNDETERMINED', conditionIndex: 301, conditionText: "CA10__rotationEnabled__c.delegatedTo(CA10__rotationEnabled__c).isEmpty()", currentStateMessage: "Unable to determine Key Rotation status. Possible permission issue with kms:GetKeyRotationStatus.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}});
          }
          return obj.CA10__rotationEnabled__c;
      }
      function extract9() { if (!this.out) { this.out = fieldChecked10(); } return this.out; };
      try {
          if (extract9.call(extract9) == true) {
              return {status: 'COMPLIANT', conditionIndex: 399, conditionText: "extract('CA10__rotationEnabled__c') == true", currentStateMessage: "AWS KMS Key rotation is enabled.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null};
          }
      } catch (err) {
          if (err.cause && err.cause.status) { return err.cause; } else { throw err; }
      }
      return {status: 'UNDETERMINED', conditionIndex: 400, conditionText: "otherwise", currentStateMessage: "Unexpected values in the fields.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null};
  """;


  SELECT
    expectedResult.Id as Id,
    IF (
      IFNULL(expectedResult.expectedResult.status, '') = IFNULL(sObject.result.status, '')
      AND IFNULL(expectedResult.expectedResult.conditionIndex, -1) = IFNULL(sObject.result.conditionIndex, -1)
      AND IFNULL(expectedResult.expectedResult.conditionText, '') = IFNULL(sObject.result.conditionText, '')
      AND IFNULL(expectedResult.expectedResult.runtimeError, '') = IFNULL(sObject.result.runtimeError, ''),
      "MATCH",
      "FAIL"
    ) as match,
    expectedResult.expectedResult.status as expectedStatus, sObject.result.status as actualStatus,
    expectedResult.expectedResult.conditionIndex as expectedConditionIndex, sObject.result.conditionIndex as actualConditionIndex,
    expectedResult.expectedResult.conditionText as expectedConditionText, sObject.result.conditionText as actualConditionText,
    expectedResult.expectedResult.runtimeError as expectedRuntimeError, sObject.result.runtimeError as actualRuntimeError
  FROM UNNEST(mock_ExpectedResult()) expectedResult
  LEFT JOIN (
      SELECT
          sObject.Id AS Id,
          sObject.CA10__disappearanceTime__c AS CA10__disappearanceTime__c,
          sObject.CA10__keySpec__c AS CA10__keySpec__c,
          sObject.CA10__rotationEnabled__c AS CA10__rotationEnabled__c,
          process_CA10__CaAwsKmsKey__c(
              STRUCT(
                  sObject.Id AS Id,
                  sObject.CA10__disappearanceTime__c AS CA10__disappearanceTime__c,
                  sObject.CA10__keySpec__c AS CA10__keySpec__c,
                  sObject.CA10__rotationEnabled__c AS CA10__rotationEnabled__c
              ),
              sObject.context.snapshotTime
          ) as result
      FROM UNNEST(mock_CA10__CaAwsKmsKey__c()) AS sObject
  ) sObject ON sObject.Id = expectedResult.Id;
