Table: aws_ec2_instances

This table shows data for Amazon Elastic Compute Cloud (EC2) Instances.

https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Instance.html (opens in a new tab)

The primary key for this table is arn.

Columns

NameType
_cq_iduuid
_cq_parent_iduuid
account_idutf8
regionutf8
arn (PK)utf8
state_transition_reason_timetimestamp[us, tz=UTC]
tagsjson
ami_launch_indexint64
architectureutf8
block_device_mappingsjson
boot_modeutf8
capacity_reservation_idutf8
capacity_reservation_specificationjson
client_tokenutf8
cpu_optionsjson
current_instance_boot_modeutf8
ebs_optimizedbool
elastic_gpu_associationsjson
elastic_inference_accelerator_associationsjson
ena_supportbool
enclave_optionsjson
hibernation_optionsjson
hypervisorutf8
iam_instance_profilejson
image_idutf8
instance_idutf8
instance_lifecycleutf8
instance_typeutf8
ipv6_addressutf8
kernel_idutf8
key_nameutf8
launch_timetimestamp[us, tz=UTC]
licensesjson
maintenance_optionsjson
metadata_optionsjson
monitoringjson
network_interfacesjson
outpost_arnutf8
placementjson
platformutf8
platform_detailsutf8
private_dns_nameutf8
private_dns_name_optionsjson
private_ip_addressutf8
product_codesjson
public_dns_nameutf8
public_ip_addressutf8
ramdisk_idutf8
root_device_nameutf8
root_device_typeutf8
security_groupsjson
source_dest_checkbool
spot_instance_request_idutf8
sriov_net_supportutf8
statejson
state_reasonjson
state_transition_reasonutf8
subnet_idutf8
tpm_supportutf8
usage_operationutf8
usage_operation_update_timetimestamp[us, tz=UTC]
virtualization_typeutf8
vpc_idutf8

Example Queries

These SQL queries are sampled from CloudQuery policies and are compatible with PostgreSQL.

EC2 instances should not use multiple ENIs

WITH
  data
    AS (
      SELECT
        account_id, instance_id, count(nics->>'Status') AS cnt
      FROM
        aws_ec2_instances
        LEFT JOIN jsonb_array_elements(aws_ec2_instances.network_interfaces)
            AS nics ON true
      GROUP BY
        account_id, instance_id
    )
SELECT
  'EC2 instances should not use multiple ENIs' AS title,
  account_id,
  instance_id AS resource_id,
  CASE WHEN cnt > 1 THEN 'fail' ELSE 'pass' END AS status
FROM
  data;

EC2 instances should not have a public IP address

SELECT
  'EC2 instances should not have a public IP address' AS title,
  account_id,
  instance_id AS resource_id,
  CASE WHEN public_ip_address IS NOT NULL THEN 'fail' ELSE 'pass' END AS status
FROM
  aws_ec2_instances;

Security group is not currently in use so it should be deleted

WITH
  interface_groups
    AS (
      SELECT
        DISTINCT g->>'GroupId' AS id
      FROM
        aws_ec2_instances AS i,
        jsonb_array_elements(network_interfaces) AS a,
        jsonb_array_elements(a->'Groups') AS g
    )
SELECT
  'security group is not currently in use so it should be deleted' AS title,
  account_id,
  arn AS resource_id,
  CASE WHEN interface_groups.id IS NULL THEN 'fail' ELSE 'pass' END AS status
FROM
  aws_ec2_security_groups
  LEFT JOIN interface_groups ON
      aws_ec2_security_groups.group_id = interface_groups.id;

EC2 instances should use IMDSv2

SELECT
  'EC2 instances should use IMDSv2' AS title,
  account_id,
  instance_id AS resource_id,
  CASE
  WHEN metadata_options->>'HttpTokens' IS DISTINCT FROM 'required' THEN 'fail'
  ELSE 'pass'
  END
    AS status
FROM
  aws_ec2_instances;

Find all ec2 instances that have unrestricted access to the internet with a wide open security group and routing

-- Find all AWS instances that are in a subnet that includes a catchall route
SELECT
  'Find all ec2 instances that have unrestricted access to the internet with a wide open security group and routing'
    AS title,
  account_id,
  instance_id AS resource_id,
  'fail' AS status
FROM
  aws_ec2_instances
WHERE
  subnet_id
  IN (
      SELECT
        a->>'SubnetId'
      FROM
        aws_ec2_route_tables AS t,
        jsonb_array_elements(t.associations) AS a,
        jsonb_array_elements(t.routes) AS r
      WHERE
        r->>'DestinationCidrBlock' = '0.0.0.0/0'
        OR r->>'DestinationIpv6CidrBlock' = '::/0'
    )
  AND instance_id
    IN (
        SELECT
          instance_id
        FROM
          aws_ec2_instances,
          jsonb_array_elements(security_groups) AS sg
          INNER JOIN view_aws_security_group_egress_rules ON id = sg->>'GroupId'
        WHERE
          ip = '0.0.0.0/0' OR ip6 = '::/0'
      );

All ec2 instances that have unrestricted access to the internet via a security group

-- Find all AWS instances that have a security group that allows unrestricted egress
SELECT
  'All ec2 instances that have unrestricted access to the internet via a security group'
    AS title,
  aws_ec2_instances.account_id,
  instance_id AS resource_id,
  'fail' AS status
FROM
  aws_ec2_instances,
  jsonb_array_elements(security_groups) AS sg
  INNER JOIN view_aws_security_group_egress_rules ON id = sg->>'GroupId'
WHERE
  ip = '0.0.0.0/0' OR ip6 = '::/0';

Find all instances with a public IP address

SELECT
  'Find all instances with a public IP address' AS title,
  account_id,
  arn AS resource_id,
  CASE WHEN public_ip_address IS NOT NULL THEN 'fail' ELSE 'pass' END AS status
FROM
  aws_ec2_instances;

Unused EC2 security group

WITH
  interface_groups
    AS (
      SELECT
        DISTINCT a->>'GroupId' AS group_id
      FROM
        aws_ec2_instances, jsonb_array_elements(security_groups) AS a
    )
SELECT
  'Unused EC2 security group' AS title,
  sg.account_id,
  sg.arn AS resource_id,
  'fail' AS status
FROM
  aws_ec2_security_groups AS sg
  LEFT JOIN interface_groups ON interface_groups.group_id = sg.group_id
WHERE
  interface_groups.group_id IS NULL;

Stopped EC2 instances should be removed after a specified time period

SELECT
  'Stopped EC2 instances should be removed after a specified time period'
    AS title,
  account_id,
  instance_id AS resource_id,
  CASE
  WHEN state->>'Name' = 'stopped'
  AND now() - state_transition_reason_time > '30'::INTERVAL DAY
  THEN 'fail'
  ELSE 'pass'
  END
FROM
  aws_ec2_instances;

Amazon EC2 instances should be managed by AWS Systems Manager

SELECT
  'Amazon EC2 instances should be managed by AWS Systems Manager' AS title,
  aws_ec2_instances.account_id,
  aws_ec2_instances.arn AS resource_id,
  CASE
  WHEN aws_ssm_instances.instance_id IS NULL THEN 'fail'
  ELSE 'pass'
  END
    AS status
FROM
  aws_ec2_instances
  LEFT JOIN aws_ssm_instances ON
      aws_ec2_instances.instance_id = aws_ssm_instances.instance_id;