---
policy: /ce/ca/aws/ec2/instance-iam-role
logic: /ce/ca/aws/ec2/instance-iam-role/prod.logic.yaml
executionTime: 2025-04-24T23:44:30.424168181Z
rows:
  - id: a01
    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: a02
    match: true
    status:
      expected: COMPLIANT
      actual: COMPLIANT
    conditionIndex:
      expected: 199
      actual: 199
    conditionText:
      expected: extract('CA10__iamInstanceProfileArn__c').isNotEmpty()
      actual: extract('CA10__iamInstanceProfileArn__c').isNotEmpty()
    runtimeError: {}
  - id: a03
    match: true
    status:
      expected: INCOMPLIANT
      actual: INCOMPLIANT
    conditionIndex:
      expected: 200
      actual: 200
    conditionText:
      expected: otherwise
      actual: otherwise
    runtimeError: {}
usedFiles:
  - path: /ce/ca/aws/ec2/instance-iam-role/policy.yaml
    md5Hash: 9444BCA5431150BBAD5A75E80F3D6852
    content: |
      ---
      names:
        full: AWS EC2 Instance IAM role is not attached
        contextual: Instance IAM role is not attached
      description: AWS access from within AWS instances can be done by either encoding AWS
        keys into AWS API calls or by assigning the instance to a role which has an appropriate
        permissions policy for the required access. 'AWS Access' means accessing the APIs
        of AWS in order to access AWS resources or manage AWS account resources.
      type: COMPLIANCE_POLICY
      categories:
        - SECURITY
      frameworkMappings:
        - "/frameworks/cis-aws-v5.0.0/01/17"
        - "/frameworks/cloudaware/resource-security/secure-access"
      similarPolicies:
        internal:
          - dec-x-6c93750d
        cloudConformity:
          - url: https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/EC2/ec2-instance-using-iam-roles.html
            name: EC2 Instance Using IAM Roles
  - path: /ce/ca/aws/ec2/instance-iam-role/prod.logic.yaml
    md5Hash: 78BF396827C8F90A7DBEBBC817501D75
    content: |
      ---
      inputType: "CA10__CaAwsInstance__c"
      testData:
        - file: test-data.json
      importExtracts:
        - file: /types/CA10__CaAwsInstance__c/object.extracts.yaml
      conditions:
        - status: "COMPLIANT"
          currentStateMessage: "The instance has an IAM role attached."
          check:
            NOT_EMPTY:
              arg:
                EXTRACT: "CA10__iamInstanceProfileArn__c"
      otherwise:
        status: "INCOMPLIANT"
        currentStateMessage: "The instance doesn't have an IAM role attached."
        remediationMessage: "Consider attaching an IAM role to the instance."
  - path: /types/CA10__CaAwsInstance__c/object.extracts.yaml
    md5Hash: 802FA80DBDE640AF85A69B42E51E0CCD
    content: "---\nextracts:\n# Values pending, applied. Not nullable. Can't have\
      \ no access, retrieved via ec2:DescribeInstances\n  - name: \"CA10__metadataState__c\"\
      \n    value: \n      FIELD:\n        path: \"CA10__metadataState__c\"\n    \
      \    undeterminedIf:\n          isEmpty: \"Corrupted data. EC2 Instances Metadata\
      \ State cannot be empty.\"\n# Values: optional, required. Not nullable. Can't\
      \ have no access, retrieved via ec2:DescribeInstances\n  - name: \"CA10__metadataHttpTokens__c\"\
      \n    value: \n      FIELD:\n        path: \"CA10__metadataHttpTokens__c\"\n\
      \        undeterminedIf:\n          isEmpty: \"Corrupted data. EC2 Instances\
      \ Metadata Http Token cannot be empty.\"\n  - name: CA10__iamInstanceProfileArn__c\n\
      \    value:\n      FIELD: \n        path: CA10__iamInstanceProfileArn__c\n#\
      \ Nullable. Can't have no access, retrieved via ec2:DescribeInstances\n  - name:\
      \ \"CA10__publicIpAddress__c\"\n    value: \n      FIELD:\n        path: \"\
      CA10__publicIpAddress__c\"\n# Values: enabled, disabled. Not nullable. Can't\
      \ have no access, retrieved via ec2:DescribeInstances\n  - name: \"CA10__monitoringState__c\"\
      \n    value: \n      FIELD:\n        path: \"CA10__monitoringState__c\"\n  \
      \      undeterminedIf:\n          isEmpty: \"Corrupted data. EC2 Instances Detailed\
      \ Monitoring State cannot be empty.\"\n# Values: pending | running | shutting-down\
      \ | terminated | stopping | stopped. Not nullable.\n  - name: \"CA10__stateName__c\"\
      \n    value: \n      FIELD:\n        path: \"CA10__stateName__c\"\n        undeterminedIf:\n\
      \          noAccessDelegate:\n            path: \"CA10__stateName__c\"\n   \
      \         currentStateMessage: \"Unable to determine EC2 Instances State Name.\
      \ Possible permission issue with ec2:DescribeInstanceStatus\"\n# Number of Days.\
      \ Nullable. Can't have no access, retrieved via ec2:DescribeInstances\n  - name:\
      \ \"CA10__currentRunningTime__c\"\n    value: \n      FIELD:\n        path:\
      \ \"CA10__currentRunningTime__c\"      \n# Nullable.\n  - name: \"CA10__averageCpuTwoWeeks__c\"\
      \n    value: \n      FIELD:\n        path: \"CA10__averageCpuTwoWeeks__c\" \
      \     \n# Nullable.\n  - name: \"CA10__maxCpuTwoWeeks__c\"\n    value: \n  \
      \    FIELD:\n        path: \"CA10__maxCpuTwoWeeks__c\"      \n# Nullable.\n\
      \  - name: \"CA10__sumTwoWeekNetworkOutMb__c\"\n    value: \n      FIELD:\n\
      \        path: \"CA10__sumTwoWeekNetworkOutMb__c\"      \n# Nullable.\n  - name:\
      \ \"CA10__sumTwoWeekNetworkInMb__c\"\n    value: \n      FIELD:\n        path:\
      \ \"CA10__sumTwoWeekNetworkInMb__c\"      \n"
  - path: /ce/ca/aws/ec2/instance-iam-role/test-data.json
    md5Hash: FE3C2257B0089178EDFB3234391E48BB
    content: |-
      [
        {
          "expectedResult": {
            "status": "DISAPPEARED",
            "conditionIndex": "99",
            "conditionText": "isDisappeared(CA10__disappearanceTime__c)",
            "runtimeError": null
          },
          "context": {
            "snapshotTime": "2024-06-19T07:55:48Z"
          },
          "Id": "a01",
          "CA10__disappearanceTime__c": "2024-06-18T13:02:29Z",
          "CA10__iamInstanceProfileArn__c": ""
        },
        {
          "expectedResult": {
            "status": "COMPLIANT",
            "conditionIndex": "199",
            "conditionText": "extract('CA10__iamInstanceProfileArn__c').isNotEmpty()",
            "runtimeError": null
          },
          "context": {
            "snapshotTime": "2024-06-19T07:55:48Z"
          },
          "Id": "a02",
          "CA10__disappearanceTime__c": null,
          "CA10__iamInstanceProfileArn__c": "arn:aws:iam::1234567890:instance-profile/ProfileArn"
        },
        {
          "expectedResult": {
            "status": "INCOMPLIANT",
            "conditionIndex": "200",
            "conditionText": "otherwise",
            "runtimeError": null
          },
          "context": {
            "snapshotTime": "2024-06-19T07:55:48Z"
          },
          "Id": "a03",
          "CA10__disappearanceTime__c": null,
          "CA10__iamInstanceProfileArn__c": ""
        }
      ]
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" : "a01",
    "expectedResult" : {
      "status" : "DISAPPEARED",
      "conditionIndex" : "99",
      "conditionText" : "isDisappeared(CA10__disappearanceTime__c)",
      "runtimeError" : null
    }
  }, {
    "Id" : "a02",
    "expectedResult" : {
      "status" : "COMPLIANT",
      "conditionIndex" : "199",
      "conditionText" : "extract('CA10__iamInstanceProfileArn__c').isNotEmpty()",
      "runtimeError" : null
    }
  }, {
    "Id" : "a03",
    "expectedResult" : {
      "status" : "INCOMPLIANT",
      "conditionIndex" : "200",
      "conditionText" : "otherwise",
      "runtimeError" : null
    }
  } ];
  """;

  CREATE TEMP FUNCTION mock_CA10__CaAwsInstance__c()
  RETURNS ARRAY<STRUCT<
      Id STRING,
      CA10__disappearanceTime__c TIMESTAMP,
      CA10__iamInstanceProfileArn__c STRING,
      context STRUCT<
          snapshotTime TIMESTAMP
      >
  >>
  DETERMINISTIC
  LANGUAGE js
  AS r"""
    return [ {
    "context" : {
      "snapshotTime" : new Date("2024-06-19T07:55:48Z")
    },
    "Id" : "a01",
    "CA10__disappearanceTime__c" : new Date("2024-06-18T13:02:29Z"),
    "CA10__iamInstanceProfileArn__c" : ""
  }, {
    "context" : {
      "snapshotTime" : new Date("2024-06-19T07:55:48Z")
    },
    "Id" : "a02",
    "CA10__iamInstanceProfileArn__c" : "arn:aws:iam::1234567890:instance-profile/ProfileArn"
  }, {
    "context" : {
      "snapshotTime" : new Date("2024-06-19T07:55:48Z")
    },
    "Id" : "a03",
    "CA10__iamInstanceProfileArn__c" : ""
  } ];
  """;

  CREATE TEMP FUNCTION process_CA10__CaAwsInstance__c(
      obj STRUCT<
          Id STRING,
          CA10__disappearanceTime__c TIMESTAMP,
          CA10__iamInstanceProfileArn__c STRING
      >,
      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 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 extract3() { if (!this.out) { this.out = obj.CA10__iamInstanceProfileArn__c; } return this.out; };
      references1.push('IAM Instance Profile ARN [obj.CA10__iamInstanceProfileArn__c]: ' + obj.CA10__iamInstanceProfileArn__c);
      if (TextLib.isNotEmpty(extract3.call(extract3))) {
          return {status: 'COMPLIANT', conditionIndex: 199, conditionText: "extract('CA10__iamInstanceProfileArn__c').isNotEmpty()", currentStateMessage: "The instance has an IAM role attached.", currentStateReferences: references1.join('\n'), remediation: null, runtimeError: null};
      }
      return {status: 'INCOMPLIANT', conditionIndex: 200, conditionText: "otherwise", currentStateMessage: "The instance doesn't have an IAM role attached.", currentStateReferences: references1.join('\n'), remediation: "Consider attaching an IAM role to the instance.", 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__iamInstanceProfileArn__c AS CA10__iamInstanceProfileArn__c,
          process_CA10__CaAwsInstance__c(
              STRUCT(
                  sObject.Id AS Id,
                  sObject.CA10__disappearanceTime__c AS CA10__disappearanceTime__c,
                  sObject.CA10__iamInstanceProfileArn__c AS CA10__iamInstanceProfileArn__c
              ),
              sObject.context.snapshotTime
          ) as result
      FROM UNNEST(mock_CA10__CaAwsInstance__c()) AS sObject
  ) sObject ON sObject.Id = expectedResult.Id;
