--- policy: /ce/ca/oracle/iam/user-has-more-than-one-active-api-key logic: /ce/ca/oracle/iam/user-has-more-than-one-active-api-key/prod.logic.yaml executionTime: 2026-05-02T12:07:25.703177926Z generationMs: 60 executionMs: 2753 rows: - id: test1 match: true status: expected: INCOMPLIANT actual: INCOMPLIANT conditionIndex: expected: 299 actual: 299 conditionText: expected: CA10O1__Oracle_IAM_User_API_Keys__r.count(COMPLIANT) > number(1.0) actual: CA10O1__Oracle_IAM_User_API_Keys__r.count(COMPLIANT) > number(1.0) runtimeError: {} - id: test2 match: true status: expected: COMPLIANT actual: COMPLIANT conditionIndex: expected: 300 actual: 300 conditionText: expected: otherwise actual: otherwise runtimeError: {} - id: test3 match: true status: expected: COMPLIANT actual: COMPLIANT conditionIndex: expected: 300 actual: 300 conditionText: expected: otherwise actual: otherwise runtimeError: {} - id: test4 match: true status: expected: INAPPLICABLE actual: INAPPLICABLE conditionIndex: expected: 199 actual: 199 conditionText: expected: extract('CA10O1__lifecycleState__c') != 'ACTIVE' actual: extract('CA10O1__lifecycleState__c') != 'ACTIVE' runtimeError: {} usedFiles: - path: /ce/ca/oracle/iam/user-has-more-than-one-active-api-key/policy.yaml md5Hash: 00670D8F030C8F80A1FC40005A91C852 content: | --- names: full: Oracle IAM User has more than one active API key contextual: IAM User has more than one active API key description: > Oracle IAM users should have no more than one active API key. Extra active API keys increase credential exposure risk and should be removed after key rotation or migration is complete. type: COMPLIANCE_POLICY categories: - SECURITY frameworkMappings: - "/frameworks/cis-oracle-v3.1.0/01/17" - "/frameworks/cloudaware/identity-and-access-governance/credential-lifecycle-management" - path: /ce/ca/oracle/iam/user-has-more-than-one-active-api-key/prod.logic.yaml md5Hash: A7DAB30DB4FC65725E3AD11784E07D2B content: | --- inputType: "CA10O1__CaOracleIamUser__c" testData: - file: test-data.json importExtracts: - file: /types/CA10O1__CaOracleIamUser__c/object.extracts.yaml conditions: - status: "INAPPLICABLE" currentStateMessage: "This Oracle IAM user is not active." check: NOT_EQUAL: left: EXTRACT: "CA10O1__lifecycleState__c" right: TEXT: "ACTIVE" - status: "INCOMPLIANT" currentStateMessage: "This active Oracle IAM user has more than one active API key." remediationMessage: "Delete redundant active API keys so only one remains for this Oracle IAM user." check: GREATER_THAN: left: RELATED_LIST_COUNT: status: "COMPLIANT" relationshipName: "CA10O1__Oracle_IAM_User_API_Keys__r" right: NUMBER: 1.0 otherwise: status: "COMPLIANT" currentStateMessage: "This active Oracle IAM user has no more than one active API key." relatedLists: - relationshipName: "CA10O1__Oracle_IAM_User_API_Keys__r" importExtracts: - file: /types/CA10O1__CaOracleIamUserApiKey__c/object.extracts.yaml conditions: - status: "COMPLIANT" currentStateMessage: "This Oracle IAM API key is active." check: IS_EQUAL: left: EXTRACT: "CA10O1__lifecycleState__c" right: TEXT: "ACTIVE" otherwise: status: "INAPPLICABLE" currentStateMessage: "This Oracle IAM API key is not active." - path: /ce/ca/oracle/iam/user-has-more-than-one-active-api-key/test-data.json md5Hash: 631D80373263588B32C4AD5183E9B363 content: | [ { "expectedResult": { "status": "INCOMPLIANT", "conditionIndex": "299", "conditionText": "CA10O1__Oracle_IAM_User_API_Keys__r.count(COMPLIANT) > number(1.0)", "runtimeError": null }, "context": { "snapshotTime": "2026-04-12T00:00:00Z" }, "Id": "test1", "CA10O1__disappearanceTime__c": null, "CA10O1__lifecycleState__c": "ACTIVE", "CA10O1__Oracle_IAM_User_API_Keys__r": [ { "Id": "test1_1", "CA10O1__disappearanceTime__c": null, "CA10O1__user__c": "test1", "CA10O1__lifecycleState__c": "ACTIVE" }, { "Id": "test1_2", "CA10O1__disappearanceTime__c": null, "CA10O1__user__c": "test1", "CA10O1__lifecycleState__c": "ACTIVE" } ] }, { "expectedResult": { "status": "COMPLIANT", "conditionIndex": "300", "conditionText": "otherwise", "runtimeError": null }, "context": { "snapshotTime": "2026-04-12T00:00:00Z" }, "Id": "test2", "CA10O1__disappearanceTime__c": null, "CA10O1__lifecycleState__c": "ACTIVE", "CA10O1__Oracle_IAM_User_API_Keys__r": [] }, { "expectedResult": { "status": "COMPLIANT", "conditionIndex": "300", "conditionText": "otherwise", "runtimeError": null }, "context": { "snapshotTime": "2026-04-12T00:00:00Z" }, "Id": "test3", "CA10O1__disappearanceTime__c": null, "CA10O1__lifecycleState__c": "ACTIVE", "CA10O1__Oracle_IAM_User_API_Keys__r": [ { "Id": "test3_1", "CA10O1__disappearanceTime__c": null, "CA10O1__user__c": "test3", "CA10O1__lifecycleState__c": "ACTIVE" } ] }, { "expectedResult": { "status": "INAPPLICABLE", "conditionIndex": "199", "conditionText": "extract('CA10O1__lifecycleState__c') != 'ACTIVE'", "runtimeError": null }, "context": { "snapshotTime": "2026-04-12T00:00:00Z" }, "Id": "test4", "CA10O1__disappearanceTime__c": null, "CA10O1__lifecycleState__c": "DELETED", "CA10O1__Oracle_IAM_User_API_Keys__r": [ { "Id": "test4_1", "CA10O1__disappearanceTime__c": null, "CA10O1__user__c": "test4", "CA10O1__lifecycleState__c": "ACTIVE" } ] } ] - path: /types/CA10O1__CaOracleIamUserApiKey__c/object.extracts.yaml md5Hash: AA56F5592EB714844CCA7BC8D8BA5839 content: | --- extracts: # Not nullable. - name: "CA10O1__lifecycleState__c" value: FIELD: path: "CA10O1__lifecycleState__c" # Not nullable. - name: "CA10O1__timeCreated__c" value: FIELD: path: "CA10O1__timeCreated__c" - path: /types/CA10O1__CaOracleIamUser__c/object.extracts.yaml md5Hash: 47F91526ED7905B2BD0F0545EF1BCEAA content: | --- extracts: # Not nullable. - name: "CA10O1__lifecycleState__c" value: FIELD: path: "CA10O1__lifecycleState__c" undeterminedIf: isEmpty: "User lifecycle state should not be empty." # Values: Activated, Deactivated. Not nullable. - name: "CA10O1__mfaStatus__c" value: FIELD: path: "CA10O1__mfaStatus__c" undeterminedIf: isEmpty: "User MFA status should not be empty." script: |- CREATE TEMP FUNCTION mock_ExpectedResult() RETURNS ARRAY >> DETERMINISTIC LANGUAGE js AS r""" return [ { "Id" : "test1", "expectedResult" : { "status" : "INCOMPLIANT", "conditionIndex" : "299", "conditionText" : "CA10O1__Oracle_IAM_User_API_Keys__r.count(COMPLIANT) > number(1.0)", "runtimeError" : null } }, { "Id" : "test2", "expectedResult" : { "status" : "COMPLIANT", "conditionIndex" : "300", "conditionText" : "otherwise", "runtimeError" : null } }, { "Id" : "test3", "expectedResult" : { "status" : "COMPLIANT", "conditionIndex" : "300", "conditionText" : "otherwise", "runtimeError" : null } }, { "Id" : "test4", "expectedResult" : { "status" : "INAPPLICABLE", "conditionIndex" : "199", "conditionText" : "extract('CA10O1__lifecycleState__c') != 'ACTIVE'", "runtimeError" : null } } ]; """; CREATE TEMP FUNCTION mock_CA10O1__CaOracleIamUser__c() RETURNS ARRAY >> DETERMINISTIC LANGUAGE js AS r""" return [ { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "ACTIVE", "Id" : "test1" }, { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "ACTIVE", "Id" : "test2" }, { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "ACTIVE", "Id" : "test3" }, { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "DELETED", "Id" : "test4" } ]; """; CREATE TEMP FUNCTION mock_CA10O1__CaOracleIamUserApiKey__c() RETURNS ARRAY >> DETERMINISTIC LANGUAGE js AS r""" return [ { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "ACTIVE", "CA10O1__user__c" : "test1", "Id" : "test1_1" }, { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "ACTIVE", "CA10O1__user__c" : "test1", "Id" : "test1_2" }, { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "ACTIVE", "CA10O1__user__c" : "test3", "Id" : "test3_1" }, { "context" : { "snapshotTime" : new Date("2026-04-12T00:00:00Z") }, "CA10O1__lifecycleState__c" : "ACTIVE", "CA10O1__user__c" : "test4", "Id" : "test4_1" } ]; """; CREATE TEMP FUNCTION process_CA10O1__CaOracleIamUser__c( obj STRUCT< CA10O1__disappearanceTime__c TIMESTAMP, CA10O1__lifecycleState__c STRING, Id STRING, CA10O1__Oracle_IAM_User_API_Keys__r ARRAY >> >, snapshotTime TIMESTAMP ) RETURNS STRUCT 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)); }; 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 Oracle [CA10O1__disappearanceTime__c]: ' + obj.CA10O1__disappearanceTime__c); if (obj.CA10O1__disappearanceTime__c != null) { return {status: 'DISAPPEARED', conditionIndex: 99, conditionText: "isDisappeared(CA10O1__disappearanceTime__c)", currentStateMessage: "Object is deleted in the source", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}; } // condition[1], conditionIndex:[100..199] function extract3() { if (!this.out) { this.out = obj.CA10O1__lifecycleState__c; } return this.out; }; references1.push('Lifecycle State [obj.CA10O1__lifecycleState__c]: ' + obj.CA10O1__lifecycleState__c); if (TextLib.notEqual(extract3.call(extract3), 'ACTIVE')) { return {status: 'INAPPLICABLE', conditionIndex: 199, conditionText: "extract('CA10O1__lifecycleState__c') != 'ACTIVE'", currentStateMessage: "This Oracle IAM user is not active.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}; } var count_CA10O1__Oracle_IAM_User_API_Keys__r_COMPLIANT6 = 0; if (obj.CA10O1__Oracle_IAM_User_API_Keys__r != null) { for (var i7 = 0; i7 < obj.CA10O1__Oracle_IAM_User_API_Keys__r.length; i7++) { if (typeof(obj.CA10O1__Oracle_IAM_User_API_Keys__r[i7].status) !== 'undefined') { if (obj.CA10O1__Oracle_IAM_User_API_Keys__r[i7].status == 'COMPLIANT') { count_CA10O1__Oracle_IAM_User_API_Keys__r_COMPLIANT6 += obj.CA10O1__Oracle_IAM_User_API_Keys__r[i7].count; } } else { if (obj.CA10O1__Oracle_IAM_User_API_Keys__r[i7].result.status == 'COMPLIANT') { count_CA10O1__Oracle_IAM_User_API_Keys__r_COMPLIANT6 += 1; } } } } // condition[2], conditionIndex:[200..299] references1.push('Related list [CA10O1__Oracle_IAM_User_API_Keys__r] has ' + count_CA10O1__Oracle_IAM_User_API_Keys__r_COMPLIANT6 + ' objects in COMPLIANT status'); if (count_CA10O1__Oracle_IAM_User_API_Keys__r_COMPLIANT6 != null && 1.0 != null && count_CA10O1__Oracle_IAM_User_API_Keys__r_COMPLIANT6 > 1.0) { return {status: 'INCOMPLIANT', conditionIndex: 299, conditionText: "CA10O1__Oracle_IAM_User_API_Keys__r.count(COMPLIANT) > number(1.0)", currentStateMessage: "This active Oracle IAM user has more than one active API key.", currentStateReferences: references1.join('\n'), remediation: "Delete redundant active API keys so only one remains for this Oracle IAM user.", runtimeError: null}; } return {status: 'COMPLIANT', conditionIndex: 300, conditionText: "otherwise", currentStateMessage: "This active Oracle IAM user has no more than one active API key.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}; """; CREATE TEMP FUNCTION process_CA10O1__Oracle_IAM_User_API_Keys__r( obj STRUCT< CA10O1__disappearanceTime__c TIMESTAMP, CA10O1__lifecycleState__c STRING, CA10O1__user__c STRING, Id STRING >, snapshotTime TIMESTAMP ) RETURNS STRUCT 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)); }; 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 Oracle [CA10O1__disappearanceTime__c]: ' + obj.CA10O1__disappearanceTime__c); if (obj.CA10O1__disappearanceTime__c != null) { return {status: 'DISAPPEARED', conditionIndex: 99, conditionText: "isDisappeared(CA10O1__disappearanceTime__c)", currentStateMessage: "Object is deleted in the source", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}; } // condition[1], conditionIndex:[100..199] function extract3() { if (!this.out) { this.out = obj.CA10O1__lifecycleState__c; } return this.out; }; references1.push('Lifecycle State [obj.CA10O1__lifecycleState__c]: ' + obj.CA10O1__lifecycleState__c); if (TextLib.equal(extract3.call(extract3), 'ACTIVE')) { return {status: 'COMPLIANT', conditionIndex: 199, conditionText: "extract('CA10O1__lifecycleState__c') == 'ACTIVE'", currentStateMessage: "This Oracle IAM API key is active.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null}; } return {status: 'INAPPLICABLE', conditionIndex: 200, conditionText: "otherwise", currentStateMessage: "This Oracle IAM API key is not active.", 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.CA10O1__disappearanceTime__c AS CA10O1__disappearanceTime__c, sObject.CA10O1__lifecycleState__c AS CA10O1__lifecycleState__c, sObject.Id AS Id, `CA10O1__Oracle_IAM_User_API_Keys__r`.arr AS CA10O1__Oracle_IAM_User_API_Keys__r, process_CA10O1__CaOracleIamUser__c( STRUCT( sObject.CA10O1__disappearanceTime__c AS CA10O1__disappearanceTime__c, sObject.CA10O1__lifecycleState__c AS CA10O1__lifecycleState__c, sObject.Id AS Id, `CA10O1__Oracle_IAM_User_API_Keys__r`.arr AS CA10O1__Oracle_IAM_User_API_Keys__r ), sObject.context.snapshotTime ) as result FROM UNNEST(mock_CA10O1__CaOracleIamUser__c()) AS sObject LEFT JOIN ( SELECT sObject.CA10O1__user__c, ARRAY_AGG( STRUCT( sObject.CA10O1__disappearanceTime__c AS CA10O1__disappearanceTime__c, sObject.CA10O1__lifecycleState__c AS CA10O1__lifecycleState__c, sObject.CA10O1__user__c AS CA10O1__user__c, sObject.Id AS Id, process_CA10O1__Oracle_IAM_User_API_Keys__r( STRUCT( sObject.CA10O1__disappearanceTime__c AS CA10O1__disappearanceTime__c, sObject.CA10O1__lifecycleState__c AS CA10O1__lifecycleState__c, sObject.CA10O1__user__c AS CA10O1__user__c, sObject.Id AS Id ), sObject.context.snapshotTime ) as result ) ) AS arr FROM UNNEST(mock_CA10O1__CaOracleIamUserApiKey__c()) AS sObject GROUP BY sObject.CA10O1__user__c ) AS `CA10O1__Oracle_IAM_User_API_Keys__r` ON sObject.Id = `CA10O1__Oracle_IAM_User_API_Keys__r`.CA10O1__user__c ) sObject ON sObject.Id = expectedResult.Id;