Control: EC2 AMIs should only be shared with trusted organizations
Description
AWS AMIs can be shared with specific AWS organizations without making the AMI public. This control checks if AMIs are shared with untrusted organizations.
Usage
Run the control in your terminal:
powerpipe control run aws_perimeter.control.ec2_ami_shared_with_trusted_organizations
Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run aws_perimeter.control.ec2_ami_shared_with_trusted_organizations --share
Steampipe Tables
Params
Args | Name | Default | Description | Variable |
---|---|---|---|---|
$1 | trusted_organizations |
| A list of trusted organizations. |
SQL
with all_amis as ( select title, public, launch_permissions, region, _ctx, tags, account_id from aws_ec2_ami order by account_id, region, _ctx, tags, title),ami_data as ( select title, public, string_agg(lp ->> 'Group', ',') as public_access, to_jsonb(string_to_array(string_agg(split_part((lp ->> 'OrganizationArn'), '/', 2), ','), ',')) as shared_organizations, to_jsonb(string_to_array(string_agg(split_part((lp ->> 'OrganizationArn'), '/', 2), ','), ',')) - ($1)::text[] as untrusted_organizations, region, _ctx, account_id from all_amis, jsonb_array_elements(launch_permissions) lp group by title, public,region,_ctx,account_id),evaluated_amis as ( select all_amis.*, public_access, untrusted_organizations, shared_organizations from all_amis left join ami_data on all_amis.account_id = ami_data.account_id and all_amis.region = ami_data.region and all_amis.title = ami_data.title)select title as resource, case when public then 'info' when shared_organizations is null then 'ok' when untrusted_organizations is not null then 'info' else 'ok' end as status, case when public then title || ' is public.' when shared_organizations is null then title || ' is not shared.' when untrusted_organizations is not null then title || ' shared with ' || case when jsonb_array_length(untrusted_organizations) > 2 then concat('untrusted organizations ', untrusted_organizations #>> '{0}', ', ', untrusted_organizations #>> '{1}', ' and ' || (jsonb_array_length(untrusted_organizations) - 2)::text || ' more.' ) when jsonb_array_length(untrusted_organizations) = 2 then concat('untrusted organizations ', untrusted_organizations #>> '{0}', ' and ', untrusted_organizations #>> '{1}', '.') else concat('untrusted organization ', untrusted_organizations #>> '{0}', '.') end else title || ' shared with trusted organization(s).' end as reason , region, account_idfrom evaluated_amis;