turbot/aws_perimeter

Control: DLM policies should only share EBS snapshot copies with trusted accounts

Description

Automating cross-account snapshot copies enables you to copy your EBS snapshots to specific regions in an isolated account and encrypt those snapshots with an encryption key. This enables you to protect yourself against data loss in the event of your account being compromised. This control checks if EBS snapshots are being copied to untrusted accounts.

Usage

Run the control in your terminal:

powerpipe control run aws_perimeter.control.dlm_ebs_snapshot_policy_shared_with_trusted_accounts

Snapshot and share results via Turbot Pipes:

powerpipe login
powerpipe control run aws_perimeter.control.dlm_ebs_snapshot_policy_shared_with_trusted_accounts --share

Steampipe Tables

Params

ArgsNameDefaultDescriptionVariable
$1trusted_accounts
["123456781234","123456781200"]
A list of trusted accounts.

SQL

with dlm_policy_shared_snapshot_copies as (
select
policy_id,
policy_type,
state,
-- A DLM policy can have at most 4 schedules, we need to verify each schedule if snapshots, through it will be shared to external accounts
(policy_details #> '{Schedules,0,ShareRules,0,TargetAccounts}')::jsonb - ($1)::text[] as schedule_0_untrusted_accountss,
(policy_details #> '{Schedules,1,ShareRules,0,TargetAccounts}')::jsonb - ($1)::text[] as schedule_1_untrusted_accountss,
(policy_details #> '{Schedules,2,ShareRules,0,TargetAccounts}')::jsonb - ($1)::text[] as schedule_2_untrusted_accountss,
(policy_details #> '{Schedules,3,ShareRules,0,TargetAccounts}')::jsonb - ($1)::text[] as schedule_3_untrusted_accountss,
account_id,
_ctx,
region,
tags
from
aws_dlm_lifecycle_policy
where
policy_type = 'EBS_SNAPSHOT_MANAGEMENT'
)
select
policy_id as resource,
case
when state = 'DISABLED' then 'skip'
when jsonb_array_length(schedule_0_untrusted_accountss) > 0
or jsonb_array_length(schedule_1_untrusted_accountss) > 0
or jsonb_array_length(schedule_2_untrusted_accountss) > 0
or jsonb_array_length(schedule_3_untrusted_accountss) > 0 then 'info'
else 'ok'
end as status,
case
when state = 'DISABLED' then policy_id || ' policy disabled.'
when jsonb_array_length(schedule_0_untrusted_accountss) > 0 then
policy_id || ' creates EBS snapshots and shares with ' ||
case
when jsonb_array_length(schedule_0_untrusted_accountss) > 2 then
concat(schedule_0_untrusted_accountss #>> '{0}', ', ', schedule_0_untrusted_accountss #>> '{1}', ' and ', (jsonb_array_length(schedule_0_untrusted_accountss) - 2)::text, ' more untrusted account(s).')
when jsonb_array_length(schedule_0_untrusted_accountss) = 2 then
concat(schedule_0_untrusted_accountss #>> '{0}', ', ', schedule_0_untrusted_accountss #>> '{1}', ' untrusted accounts.')
else concat(schedule_0_untrusted_accountss #>> '{0}', ' untrusted account.')
end
when jsonb_array_length(schedule_1_untrusted_accountss) > 0 then
policy_id || ' creates EBS snapshots and shares with ' ||
case
when jsonb_array_length(schedule_1_untrusted_accountss) > 2 then
concat('untrusted accounts ', schedule_1_untrusted_accountss #>> '{0}', ', ', schedule_1_untrusted_accountss #>> '{1}', ' and ', (jsonb_array_length(schedule_1_untrusted_accountss) - 2)::text, ' more.')
when jsonb_array_length(schedule_1_untrusted_accountss) = 2 then
concat('untrusted accounts ', schedule_1_untrusted_accountss #>> '{0}', ' and ', schedule_1_untrusted_accountss #>> '{1}', '.')
else concat('untrusted account ', schedule_1_untrusted_accountss #>> '{0}', '.')
end
when jsonb_array_length(schedule_2_untrusted_accountss) > 0 then
policy_id || ' creates EBS snapshots and shares with ' ||
case
when jsonb_array_length(schedule_2_untrusted_accountss) > 2 then
concat('untrusted accounts ', schedule_2_untrusted_accountss #>> '{0}', ', ', schedule_2_untrusted_accountss #>> '{1}', ' and ', (jsonb_array_length(schedule_2_untrusted_accountss) - 2)::text, ' more.')
when jsonb_array_length(schedule_2_untrusted_accountss) = 2 then
concat('untrusted accounts ', schedule_2_untrusted_accountss #>> '{0}', ' and ', schedule_2_untrusted_accountss #>> '{1}', '.')
else concat('untrusted account ', schedule_2_untrusted_accountss #>> '{0}', '.')
end
when jsonb_array_length(schedule_3_untrusted_accountss) > 0 then
policy_id || ' creates EBS snapshots and shares with ' ||
case
when jsonb_array_length(schedule_3_untrusted_accountss) > 2 then
concat('untrusted accounts ', schedule_3_untrusted_accountss #>> '{0}', ', ', schedule_3_untrusted_accountss #>> '{1}', ' and ', (jsonb_array_length(schedule_3_untrusted_accountss) - 2)::text, ' more.')
when jsonb_array_length(schedule_3_untrusted_accountss) = 2 then
concat('untrusted accounts ', schedule_3_untrusted_accountss #>> '{0}', ' and ', schedule_3_untrusted_accountss #>> '{1}', '.')
else concat('untrusted account ', schedule_3_untrusted_accountss #>> '{0}', '.')
end
else policy_id || ' does not create any EBS snapshot shared with untrusted account(s).'
end as reason
, region, account_id
from
dlm_policy_shared_snapshot_copies;

Tags