Control: 15 Redshift security groups should allow ingress on the cluster port only from restricted origins
Description
This control checks whether a security group associated with an Amazon Redshift cluster has ingress rules that permit access to the cluster port from the internet (0.0.0.0/0 or ::/0). The control fails if the security group ingress rules permit access to the cluster port from the internet.
Permitting unrestricted inbound access to the Redshift cluster port (IP address with a /0 suffix) can result in unauthorized access or security incidents. We recommend applying the principal of least privilege access when creating security groups and configuring inbound rules.
Remediation
To restrict ingress on the Redshift cluster port to restricted origins, see Work with security group rules in the Amazon VPC User Guide. Update rules where the port range matches the Redshift cluster port and the IP port range is 0.0.0.0/0.
Usage
Run the control in your terminal:
powerpipe control run aws_compliance.control.foundational_security_redshift_15Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run aws_compliance.control.foundational_security_redshift_15 --shareSQL
This control uses a named query:
with redshift_security_groups as (  select    arn,    sg ->> 'VpcSecurityGroupId' as security_group_id,    region,    account_id,    coalesce((endpoint ->> 'Port')::int, 5439) as redshift_port  from    aws_redshift_cluster,    jsonb_array_elements(vpc_security_groups) as sg), ingress_redshift_port as (  select    distinct rsg.arn as redshift_arn,    group_id as sg_id,    redshift_port  from    redshift_security_groups as rsg    left join aws_vpc_security_group_rule as sgr on sgr.group_id = rsg.security_group_id  where    type = 'ingress'    and      (cidr_ipv4 = '0.0.0.0/0'      or cidr_ipv6 = '::/0')    and    (      ( ip_protocol = '-1'      and from_port is null      )      or (        from_port <= redshift_port        and to_port >= redshift_port      )    )  group by    group_id,    rsg.arn,    rsg.redshift_port), redshift_sg_agg as (  select    redshift_arn,    redshift_port,    array_agg(distinct sg_id) as offending_sgs,    count(distinct sg_id)  as offending_sg_count  from ingress_redshift_port  group by redshift_arn, redshift_port)select  arn as resource,  case    when offending_sg_count > 0  then 'alarm'    else 'ok'  end as status,  case    when offending_sg_count > 0  then title || ' contains ' || offending_sg_count || ' security groups ' || array_to_string(coalesce(offending_sgs, array[]::text[]), ', ') || ' with ingress rule(s) from 0.0.0.0/0 or ::/0 to Redshift port ' ||  p.redshift_port || '.'    else title || ' has no security groups with ingress from 0.0.0.0/0 or ::/0 to Redshift port.'  end as reason    , region, account_idfrom  aws_redshift_cluster as r  left join redshift_sg_agg as p on p.redshift_arn = r.arn;