SCPで「非暗号化EBS作成」が禁止された環境で、既存EBSを暗号化する2つの方法【CLI手順付き】

記事タイトルとURLをコピーする

垣見です。

AWS OrganizationsのSCP(サービスコントロールポリシー)で「暗号化されていないEBSボリュームの作成」が禁止(Deny)されている環境において、既存の非暗号化EBSボリューム(以下EBS)は一般的な方法では暗号化済みに移行できません

「リストアが必要になったが、SCPに弾かれてできなかった!」のような事態を防ぐために、SCPを付けたままでも非暗号化EBSをEBSに置き換えられる2つの方法について検証を行いました。

なおこの記事は、サーバーワークス Advent Calendar 2025の1日目の企画です。調べたところアドベントとは、クリスマスまでの約4週間を指し、キリストの降臨を待つ期間のことだそうです。(知らなかった) qiita.com

課題とテーマ

非暗号化EBSを暗号化する方法はいくつか存在します。最も一般的な方法は以下かと思います。

  1. 既存非暗号化EBSから、非暗号化EBSスナップショットを作成
  2. その非暗号化スナップショットから暗号化EBSを作成
  3. EC2を停止し、非暗号化EBSをデタッチし、暗号化EBSをアタッチし、EC2を起動する

blog.serverworks.co.jp

暗号化されていないリソースを暗号化する 既存の暗号化されていないボリュームやスナップショットを直接暗号化することはできません

暗号化されていないボリュームを暗号化するには、そのボリュームのスナップショットを作成し、そのスナップショットを使用して新しい暗号化ボリュームを作成します。詳細については、 「スナップショットの作成」 および「ボリュームの作成」を参照してください。 既存および新規の Amazon EBS ボリュームを自動的に暗号化する - AWS 規範ガイダンス

SCPがある場合の課題

運用環境のセキュリティ要件において、SCPで「暗号化されていないEBSの作成(ec2:CreateVolumeec2:RunInstances)」が禁止されているケースがあります。
例えば以下のような形です。

     {
            "Sid": "DenyUnencryptedEBS",
            "Effect": "Deny",
            "Action": [
                "ec2:RunInstances",
                "ec2:CreateVolume"
            ],
            "Condition": {
                "StringEquals": {
                    "ec2:Encrypted": "false"
                }
            },
            "Resource": "*"
        },

このポリシーは、暗号化されていないEBSボリュームの作成、および暗号化されていないボリュームを持つEC2インスタンスの起動を拒否します。

これにより、組織内のすべての新規EBSボリュームで暗号化が強制されるのですが……「このSCPを付けた後、既存の非暗号化EBSをどう暗号化状態に持っていくか?」という問題があります。

SCPで新規の非暗号化EBSが生まれないようにした後、既存のEBSを暗号化して、組織全体の統制を高めていく、という組織的な対応の流れはよくある事でしょう。

しかし、このポリシーが入っていると、上記ブログでご紹介した手順では対応ができません。

【参考】SCP(ec2:CreateVolumeのDeny)のせいで失敗するパターン

上記ブログの手順に添って実施したところ、3ステップの2番目のフェーズでwith an explicit deny in a service control policyにより拒否エラーが起きてしまいました。

  1. 既存非暗号化EBSから、非暗号化EBSスナップショットを作成
  2. その非暗号化スナップショットから暗号化EBSを作成→【⚠️ ここで ec2:CreateVolume のDenyポリシーにより失敗します。
  3. EC2を停止し、非暗号化EBSをデタッチし、暗号化EBSをアタッチし、EC2を起動する

イメージ

* なお、後述の「EBSデフォルト暗号化設定」をしていても同様のエラーで失敗しました。

非暗号化スナップショットからボリュームの作成段階でエラー

You are not authorized to perform this operation. User: arn:aws:sts::111111111111:assumed-role/OrganizationAccountAccessRole/administrator is not authorized to perform: ec2:CreateVolume on resource: arn:aws:ec2:us-east-1::snapshot/snap-aaaaaaaaaaaa with an explicit deny in a service control policy. Encoded authorization failure message: uiacC-IfpzBzD8S-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

テーマ

このように手順が確立していない状況では、組織ポリシーに準拠できない他、緊急時のバックアップからのリストアも出来ず、可用性が下がってしまいます。

そこでいくつかの手順を検証した結果、SCPの設定を変更することなく、2つのやり方で対応可能であることがわかりました。

解決策の概要

結論として、「非暗号化スナップショットが存在すれば、暗号化オプションを付与してコピーすることで、リストアおよび暗号化移行が可能」です。

今回は、SCPの変更なしで実施できる2つの手順をご紹介します。
なお、どちらの方法もEC2インスタンスの停止、または再起動を伴いますのでご留意ください。

特徴 パターンA:スナップショットコピー方式 パターンB:ルートボリューム置換方式
概要 スナップショットを暗号化コピーして差し替える 「ルートボリュームの置換」機能を使う
メリット ・一般的な手法でノウハウが多い
・新規EC2への移行や障害復旧(リストア)時に使いやすい
・KMSキーを個別に指定しやすい
・手順がシンプルで素早い
・デフォルト暗号化設定を併用するため、以降の権限エラーが減る
デメリット ・コピーに時間がかかる(容量依存)
・EC2の停止・デタッチ・アタッチ等の手順が多い
・削除対象のリソースが増える
・「常に新しいEBSを暗号化」設定がアカウント・リージョン単位で必要
・特定のキーを使いたい場合は都度設定が必要
・ルートボリュームとして使われるEBSにのみ有効
ダウンタイム 停止+起動が必要 自動的に再起動が発生

SCP環境で可能なふたつの手法

パターンA:スナップショットコピー方式

冒頭に紹介した手順との違いは非暗号化スナップショットから直接暗号化EBSを作るのではなく暗号化スナップショットをコピーによって作る部分で、それによってSCPの制限を回避します。

手順の流れ

  1. 既存非暗号化EBSの非暗号化スナップショット作成
  2. 非暗号化スナップショットを暗号化オプション付きでコピー、暗号化スナップショットを作る
  3. 暗号化スナップショットから暗号化EBSボリュームを作成
  4. EC2を停止し、EBSボリュームを差し替える。終わったらEC2を起動する。

パターンA

コンソールでの手順

こちらを参考にしてください: blog.serverworks.co.jp

CLI手順

※コンソール手順のCLI版です。

1. 既存非暗号化EBSから、スナップショット作成

# ボリュームIDを指定してスナップショット作成
aws ec2 create-snapshot \
    --volume-id vol-xxxxxxxxxxxxxxxxx \
    --description "Backup before encrypt vol-xxxxxxxxxxxxxxxxx"

# 実行後、出力される SnapshotId を控えてください

2. スナップショットを暗号化コピー

# --source-snapshot-id は手順1で作ったIDを指定
# --encrypted オプションで暗号化を明示します
aws ec2 copy-snapshot \
    --source-snapshot-id snap-0123456789abcdef0 \
    --source-region ap-northeast-1 \
    --description "Encrypted copy of snap-0123456789abcdef0" \
    --encrypted
    # 特定のCMKを使う場合は --kms-key-id でARNを指定してください

※データ量に応じて数分〜数十分かかります。

3. 暗号化スナップショットからEBSボリュームを作成

# --snapshot-id は手順2で作った暗号化スナップショットID
# ※重要:--availability-zone はインスタンスと同じAZを指定してください
aws ec2 create-volume \
    --snapshot-id snap-abcdef0123456789 \
    --availability-zone ap-northeast-1a \
    --volume-type gp3 \
    --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=Encrypted-Volume-For-MyInstance}]'

4. ボリュームの差し替え(停止・デタッチ・アタッチ・起動)

# 1. EC2停止
aws ec2 stop-instances --instance-ids i-xxxxxxxxxxxxxxxxx
aws ec2 wait instance-stopped --instance-ids i-xxxxxxxxxxxxxxxxx
echo "インスタンスが停止しました"

# 2. 非暗号化EBSをデタッチ
aws ec2 detach-volume --volume-id vol-xxxxxxxxxxxxxxxxx
aws ec2 wait volume-detached --volume-ids vol-xxxxxxxxxxxxxxxxx
echo "旧ボリュームのデタッチ完了"

# 3. 暗号化EBSをアタッチ
# --device は元のデバイス名(例: /dev/sdf や /dev/xvda)に合わせてください
aws ec2 attach-volume \
    --volume-id vol-0abcdef123456789ab \
    --instance-id i-xxxxxxxxxxxxxxxxx \
    --device /dev/sdf
aws ec2 wait volume-in-use --volume-ids vol-0abcdef123456789ab
echo "暗号化ボリュームのアタッチ完了"

# 4. EC2起動
aws ec2 start-instances --instance-ids i-xxxxxxxxxxxxxxxxx
aws ec2 wait instance-running --instance-ids i-xxxxxxxxxxxxxxxxx
echo "EC2起動完了"

パターンB:ルートボリューム置換機能を使う方式

こちらのre:Postを参考にしました

repost.aws

「ルートボリュームの置換 (Replace Root Volume)」機能を使うことで、より少ないステップで置換を可能にしています。
アカウントレベルでデフォルト暗号化を有効すると、置換時に勝手に暗号化され、またルートボリューム置換機能を使うことでSCPで設定したAPI仕様を回避できるようです。

検証時のCloudTrailログ。UpdateInstanceInformationが沢山あり、CreateVolumeはありません。

手順の流れ

  1. アカウント・リージョン設定で「EBS暗号化をデフォルトで有効」にする
  2. 既存EBSの非暗号化スナップショットを作成
  3. 「ルートボリュームを置き換える」タスクを実行(ここでEC2が自動再起動し、新規暗号化EBSがアタッチされます)

パターンB

コンソールでの手順

1. アカウント・リージョン設定で「EBS暗号化をデフォルトで有効」にする

EC2コンソール > Dashboard > Data protection and security

EBS暗号化 > 編集

有効化して更新

なお、画面に

※上記の設定はアジアパシフィック(東京)リージョンにのみ適用されます。別のリージョンを選択すると、そのリージョンの設定を変更できます。アカウントレベルの暗号化を有効にした後でなければ、EBS暗号化をサポートするインスタンスタイプのみ起動できます。

とありますが、現在Amazon EBS 暗号化は、 現世代および 前世代のすべてのインスタンスタイプで利用できるようです。

docs.aws.amazon.com

設定完了

2. 既存EBSの非暗号化スナップショットを作成

EC2コンソール > スナップショット > スナップショットの作成

非暗号化スナップショットができる

3. 「ルートボリュームを置き換える」タスクを実行(自動再起動)

EC2コンソール > インスタンス選択 > アクション > モニタリングとトラブルシューティング > ルートボリュームを置き換える

「暗号化していない」スナップショットを選択して置換

結果、「最近のルートボリュームの置き換えタスク」項目に新規タスクが生まれ、1分ほどで完了し、EBSボリュームが暗号化済みになっています。

またこの時EBSボリュームを見ると、最初の「未暗号化ボリューム」がデタッチされた状態になり、新規の暗号化済みボリュームがアタッチされていることがわかります。

4. (必要があれば)問題がないことを確認してから、古い非暗号化EBSボリュームと非暗号化EBSスナップショットを削除してください

CLI手順

1. EBS暗号化のデフォルト有効化

# デフォルト暗号化を有効化
aws ec2 enable-ebs-encryption-by-default

# 設定確認
aws ec2 get-ebs-encryption-by-default
# 結果が "EbsEncryptionByDefault": true となればOK

2. スナップショット作成

# ルートボリュームIDを確認してスナップショットを作成
aws ec2 create-snapshot \
    --volume-id vol-yyyyyyyyyyyyyyyyy \
    --description "Root volume snapshot for instance i-xxxxxxxxxxxxxxxxx before encryption"

3. ルートボリューム置換タスクの実行 この操作を行うと、指定したスナップショットを使ってボリュームが復元・置換され、インスタンスが自動的に再起動します。手順1の設定により、復元されるボリュームは自動的に暗号化されます。

# --snapshot-id: 手順2で作成した非暗号化スナップショットID
aws ec2 create-replace-root-volume-task \
    --instance-id i-xxxxxxxxxxxxxxxxx \
    --snapshot-id snap-zzzzzzzzzzzzzzzzz \
    --tag-specifications 'ResourceType=replace-root-volume-task,Tags=[{Key=Name,Value=Encrypt-Root-Task}]'

タスク完了後、マネジメントコンソール等でボリュームが暗号化されていることを確認してください。

まとめ

SCPでセキュリティを厳格に管理している環境では、運用の柔軟性が下がる場面がありますが、AWSの機能を組み合わせることで安全に移行が可能です。

  • 確実性・個別指定重視なら パターンA
  • スピード・手軽さ重視なら パターンB

環境に合わせて適切な方法を選択してください。作業後、不要になった旧ボリュームやスナップショットの削除についてもお忘れなく実行していただければと思います。

ブログが皆様のお役に立てれば幸いです。

垣見(かきみ)(執筆記事の一覧)

2023年新卒入社 エンタープライズクラウド部所属 2025 Japan AWS Jr.Champions

図解するのが好き。「サバワク」のアイキャッチ作成も担当しています