--- policy: /ce/ca/aws/iam/group-inline-policy-allows-kms-decrypt-on-all-keys logic: /ce/ca/aws/iam/group-inline-policy-allows-kms-decrypt-on-all-keys/prod.logic.yaml executionTime: 2026-04-25T12:03:11.090492966Z generationMs: 60 executionMs: 1964 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__policyDocument__c.delegatedTo(CA10__policyDocument__c).isEmpty() actual: CA10__policyDocument__c.delegatedTo(CA10__policyDocument__c).isEmpty() runtimeError: {} - id: test3 match: true status: expected: INCOMPLIANT actual: INCOMPLIANT conditionIndex: expected: 199 actual: 199 conditionText: expected: "extract('caJsonFrom_policyDocument__c').jsonQueryText('type(Statement)')\ \ == 'array' && extract('caJsonFrom_policyDocument__c').jsonQueryText('length(Statement[?\ \ Effect == \\'Allow\\' && (((type(Action) == \\'array\\') && (contains(Action,\ \ \\'kms:Decrypt\\') || contains(Action, \\'kms:ReEncryptFrom\\') || contains(Action,\ \ \\'kms:*\\') || contains(Action, \\'kms:ReEncrypt*\\'))) || ((type(Action)\ \ == \\'string\\') && (Action == \\'kms:Decrypt\\' || Action == \\'kms:ReEncryptFrom\\\ ' || Action == \\'kms:*\\' || Action == \\'kms:ReEncrypt*\\'))) && (((type(Resource)\ \ == \\'array\\') && (contains(Resource, \\'*\\') || length(Resource[? (starts_with(@,\ \ \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@,\ \ \\':key/*\\')]) > `0`)) || ((type(Resource) == \\'string\\') && (Resource\ \ == \\'*\\' || ((starts_with(Resource, \\'arn:aws:kms:\\') || starts_with(Resource,\ \ \\'arn:*:kms:\\')) && contains(Resource, \\':key/*\\')))))])') > number(0.0)" actual: "extract('caJsonFrom_policyDocument__c').jsonQueryText('type(Statement)')\ \ == 'array' && extract('caJsonFrom_policyDocument__c').jsonQueryText('length(Statement[?\ \ Effect == \\'Allow\\' && (((type(Action) == \\'array\\') && (contains(Action,\ \ \\'kms:Decrypt\\') || contains(Action, \\'kms:ReEncryptFrom\\') || contains(Action,\ \ \\'kms:*\\') || contains(Action, \\'kms:ReEncrypt*\\'))) || ((type(Action)\ \ == \\'string\\') && (Action == \\'kms:Decrypt\\' || Action == \\'kms:ReEncryptFrom\\\ ' || Action == \\'kms:*\\' || Action == \\'kms:ReEncrypt*\\'))) && (((type(Resource)\ \ == \\'array\\') && (contains(Resource, \\'*\\') || length(Resource[? (starts_with(@,\ \ \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@,\ \ \\':key/*\\')]) > `0`)) || ((type(Resource) == \\'string\\') && (Resource\ \ == \\'*\\' || ((starts_with(Resource, \\'arn:aws:kms:\\') || starts_with(Resource,\ \ \\'arn:*:kms:\\')) && contains(Resource, \\':key/*\\')))))])') > number(0.0)" runtimeError: {} - id: test4 match: true status: expected: INCOMPLIANT actual: INCOMPLIANT conditionIndex: expected: 299 actual: 299 conditionText: expected: "extract('caJsonFrom_policyDocument__c').jsonQueryText('(Statement.Effect\ \ == \\'Allow\\') && ((((type(Statement.Action) == \\'string\\') && (Statement.Action\ \ == \\'kms:Decrypt\\' || Statement.Action == \\'kms:ReEncryptFrom\\' || Statement.Action\ \ == \\'kms:*\\' || Statement.Action == \\'kms:ReEncrypt*\\')) || ((type(Statement.Action)\ \ == \\'array\\') && (contains(Statement.Action, \\'kms:Decrypt\\') || contains(Statement.Action,\ \ \\'kms:ReEncryptFrom\\') || contains(Statement.Action, \\'kms:*\\') || contains(Statement.Action,\ \ \\'kms:ReEncrypt*\\')))) && (((type(Statement.Resource) == \\'string\\')\ \ && (Statement.Resource == \\'*\\' || ((starts_with(Statement.Resource, \\\ 'arn:aws:kms:\\') || starts_with(Statement.Resource, \\'arn:*:kms:\\')) &&\ \ contains(Statement.Resource, \\':key/*\\')))) || ((type(Statement.Resource)\ \ == \\'array\\') && (contains(Statement.Resource, \\'*\\') || length(Statement.Resource[?\ \ (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\'))\ \ && contains(@, \\':key/*\\')]) > `0`))))') == true" actual: "extract('caJsonFrom_policyDocument__c').jsonQueryText('(Statement.Effect\ \ == \\'Allow\\') && ((((type(Statement.Action) == \\'string\\') && (Statement.Action\ \ == \\'kms:Decrypt\\' || Statement.Action == \\'kms:ReEncryptFrom\\' || Statement.Action\ \ == \\'kms:*\\' || Statement.Action == \\'kms:ReEncrypt*\\')) || ((type(Statement.Action)\ \ == \\'array\\') && (contains(Statement.Action, \\'kms:Decrypt\\') || contains(Statement.Action,\ \ \\'kms:ReEncryptFrom\\') || contains(Statement.Action, \\'kms:*\\') || contains(Statement.Action,\ \ \\'kms:ReEncrypt*\\')))) && (((type(Statement.Resource) == \\'string\\')\ \ && (Statement.Resource == \\'*\\' || ((starts_with(Statement.Resource, \\\ 'arn:aws:kms:\\') || starts_with(Statement.Resource, \\'arn:*:kms:\\')) &&\ \ contains(Statement.Resource, \\':key/*\\')))) || ((type(Statement.Resource)\ \ == \\'array\\') && (contains(Statement.Resource, \\'*\\') || length(Statement.Resource[?\ \ (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\'))\ \ && contains(@, \\':key/*\\')]) > `0`))))') == true" runtimeError: {} - id: test5 match: true status: expected: COMPLIANT actual: COMPLIANT conditionIndex: expected: 300 actual: 300 conditionText: expected: otherwise actual: otherwise runtimeError: {} usedFiles: - path: /ce/ca/aws/iam/group-inline-policy-allows-kms-decrypt-on-all-keys/policy.yaml md5Hash: DE00ED88DC8D437107CA4F8C51332548 content: | --- names: full: AWS IAM Group Inline Policy allows KMS decryption actions on all KMS keys contextual: Group Inline Policy allows KMS decryption actions on all KMS keys description: > IAM group inline policies should grant AWS KMS decryption permissions only for the specific KMS keys required by group members. Allowing decryption actions on all KMS keys weakens least-privilege access control and can expose encrypted data beyond the intended scope. type: COMPLIANCE_POLICY categories: - SECURITY frameworkMappings: - "/frameworks/cloudaware/identity-and-access-governance/rbac-management" - "/frameworks/aws-fsbp-v1.0.0/kms/02" similarPolicies: awsSecurityHub: - name: "[KMS.2] IAM principals should not have IAM inline policies that allow decryption actions on all KMS keys" url: "https://docs.aws.amazon.com/securityhub/latest/userguide/kms-controls.html#kms-2" - path: /ce/ca/aws/iam/group-inline-policy-allows-kms-decrypt-on-all-keys/prod.logic.yaml md5Hash: 49EA5D848122FB59B3E3E2849A4E8D12 content: | --- inputType: "CA10__CaAwsGroupPolicy__c" testData: - file: "test-data.json" importExtracts: - file: "/types/CA10__CaAwsGroupPolicy__c/object.extracts.yaml" conditions: - status: "INCOMPLIANT" currentStateMessage: "This IAM group inline policy allows KMS decryption actions on all KMS keys." remediationMessage: "Restrict KMS decryption permissions to only the specific KMS keys that the group inline policy should allow." check: AND: args: # Handle policies where Statement is an array. We count only statements # that combine Allow + decrypt-related KMS action + wildcard KMS key scope. # Wildcard scope includes Resource == '*' and KMS key ARNs ending with ':key/*'. - IS_EQUAL: left: JSON_QUERY_TEXT: arg: EXTRACT: "caJsonFrom_policyDocument__c" expression: "type(Statement)" undeterminedIf: evaluationError: "The JSON query has failed." resultTypeMismatch: "The JSON query did not return text type." right: TEXT: "array" - GREATER_THAN: left: JSON_QUERY_NUMBER: arg: EXTRACT: "caJsonFrom_policyDocument__c" expression: "length(Statement[? Effect == 'Allow' && (((type(Action) == 'array') && (contains(Action, 'kms:Decrypt') || contains(Action, 'kms:ReEncryptFrom') || contains(Action, 'kms:*') || contains(Action, 'kms:ReEncrypt*'))) || ((type(Action) == 'string') && (Action == 'kms:Decrypt' || Action == 'kms:ReEncryptFrom' || Action == 'kms:*' || Action == 'kms:ReEncrypt*'))) && (((type(Resource) == 'array') && (contains(Resource, '*') || length(Resource[? (starts_with(@, 'arn:aws:kms:') || starts_with(@, 'arn:*:kms:')) && contains(@, ':key/*')]) > `0`)) || ((type(Resource) == 'string') && (Resource == '*' || ((starts_with(Resource, 'arn:aws:kms:') || starts_with(Resource, 'arn:*:kms:')) && contains(Resource, ':key/*')))))])" undeterminedIf: evaluationError: "The JSON query has failed." resultTypeMismatch: "The JSON query did not return number type." right: NUMBER: 0.0 - status: "INCOMPLIANT" currentStateMessage: "This IAM group inline policy allows KMS decryption actions on all KMS keys." remediationMessage: "Restrict KMS decryption permissions to only the specific KMS keys that the group inline policy should allow." check: # Handle policies where Statement is a single object instead of an array. # The expression verifies the same three requirements in one statement: # Allow effect, decrypt-related KMS action, and wildcard KMS key scope. # Wildcard scope includes Resource == '*' and KMS key ARNs ending with ':key/*'. IS_EQUAL: left: JSON_QUERY_BOOLEAN: arg: EXTRACT: "caJsonFrom_policyDocument__c" expression: "(Statement.Effect == 'Allow') && ((((type(Statement.Action) == 'string') && (Statement.Action == 'kms:Decrypt' || Statement.Action == 'kms:ReEncryptFrom' || Statement.Action == 'kms:*' || Statement.Action == 'kms:ReEncrypt*')) || ((type(Statement.Action) == 'array') && (contains(Statement.Action, 'kms:Decrypt') || contains(Statement.Action, 'kms:ReEncryptFrom') || contains(Statement.Action, 'kms:*') || contains(Statement.Action, 'kms:ReEncrypt*')))) && (((type(Statement.Resource) == 'string') && (Statement.Resource == '*' || ((starts_with(Statement.Resource, 'arn:aws:kms:') || starts_with(Statement.Resource, 'arn:*:kms:')) && contains(Statement.Resource, ':key/*')))) || ((type(Statement.Resource) == 'array') && (contains(Statement.Resource, '*') || length(Statement.Resource[? (starts_with(@, 'arn:aws:kms:') || starts_with(@, 'arn:*:kms:')) && contains(@, ':key/*')]) > `0`))))" undeterminedIf: evaluationError: "The JSON query has failed." resultTypeMismatch: "The JSON query did not return boolean type." right: BOOLEAN: true otherwise: status: "COMPLIANT" currentStateMessage: "This IAM group inline policy does not allow KMS decryption actions on all KMS keys." - path: /ce/ca/aws/iam/group-inline-policy-allows-kms-decrypt-on-all-keys/test-data.json md5Hash: 8DD39649A7447CB7CB37FCF16DD3968B content: | [ { "expectedResult": { "status": "DISAPPEARED", "conditionIndex": 99, "conditionText": "isDisappeared(CA10__disappearanceTime__c)", "runtimeError": null }, "context": { "snapshotTime": "2026-01-15T10:42:39Z" }, "Id": "test1", "CA10__disappearanceTime__c": "2026-01-10T10:42:39Z", "CA10__policyDocument__c": "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"kms:Decrypt\",\"Resource\":\"*\"}}" }, { "expectedResult": { "status": "UNDETERMINED", "conditionIndex": 101, "conditionText": "CA10__policyDocument__c.delegatedTo(CA10__policyDocument__c).isEmpty()", "runtimeError": null }, "context": { "snapshotTime": "2026-01-15T10:42:39Z" }, "Id": "test2", "CA10__disappearanceTime__c": null, "CA10__policyDocument__c": "" }, { "expectedResult": { "status": "INCOMPLIANT", "conditionIndex": 199, "conditionText": "extract('caJsonFrom_policyDocument__c').jsonQueryText('type(Statement)') == 'array' && extract('caJsonFrom_policyDocument__c').jsonQueryText('length(Statement[? Effect == \\'Allow\\' && (((type(Action) == \\'array\\') && (contains(Action, \\'kms:Decrypt\\') || contains(Action, \\'kms:ReEncryptFrom\\') || contains(Action, \\'kms:*\\') || contains(Action, \\'kms:ReEncrypt*\\'))) || ((type(Action) == \\'string\\') && (Action == \\'kms:Decrypt\\' || Action == \\'kms:ReEncryptFrom\\' || Action == \\'kms:*\\' || Action == \\'kms:ReEncrypt*\\'))) && (((type(Resource) == \\'array\\') && (contains(Resource, \\'*\\') || length(Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`)) || ((type(Resource) == \\'string\\') && (Resource == \\'*\\' || ((starts_with(Resource, \\'arn:aws:kms:\\') || starts_with(Resource, \\'arn:*:kms:\\')) && contains(Resource, \\':key/*\\')))))])') > number(0.0)", "runtimeError": null }, "context": { "snapshotTime": "2026-01-15T10:42:39Z" }, "Id": "test3", "CA10__disappearanceTime__c": null, "CA10__policyDocument__c": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"kms:Decrypt\"],\"Resource\":\"*\"}]}" }, { "expectedResult": { "status": "INCOMPLIANT", "conditionIndex": 299, "conditionText": "extract('caJsonFrom_policyDocument__c').jsonQueryText('(Statement.Effect == \\'Allow\\') && ((((type(Statement.Action) == \\'string\\') && (Statement.Action == \\'kms:Decrypt\\' || Statement.Action == \\'kms:ReEncryptFrom\\' || Statement.Action == \\'kms:*\\' || Statement.Action == \\'kms:ReEncrypt*\\')) || ((type(Statement.Action) == \\'array\\') && (contains(Statement.Action, \\'kms:Decrypt\\') || contains(Statement.Action, \\'kms:ReEncryptFrom\\') || contains(Statement.Action, \\'kms:*\\') || contains(Statement.Action, \\'kms:ReEncrypt*\\')))) && (((type(Statement.Resource) == \\'string\\') && (Statement.Resource == \\'*\\' || ((starts_with(Statement.Resource, \\'arn:aws:kms:\\') || starts_with(Statement.Resource, \\'arn:*:kms:\\')) && contains(Statement.Resource, \\':key/*\\')))) || ((type(Statement.Resource) == \\'array\\') && (contains(Statement.Resource, \\'*\\') || length(Statement.Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`))))') == true", "runtimeError": null }, "context": { "snapshotTime": "2026-01-15T10:42:39Z" }, "Id": "test4", "CA10__disappearanceTime__c": null, "CA10__policyDocument__c": "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"kms:Decrypt\",\"Resource\":\"*\"}}" }, { "expectedResult": { "status": "COMPLIANT", "conditionIndex": 300, "conditionText": "otherwise", "runtimeError": null }, "context": { "snapshotTime": "2026-01-15T10:42:39Z" }, "Id": "test5", "CA10__disappearanceTime__c": null, "CA10__policyDocument__c": "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"kms:Decrypt\",\"Resource\":\"arn:aws:kms:us-east-1:123456789012:key/abcd-1234\"}}" } ] - path: /types/CA10__CaAwsGroupPolicy__c/object.extracts.yaml md5Hash: 341B36859C7B7E18CC5D87C624DFE155 content: | # yaml-language-server: $schema=../../schema/Extracts.schema.json --- extracts: - name: "CA10__policyDocument__c" value: FIELD: path: "CA10__policyDocument__c" returnType: BYTES undeterminedIf: noAccessDelegate: path: "CA10__policyDocument__c" currentStateMessage: "Unable to determine the Policy Document. Possible permission issue with iam:GetGroupPolicy" - name: "caJsonFrom_policyDocument__c" value: JSON_FROM: arg: EXTRACT: "CA10__policyDocument__c" undeterminedIf: isInvalid: "IAM policy document JSON is invalid." script: |- CREATE TEMP FUNCTION mock_ExpectedResult() RETURNS ARRAY >> 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__policyDocument__c.delegatedTo(CA10__policyDocument__c).isEmpty()", "runtimeError" : null } }, { "Id" : "test3", "expectedResult" : { "status" : "INCOMPLIANT", "conditionIndex" : 199, "conditionText" : "extract('caJsonFrom_policyDocument__c').jsonQueryText('type(Statement)') == 'array' && extract('caJsonFrom_policyDocument__c').jsonQueryText('length(Statement[? Effect == \\'Allow\\' && (((type(Action) == \\'array\\') && (contains(Action, \\'kms:Decrypt\\') || contains(Action, \\'kms:ReEncryptFrom\\') || contains(Action, \\'kms:*\\') || contains(Action, \\'kms:ReEncrypt*\\'))) || ((type(Action) == \\'string\\') && (Action == \\'kms:Decrypt\\' || Action == \\'kms:ReEncryptFrom\\' || Action == \\'kms:*\\' || Action == \\'kms:ReEncrypt*\\'))) && (((type(Resource) == \\'array\\') && (contains(Resource, \\'*\\') || length(Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`)) || ((type(Resource) == \\'string\\') && (Resource == \\'*\\' || ((starts_with(Resource, \\'arn:aws:kms:\\') || starts_with(Resource, \\'arn:*:kms:\\')) && contains(Resource, \\':key/*\\')))))])') > number(0.0)", "runtimeError" : null } }, { "Id" : "test4", "expectedResult" : { "status" : "INCOMPLIANT", "conditionIndex" : 299, "conditionText" : "extract('caJsonFrom_policyDocument__c').jsonQueryText('(Statement.Effect == \\'Allow\\') && ((((type(Statement.Action) == \\'string\\') && (Statement.Action == \\'kms:Decrypt\\' || Statement.Action == \\'kms:ReEncryptFrom\\' || Statement.Action == \\'kms:*\\' || Statement.Action == \\'kms:ReEncrypt*\\')) || ((type(Statement.Action) == \\'array\\') && (contains(Statement.Action, \\'kms:Decrypt\\') || contains(Statement.Action, \\'kms:ReEncryptFrom\\') || contains(Statement.Action, \\'kms:*\\') || contains(Statement.Action, \\'kms:ReEncrypt*\\')))) && (((type(Statement.Resource) == \\'string\\') && (Statement.Resource == \\'*\\' || ((starts_with(Statement.Resource, \\'arn:aws:kms:\\') || starts_with(Statement.Resource, \\'arn:*:kms:\\')) && contains(Statement.Resource, \\':key/*\\')))) || ((type(Statement.Resource) == \\'array\\') && (contains(Statement.Resource, \\'*\\') || length(Statement.Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`))))') == true", "runtimeError" : null } }, { "Id" : "test5", "expectedResult" : { "status" : "COMPLIANT", "conditionIndex" : 300, "conditionText" : "otherwise", "runtimeError" : null } } ]; """; CREATE TEMP FUNCTION mock_CA10__CaAwsGroupPolicy__c() RETURNS ARRAY >> DETERMINISTIC LANGUAGE js AS r""" return [ { "context" : { "snapshotTime" : new Date("2026-01-15T10:42:39Z") }, "CA10__disappearanceTime__c" : new Date("2026-01-10T10:42:39Z"), "CA10__policyDocument__c" : "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"kms:Decrypt\",\"Resource\":\"*\"}}", "Id" : "test1" }, { "context" : { "snapshotTime" : new Date("2026-01-15T10:42:39Z") }, "CA10__policyDocument__c" : "", "Id" : "test2" }, { "context" : { "snapshotTime" : new Date("2026-01-15T10:42:39Z") }, "CA10__policyDocument__c" : "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"kms:Decrypt\"],\"Resource\":\"*\"}]}", "Id" : "test3" }, { "context" : { "snapshotTime" : new Date("2026-01-15T10:42:39Z") }, "CA10__policyDocument__c" : "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"kms:Decrypt\",\"Resource\":\"*\"}}", "Id" : "test4" }, { "context" : { "snapshotTime" : new Date("2026-01-15T10:42:39Z") }, "CA10__policyDocument__c" : "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"kms:Decrypt\",\"Resource\":\"arn:aws:kms:us-east-1:123456789012:key/abcd-1234\"}}", "Id" : "test5" } ]; """; CREATE TEMP FUNCTION process_CA10__CaAwsGroupPolicy__c( obj STRUCT< CA10__disappearanceTime__c TIMESTAMP, CA10__policyDocument__c STRING, Id STRING >, snapshotTime TIMESTAMP ) RETURNS STRUCT DETERMINISTIC LANGUAGE js OPTIONS (library=['gs://compliance-platform-public/jmespath.min.js']) AS r""" var BytesLib = new function () { this.normalize = function(arg) { return arg == null ? '' : arg; }; 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)); }; this.containsAll = function(arg, substrings) { if (substrings == null || substrings.length === 0) return false; let normalizedArg = this.normalize(arg); return substrings.every(sub => normalizedArg.includes(this.normalize(sub))); }; this.containsAny = function(arg, substrings) { if (substrings == null || substrings.length === 0) return false; let normalizedArg = this.normalize(arg); return substrings.some(sub => normalizedArg.includes(this.normalize(sub))); }; }(); 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)); }; this.containsAll = function(arg, substrings) { if (substrings == null || substrings.length === 0) return false; let normalizedArg = this.normalize(arg); return substrings.every(sub => normalizedArg.includes(this.normalize(sub))); }; this.containsAny = function(arg, substrings) { if (substrings == null || substrings.length === 0) return false; let normalizedArg = this.normalize(arg); return substrings.some(sub => normalizedArg.includes(this.normalize(sub))); }; }(); 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 jsonQueryChecked2() { var input = extract4.call(extract4); var out; try { out = jmespath.search(input, 'type(Statement)'); if (out != null && typeof out != 'string') { throw new Error("UNDETERMINED condition:103", {cause: {status: 'UNDETERMINED', conditionIndex: 103, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('type(Statement)').isResultTypeMismatch()", currentStateMessage: "The JSON query did not return text type.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}}); } } catch (e) { throw new Error("UNDETERMINED condition:104", {cause: {status: 'UNDETERMINED', conditionIndex: 104, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('type(Statement)').isEvaluationFailed()", currentStateMessage: "The JSON query has failed.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: e.message}}); } return out; } function jsonChecked5() { var input = extract7.call(extract7); input = TextLib.isEmpty(input) ? null : input; var out; try { out = JSON.parse(input); } catch (e) { throw new Error("UNDETERMINED condition:102", {cause: {status: 'UNDETERMINED', conditionIndex: 102, conditionText: "extract('CA10__policyDocument__c').asJson().isInvalid()", currentStateMessage: "IAM policy document JSON is invalid.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: e.message}}); } return out; } function fieldChecked8() { if (BytesLib.isEmpty(obj.CA10__policyDocument__c)) { throw new Error("UNDETERMINED condition:101", {cause: {status: 'UNDETERMINED', conditionIndex: 101, conditionText: "CA10__policyDocument__c.delegatedTo(CA10__policyDocument__c).isEmpty()", currentStateMessage: "Unable to determine the Policy Document. Possible permission issue with iam:GetGroupPolicy", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}}); } return obj.CA10__policyDocument__c; } function extract7() { if (!this.out) { this.out = fieldChecked8(); } return this.out; }; function extract4() { if (!this.out) { this.out = jsonChecked5(); } return this.out; }; function comparison9() { var comparisonLeft12 = jsonQueryChecked10(); return comparisonLeft12 != null && 0.0 != null && comparisonLeft12 > 0.0; } function jsonQueryChecked10() { var input = extract4.call(extract4); var out; try { out = jmespath.search(input, 'length(Statement[? Effect == \'Allow\' && (((type(Action) == \'array\') && (contains(Action, \'kms:Decrypt\') || contains(Action, \'kms:ReEncryptFrom\') || contains(Action, \'kms:*\') || contains(Action, \'kms:ReEncrypt*\'))) || ((type(Action) == \'string\') && (Action == \'kms:Decrypt\' || Action == \'kms:ReEncryptFrom\' || Action == \'kms:*\' || Action == \'kms:ReEncrypt*\'))) && (((type(Resource) == \'array\') && (contains(Resource, \'*\') || length(Resource[? (starts_with(@, \'arn:aws:kms:\') || starts_with(@, \'arn:*:kms:\')) && contains(@, \':key/*\')]) > `0`)) || ((type(Resource) == \'string\') && (Resource == \'*\' || ((starts_with(Resource, \'arn:aws:kms:\') || starts_with(Resource, \'arn:*:kms:\')) && contains(Resource, \':key/*\')))))])'); if (out != null && typeof out != 'number') { throw new Error("UNDETERMINED condition:105", {cause: {status: 'UNDETERMINED', conditionIndex: 105, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('length(Statement[? Effect == \\'Allow\\' && (((type(Action) == \\'array\\') && (contains(Action, \\'kms:Decrypt\\') || contains(Action, \\'kms:ReEncryptFrom\\') || contains(Action, \\'kms:*\\') || contains(Action, \\'kms:ReEncrypt*\\'))) || ((type(Action) == \\'string\\') && (Action == \\'kms:Decrypt\\' || Action == \\'kms:ReEncryptFrom\\' || Action == \\'kms:*\\' || Action == \\'kms:ReEncrypt*\\'))) && (((type(Resource) == \\'array\\') && (contains(Resource, \\'*\\') || length(Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`)) || ((type(Resource) == \\'string\\') && (Resource == \\'*\\' || ((starts_with(Resource, \\'arn:aws:kms:\\') || starts_with(Resource, \\'arn:*:kms:\\')) && contains(Resource, \\':key/*\\')))))])').isResultTypeMismatch()", currentStateMessage: "The JSON query did not return number type.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}}); } } catch (e) { throw new Error("UNDETERMINED condition:106", {cause: {status: 'UNDETERMINED', conditionIndex: 106, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('length(Statement[? Effect == \\'Allow\\' && (((type(Action) == \\'array\\') && (contains(Action, \\'kms:Decrypt\\') || contains(Action, \\'kms:ReEncryptFrom\\') || contains(Action, \\'kms:*\\') || contains(Action, \\'kms:ReEncrypt*\\'))) || ((type(Action) == \\'string\\') && (Action == \\'kms:Decrypt\\' || Action == \\'kms:ReEncryptFrom\\' || Action == \\'kms:*\\' || Action == \\'kms:ReEncrypt*\\'))) && (((type(Resource) == \\'array\\') && (contains(Resource, \\'*\\') || length(Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`)) || ((type(Resource) == \\'string\\') && (Resource == \\'*\\' || ((starts_with(Resource, \\'arn:aws:kms:\\') || starts_with(Resource, \\'arn:*:kms:\\')) && contains(Resource, \\':key/*\\')))))])').isEvaluationFailed()", currentStateMessage: "The JSON query has failed.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: e.message}}); } return out; } references1.push('Policy Document JSON [obj.CA10__policyDocument__c]: ' + obj.CA10__policyDocument__c); try { if (TextLib.equal(jsonQueryChecked2(), 'array') && comparison9()) { return {status: 'INCOMPLIANT', conditionIndex: 199, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('type(Statement)') == 'array' && extract('caJsonFrom_policyDocument__c').jsonQueryText('length(Statement[? Effect == \\'Allow\\' && (((type(Action) == \\'array\\') && (contains(Action, \\'kms:Decrypt\\') || contains(Action, \\'kms:ReEncryptFrom\\') || contains(Action, \\'kms:*\\') || contains(Action, \\'kms:ReEncrypt*\\'))) || ((type(Action) == \\'string\\') && (Action == \\'kms:Decrypt\\' || Action == \\'kms:ReEncryptFrom\\' || Action == \\'kms:*\\' || Action == \\'kms:ReEncrypt*\\'))) && (((type(Resource) == \\'array\\') && (contains(Resource, \\'*\\') || length(Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`)) || ((type(Resource) == \\'string\\') && (Resource == \\'*\\' || ((starts_with(Resource, \\'arn:aws:kms:\\') || starts_with(Resource, \\'arn:*:kms:\\')) && contains(Resource, \\':key/*\\')))))])') > number(0.0)", currentStateMessage: "This IAM group inline policy allows KMS decryption actions on all KMS keys.", currentStateReferences: references1.join('\n'), remediation: "Restrict KMS decryption permissions to only the specific KMS keys that the group inline policy should allow.", runtimeError: null}; } } catch (err) { if (err.cause && err.cause.status) { return err.cause; } else { throw err; } } // condition[2], conditionIndex:[200..299] function jsonQueryChecked13() { var input = extract15.call(extract15); var out; try { out = jmespath.search(input, '(Statement.Effect == \'Allow\') && ((((type(Statement.Action) == \'string\') && (Statement.Action == \'kms:Decrypt\' || Statement.Action == \'kms:ReEncryptFrom\' || Statement.Action == \'kms:*\' || Statement.Action == \'kms:ReEncrypt*\')) || ((type(Statement.Action) == \'array\') && (contains(Statement.Action, \'kms:Decrypt\') || contains(Statement.Action, \'kms:ReEncryptFrom\') || contains(Statement.Action, \'kms:*\') || contains(Statement.Action, \'kms:ReEncrypt*\')))) && (((type(Statement.Resource) == \'string\') && (Statement.Resource == \'*\' || ((starts_with(Statement.Resource, \'arn:aws:kms:\') || starts_with(Statement.Resource, \'arn:*:kms:\')) && contains(Statement.Resource, \':key/*\')))) || ((type(Statement.Resource) == \'array\') && (contains(Statement.Resource, \'*\') || length(Statement.Resource[? (starts_with(@, \'arn:aws:kms:\') || starts_with(@, \'arn:*:kms:\')) && contains(@, \':key/*\')]) > `0`))))'); if (out != null && typeof out != 'boolean') { throw new Error("UNDETERMINED condition:203", {cause: {status: 'UNDETERMINED', conditionIndex: 203, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('(Statement.Effect == \\'Allow\\') && ((((type(Statement.Action) == \\'string\\') && (Statement.Action == \\'kms:Decrypt\\' || Statement.Action == \\'kms:ReEncryptFrom\\' || Statement.Action == \\'kms:*\\' || Statement.Action == \\'kms:ReEncrypt*\\')) || ((type(Statement.Action) == \\'array\\') && (contains(Statement.Action, \\'kms:Decrypt\\') || contains(Statement.Action, \\'kms:ReEncryptFrom\\') || contains(Statement.Action, \\'kms:*\\') || contains(Statement.Action, \\'kms:ReEncrypt*\\')))) && (((type(Statement.Resource) == \\'string\\') && (Statement.Resource == \\'*\\' || ((starts_with(Statement.Resource, \\'arn:aws:kms:\\') || starts_with(Statement.Resource, \\'arn:*:kms:\\')) && contains(Statement.Resource, \\':key/*\\')))) || ((type(Statement.Resource) == \\'array\\') && (contains(Statement.Resource, \\'*\\') || length(Statement.Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`))))').isResultTypeMismatch()", currentStateMessage: "The JSON query did not return boolean type.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}}); } } catch (e) { throw new Error("UNDETERMINED condition:204", {cause: {status: 'UNDETERMINED', conditionIndex: 204, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('(Statement.Effect == \\'Allow\\') && ((((type(Statement.Action) == \\'string\\') && (Statement.Action == \\'kms:Decrypt\\' || Statement.Action == \\'kms:ReEncryptFrom\\' || Statement.Action == \\'kms:*\\' || Statement.Action == \\'kms:ReEncrypt*\\')) || ((type(Statement.Action) == \\'array\\') && (contains(Statement.Action, \\'kms:Decrypt\\') || contains(Statement.Action, \\'kms:ReEncryptFrom\\') || contains(Statement.Action, \\'kms:*\\') || contains(Statement.Action, \\'kms:ReEncrypt*\\')))) && (((type(Statement.Resource) == \\'string\\') && (Statement.Resource == \\'*\\' || ((starts_with(Statement.Resource, \\'arn:aws:kms:\\') || starts_with(Statement.Resource, \\'arn:*:kms:\\')) && contains(Statement.Resource, \\':key/*\\')))) || ((type(Statement.Resource) == \\'array\\') && (contains(Statement.Resource, \\'*\\') || length(Statement.Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`))))').isEvaluationFailed()", currentStateMessage: "The JSON query has failed.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: e.message}}); } return out; } function jsonChecked16() { var input = extract18.call(extract18); input = TextLib.isEmpty(input) ? null : input; var out; try { out = JSON.parse(input); } catch (e) { throw new Error("UNDETERMINED condition:202", {cause: {status: 'UNDETERMINED', conditionIndex: 202, conditionText: "extract('CA10__policyDocument__c').asJson().isInvalid()", currentStateMessage: "IAM policy document JSON is invalid.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: e.message}}); } return out; } function fieldChecked19() { if (BytesLib.isEmpty(obj.CA10__policyDocument__c)) { throw new Error("UNDETERMINED condition:201", {cause: {status: 'UNDETERMINED', conditionIndex: 201, conditionText: "CA10__policyDocument__c.delegatedTo(CA10__policyDocument__c).isEmpty()", currentStateMessage: "Unable to determine the Policy Document. Possible permission issue with iam:GetGroupPolicy", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}}); } return obj.CA10__policyDocument__c; } function extract18() { if (!this.out) { this.out = fieldChecked19(); } return this.out; }; function extract15() { if (!this.out) { this.out = jsonChecked16(); } return this.out; }; try { if (jsonQueryChecked13() == true) { return {status: 'INCOMPLIANT', conditionIndex: 299, conditionText: "extract('caJsonFrom_policyDocument__c').jsonQueryText('(Statement.Effect == \\'Allow\\') && ((((type(Statement.Action) == \\'string\\') && (Statement.Action == \\'kms:Decrypt\\' || Statement.Action == \\'kms:ReEncryptFrom\\' || Statement.Action == \\'kms:*\\' || Statement.Action == \\'kms:ReEncrypt*\\')) || ((type(Statement.Action) == \\'array\\') && (contains(Statement.Action, \\'kms:Decrypt\\') || contains(Statement.Action, \\'kms:ReEncryptFrom\\') || contains(Statement.Action, \\'kms:*\\') || contains(Statement.Action, \\'kms:ReEncrypt*\\')))) && (((type(Statement.Resource) == \\'string\\') && (Statement.Resource == \\'*\\' || ((starts_with(Statement.Resource, \\'arn:aws:kms:\\') || starts_with(Statement.Resource, \\'arn:*:kms:\\')) && contains(Statement.Resource, \\':key/*\\')))) || ((type(Statement.Resource) == \\'array\\') && (contains(Statement.Resource, \\'*\\') || length(Statement.Resource[? (starts_with(@, \\'arn:aws:kms:\\') || starts_with(@, \\'arn:*:kms:\\')) && contains(@, \\':key/*\\')]) > `0`))))') == true", currentStateMessage: "This IAM group inline policy allows KMS decryption actions on all KMS keys.", currentStateReferences: references1.join('\n'), remediation: "Restrict KMS decryption permissions to only the specific KMS keys that the group inline policy should allow.", runtimeError: null}; } } catch (err) { if (err.cause && err.cause.status) { return err.cause; } else { throw err; } } return {status: 'COMPLIANT', conditionIndex: 300, conditionText: "otherwise", currentStateMessage: "This IAM group inline policy does not allow KMS decryption actions on all KMS keys.", 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.CA10__disappearanceTime__c AS CA10__disappearanceTime__c, sObject.CA10__policyDocument__c AS CA10__policyDocument__c, sObject.Id AS Id, process_CA10__CaAwsGroupPolicy__c( STRUCT( sObject.CA10__disappearanceTime__c AS CA10__disappearanceTime__c, sObject.CA10__policyDocument__c AS CA10__policyDocument__c, sObject.Id AS Id ), sObject.context.snapshotTime ) as result FROM UNNEST(mock_CA10__CaAwsGroupPolicy__c()) AS sObject ) sObject ON sObject.Id = expectedResult.Id;