Control: EC2 AMIs should only be shared with trusted OUs
Description
AWS AMIs can be shared with specific AWS organizations units (OUs) without making the AMI public. This control checks if AMIs are shared with untrusted OUs.
Usage
Run the control in your terminal:
powerpipe control run aws_perimeter.control.ec2_ami_shared_with_trusted_organization_unitsSnapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run aws_perimeter.control.ec2_ami_shared_with_trusted_organization_units --shareSteampipe Tables
SQL
with all_amis as (  select    title,    public,    launch_permissions,    region,    _ctx,    tags,    account_id  from    aws_ec2_ami  order by    account_id,    _ctx,    region,    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 ->> 'OrganizationalUnitArn'), '/', 3), ','), ',')) as shared_organization_units,    to_jsonb(string_to_array(string_agg(split_part((lp ->> 'OrganizationalUnitArn'), '/', 3), ','), ',')) - ($1)::text[] as untrusted_organization_units,    region,    _ctx,    tags,    account_id  from    all_amis,    jsonb_array_elements(launch_permissions) lp  group by    title, public,region,_ctx,account_id,tags),evaluated_amis as (  select    all_amis.*,    public_access,    shared_organization_units,    untrusted_organization_units  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_organization_units is null then 'ok'    when untrusted_organization_units is not null then 'info'    else 'ok'  end as status,  case    when public then title || ' is public.'    when shared_organization_units is null then title || ' is not shared.'    when shared_organization_units is not null then title || ' shared with ' ||      case        when jsonb_array_length(untrusted_organization_units) > 2        then concat('untrusted OUs ', untrusted_organization_units #>> '{0}', ', ', untrusted_organization_units #>> '{1}', ' and ' || (jsonb_array_length(untrusted_organization_units) - 2)::text || ' more.' )        when jsonb_array_length(untrusted_organization_units) = 2        then concat('untrusted OUs ', untrusted_organization_units #>> '{0}', ' and ', untrusted_organization_units #>> '{1}', '.')        else concat('untrusted OU ', untrusted_organization_units #>> '{0}', '.')      end    else title || ' shared with trusted OU(s).'  end as reason    , region, account_idfrom  evaluated_amis;
Params
| Args | Name | Default | Description | Variable | 
|---|---|---|---|---|
| $1 | trusted_organization_units |  | A list of trusted organization units. |