turbot/steampipe-mod-aws-compliance

Control: 2 OpenSearch domains should not be publicly accessible

Description

This control checks whether OpenSearch domains are in a VPC. It does not evaluate the VPC subnet routing configuration to determine public access.

You should ensure that OpenSearch domains are not attached to public subnets. See Resource-based policies in the Amazon OpenSearch Service Developer Guide. You should also ensure that your VPC is configured according to the recommended best practices. See Security best practices for your VPC in the Amazon VPC User Guide.

OpenSearch domains deployed within a VPC can communicate with VPC resources over the private AWS network, without the need to traverse the public internet. This configuration increases the security posture by limiting access to the data in transit. VPCs provide a number of network controls to secure access to OpenSearch domains, including network ACL and security groups. Security Hub recommends that you migrate public OpenSearch domains to VPCs to take advantage of these controls.

Remediation

If you create a domain with a public endpoint, you cannot later place it within a VPC. Instead, you must create a new domain and migrate your data. The reverse is also true. If you create a domain within a VPC, it cannot have a public endpoint.

Instead, you must either create another domain or disable this control.

See Launching your Amazon OpenSearch Service domains within a VPC in the Amazon OpenSearch Service Developer Guide.

Usage

Run the control in your terminal:

powerpipe control run aws_compliance.control.foundational_security_opensearch_2

Snapshot and share results via Turbot Pipes:

powerpipe login
powerpipe control run aws_compliance.control.foundational_security_opensearch_2 --share

SQL

This control uses a named query:

with public_subnets as (
select
distinct a -> 'SubnetId' as SubnetId
from
aws_vpc_route_table as t,
jsonb_array_elements(associations) as a,
jsonb_array_elements(routes) as r
where
r ->> 'DestinationCidrBlock' = '0.0.0.0/0'
and r ->> 'GatewayId' like 'igw-%'
), opensearch_domain_with_public_subnet as (
select
arn
from
aws_opensearch_domain ,
jsonb_array_elements(vpc_options -> 'SubnetIds') as s
where
s in (select SubnetId from public_subnets)
)
select
d.arn as resource,
case
when d.vpc_options ->> 'VPCId' is null then 'alarm'
when d.vpc_options ->> 'VPCId' is not null and p.arn is not null then 'alarm'
else 'ok'
end status,
case
when vpc_options ->> 'VPCId' is null then title || ' not in VPC.'
when d.vpc_options ->> 'VPCId' is not null and p.arn is not null then title || ' attached to public subnet.'
else title || ' in VPC ' || (vpc_options ->> 'VPCId') || '.'
end reason
, d.region, d.account_id
from
aws_opensearch_domain as d
left join opensearch_domain_with_public_subnet as p on d.arn = p.arn;

Tags