Linux VM 用の Azure Disk Encryption のサンプル スクリプト
注意事項
この記事では、サービス終了 (EOL) 状態の Linux ディストリビューションである CentOS について説明します。 適宜、使用と計画を検討してください。 詳細については、「CentOS のサポート終了に関するガイダンス」を参照してください。
適用対象: ✔️ Linux VM ✔️ フレキシブルなスケール セット
この記事では、事前に暗号化された VHD の準備およびその他のタスクのためのサンプル スクリプトを提供します。
Note
すべてのスクリプトでは、特に明記されている場合を除き、非 AAD の最新バージョンの ADE が参照されます。
Azure Disk Encryption 用の PowerShell スクリプトのサンプル
サブスクリプション内の暗号化された VM をすべて一覧表示する
この PowerShell スクリプトを使用して、サブスクリプションに存在するすべてのリソース グループの ADE で暗号化されたすべての VM と拡張バージョンを見つけることができます。
また、これらのコマンドレットを使用すると、ADE で暗号化されたすべての VM が表示されます (拡張機能のバージョンは表示されません)。
$osVolEncrypted = {(Get-AzVMDiskEncryptionStatus -ResourceGroupName $_.ResourceGroupName -VMName $_.Name).OsVolumeEncrypted} $dataVolEncrypted= {(Get-AzVMDiskEncryptionStatus -ResourceGroupName $_.ResourceGroupName -VMName $_.Name).DataVolumesEncrypted} Get-AzVm | Format-Table @{Label="MachineName"; Expression={$_.Name}}, @{Label="OsVolumeEncrypted"; Expression=$osVolEncrypted}, @{Label="DataVolumesEncrypted"; Expression=$dataVolEncrypted}
サブスクリプション内のすべての暗号化された VMSS インスタンスを一覧表示する
この PowerShell スクリプトを使用して、サブスクリプションに存在するすべてのリソース グループの ADE で暗号化されたすべての VMSS インスタンスと拡張バージョンを見つけることができます。
キー コンテナー内の VM を暗号化するために使用されるディスクの暗号化シークレットをすべて一覧表示する
Get-AzKeyVaultSecret -VaultName $KeyVaultName | where {$_.Tags.ContainsKey('DiskEncryptionKeyFileName')} | format-table @{Label="MachineName"; Expression={$_.Tags['MachineName']}}, @{Label="VolumeLetter"; Expression={$_.Tags['VolumeLetter']}}, @{Label="EncryptionKeyURL"; Expression={$_.Id}}
Azure Disk Encryption の前提条件となる PowerShell スクリプトの使用
Azure Disk Encryption の前提条件に既に精通している場合は、Azure Disk Encryption の前提条件となる PowerShell スクリプトを使用できます。 この PowerShell スクリプトの使用例については、VM の暗号化のクイック スタートに関するページを参照してください。 既存のリソース グループ内の既存の VM のすべてのディスクを暗号化するために、スクリプトの 211 行目から始まるセクションのコメントを削除することができます。
次の表は、PowerShell スクリプトでどのパラメーターを使用することができるかを示しています。
パラメーター | 説明 | 必須 |
---|---|---|
$resourceGroupName | KeyVault が属するリソース グループの名前。 該当するリソース グループがない場合は、この名前の付いた新しいリソース グループが作成されます。 | True |
$keyVaultName | 暗号化キーが配置される KeyVault の名前。 該当するコンテナーが存在しない場合は、この名前の付いた新しいコンテナーが作成されます。 | True |
$location | KeyVault の場所。 KeyVault と暗号化する VM が同じ場所にあることを確認します。 場所の一覧を取得するには、Get-AzLocation を使用します。 |
True |
$subscriptionId | 使用する Azure サブスクリプションの識別子。 サブスクリプション ID を取得するには、Get-AzSubscription を使用します。 |
True |
$aadAppName | シークレットを KeyVault に書き込むために使用される Microsoft Entra アプリケーションの名前。 該当するアプリケーションがない場合は、この名前の付いた新しいアプリケーションが作成されます。 このアプリが既に存在する場合は、スクリプトに aadClientSecret パラメーターを渡します。 | False |
$aadClientSecret | 以前に作成された Microsoft Entra アプリケーションのクライアント シークレット。 | False |
$keyEncryptionKeyName | KeyVault のオプションのキー暗号化キーの名前。 該当するキーが存在しない場合は、この名前の付いた新しいキーが作成されます。 | False |
Microsoft Entra アプリを使用せずに VM を暗号化または暗号化解除する
- 既存または実行中の Linux VM でディスク暗号化を有効にする
- 実行中の Linux VM で暗号化を無効にする
- Linux VM 用のデータ ボリュームでのみ、暗号化を無効にすることができます。
Microsoft Entra アプリを使用して VM を暗号化または暗号化解除する (以前のリリース)
- 既存または実行中の Linux VM でディスク暗号化を有効にする
- 実行中の Linux VM で暗号化を無効にする
- Linux VM 用のデータ ボリュームでのみ、暗号化を無効にすることができます。
- 事前に暗号化された VHD/ストレージ BLOB から、新しい暗号化されたマネージド ディスクを作成する
- 事前に暗号化された VHD とその対応する暗号化設定がある場合、新しい暗号化されたマネージド ディスクが作成されます
実行中の Linux VM での OS ドライブの暗号化
OS ディスクを暗号化するための前提条件
- VM では、Azure Disk Encryption でサポートされているオペレーティング システムに関する記事で示されている OS ディスクの暗号化と互換性のあるディストリビューションが使用されている必要があります
- VM は、Azure Resource Manager で Marketplace イメージから作成する必要があります。
- 少なくとも 4 GB の RAM を持つAzure VM (推奨するサイズは 7 GB)。 詳細については、「メモリ要件 」を参照してください。
- (RHEL と CentOS については) SELinux を無効にします。 SELinux を無効にする方法については、 VM で「SELinux User's and Administrator's Guide (SELinux ユーザーおよび管理者用ガイド)」の「4.4.2. Disabling SELinux (SELinux の無効化)」をご覧ください。
- SELinux を無効にしたら、少なくとも 1 回、VM を再起動してください。
手順
上記のディストリビューションのいずれかを使用して、VM を作成します。
ニーズに応じて VM を構成します。 すべてのドライブ (OS およびデータ) を暗号化する場合は、/etc/fstab にデータ ドライブを指定してマウントできるようにする必要があります。
注意
/etc/fstab にデータ ドライブを指定するには、ブロック デバイス名 (たとえば、/dev/sdb1 など) ではなく、UUID=... を使用してください。 暗号化中には、ドライブの順序が VM 上で変更されます。 VM がブロック デバイスの特定の順序に依存している場合、暗号化後のマウントは失敗します。
SSH セッションからサインアウトします。
OS を暗号化するには、暗号化を有効にするときに、volumeType として All または OS を指定します。
注意
systemd
サービスとして実行されているすべてのユーザー スペースのプロセスは、SIGKILL
によって強制終了されます。 VM を再起動してください。 実行中の VM での OS ディスクの暗号化を有効にする場合は、VM のダウンタイムを計画してください。次のセクションの指示に従って、暗号化の進行状況を定期的に監視します。
Get-AzVmDiskEncryptionStatus で "VMRestartPending" が表示されたら、VM にサインインするか、ポータル、PowerShell、または CLI を使用して VM を再起動します。
C:\> Get-AzVmDiskEncryptionStatus -ResourceGroupName $ResourceGroupName -VMName $VMName -ExtensionName $ExtensionName
OsVolumeEncrypted : VMRestartPending DataVolumesEncrypted : NotMounted OsVolumeEncryptionSettings : Microsoft.Azure.Management.Compute.Models.DiskEncryptionSettings ProgressMessage : OS disk successfully encrypted, reboot the VM
再起動する前に、VM のブート診断を保存することをお勧めします。
OS 暗号化の進行状況の監視
OS 暗号化の進行状況を監視するには、次の 3 つの方法があります。
Get-AzVmDiskEncryptionStatus
コマンドレットを使用して、ProgressMessage フィールドを確認する。Get-AzVMDiskEncryptionStatus -ResourceGroupName $_.ResourceGroupName -VMName $_.Name
OsVolumeEncrypted : EncryptionInProgress DataVolumesEncrypted : NotMounted OsVolumeEncryptionSettings : Microsoft.Azure.Management.Compute.Models.DiskEncryptionSettings ProgressMessage : OS disk encryption started
VM が "OS disk encryption started (OS ディスクの暗号化が開始されました)" 状態に達するまで、Premium ストレージを使用する VM でおよそ 40 分から 50 分かかります。
WALinuxAgent での問題 #388 により、一部のディストリビューションでは、
OsVolumeEncrypted
とDataVolumesEncrypted
はUnknown
と表示されます。 WALinuxAgent バージョン 2.1.5 以降では、この問題は自動的に修正されます。 出力にUnknown
が含まれている場合は、Azure リソース エクスプローラーを使用して、ディスクの暗号化状態を確認できます。Azure リソース エクスプローラーに移動し、左側の選択パネルで次の階層を展開します。
|-- subscriptions |-- [Your subscription] |-- resourceGroups |-- [Your resource group] |-- providers |-- Microsoft.Compute |-- virtualMachines |-- [Your virtual machine] |-- InstanceView
InstanceView で、画面を下にスクロールして、ドライブの暗号化の状態を表示します。
ブート診断を調べる。 ADE 拡張機能のメッセージには、頭に
[AzureDiskEncryption]
が付きます。SSH を使用して VM にサインインし、拡張機能ログを取得する。
/var/log/azure/Microsoft.Azure.Security.AzureDiskEncryptionForLinux
OS 暗号化の進行中は、VM にサインインしないでください。 ログのコピーは、他の 2 つの方法が失敗した場合にのみ行ってください。
事前に暗号化された Linux VHD を準備する
事前に暗号化された VHD の準備は、ディストリビューションによって異なる場合があります。 Ubuntu、openSUSE、および CentOS 7 の準備に関する例を利用できます。
次の手順に従って、ディストリビューションのインストール時に暗号化を構成します。
ディスクをパーティション分割するときに [Configure encrypted volumes] を選択します。
独立したブート ドライブを作成します。このドライブは暗号化しません。 ルート ドライブを暗号化します。
パスフレーズを指定します。 これは、キー コンテナーにアップロードしたパスフレーズです。
パーティション分割を終了します。
VM を起動し、パスフレーズの入力を求められたら、手順 3 で指定したパスフレーズを入力します。
こちらの手順に従って、VM を Azure にアップロードするための準備をします。 最後の手順 (VM のプロビジョニング解除) はまだ実行しないでください。
次の手順を行って、Azure で使用する暗号化を構成します。
以下のスクリプトの内容で、
/usr/local/sbin/azure_crypt_key.sh
にファイルを作成します。 KeyFileName に注意してください。これは、Azure によって使用されるパスフレーズ ファイル名です。#!/bin/sh MountPoint=/tmp-keydisk-mount KeyFileName=LinuxPassPhraseFileName echo "Trying to get the key from disks ..." >&2 mkdir -p $MountPoint modprobe vfat >/dev/null 2>&1 modprobe ntfs >/dev/null 2>&1 sleep 2 OPENED=0 cd /sys/block for DEV in sd*; do echo "> Trying device: $DEV ..." >&2 mount -t vfat -r /dev/${DEV}1 $MountPoint >/dev/null|| mount -t ntfs -r /dev/${DEV}1 $MountPoint >/dev/null if [ -f $MountPoint/$KeyFileName ]; then cat $MountPoint/$KeyFileName umount $MountPoint 2>/dev/null OPENED=1 break fi umount $MountPoint 2>/dev/null done if [ $OPENED -eq 0 ]; then echo "FAILED to find suitable passphrase file ..." >&2 echo -n "Try to enter your password: " >&2 read -s -r A </dev/console echo -n "$A" else echo "Success loading keyfile!" >&2 fi
/etc/crypttab の crypt 構成を変更します。 次のようになります。
xxx_crypt uuid=xxxxxxxxxxxxxxxxxxxxx none luks,discard,keyscript=/usr/local/sbin/azure_crypt_key.sh
実行可能アクセス許可をスクリプトに追加します。
sudo chmod +x /usr/local/sbin/azure_crypt_key.sh
/etc/initramfs-tools/modules
を編集し、次の行を追加します。vfat ntfs nls_cp437 nls_utf8 nls_iso8859-1
update-initramfs -u -k all
を実行して initramfs を更新し、keyscript
を有効にします。これで、VM をプロビジョニング解除できるようになります。
次の手順に進み、Azure にご利用の VHD をアップロードします。
暗号化された VHD を Azure ストレージ アカウントにアップロードする
DM-Crypt 暗号化を有効にした後、ローカル環境で暗号化された VHD をストレージ アカウントにアップロードする必要があります。
Add-AzVhd [-Destination] <Uri> [-LocalFilePath] <FileInfo> [[-NumberOfUploaderThreads] <Int32> ] [[-BaseImageUriToPatch] <Uri> ] [[-OverWrite]] [ <CommonParameters>]
事前に暗号化された VM 用のシークレットをご自分のキー コンテナーにアップロードする
Microsoft Entra アプリ (以前のリリース) を使って暗号化するときは、前に取得したディスク暗号化シークレットを、キー コンテナーにシークレットとしてアップロードする必要があります。 キー コンテナーでは、Microsoft Entra クライアントに対してディスク暗号化とアクセス許可が有効になっている必要があります。
$AadClientId = "My-AAD-Client-Id"
$AadClientSecret = "My-AAD-Client-Secret"
$key vault = New-AzKeyVault -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -Location $Location
Set-AzKeyVaultAccessPolicy -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -ServicePrincipalName $AadClientId -PermissionsToKeys all -PermissionsToSecrets all
Set-AzKeyVaultAccessPolicy -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -EnabledForDiskEncryption
KEK で暗号化されないディスク暗号化シークレット
キー コンテナーでシークレットを設定するには、Set-AzKeyVaultSecret を使用します。 パスフレーズが base64 文字列としてエンコードされた後、キー コンテナーにアップロードされます。 また、Key Vault でシークレットを作成する際には、以下のタグが設定されます。
# This is the passphrase that was provided for encryption during the distribution installation
$passphrase = "contoso-password"
$tags = @{"DiskEncryptionKeyEncryptionAlgorithm" = "RSA-OAEP"; "DiskEncryptionKeyFileName" = "LinuxPassPhraseFileName"}
$secretName = [guid]::NewGuid().ToString()
$secretValue = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($passphrase))
$secureSecretValue = ConvertTo-SecureString $secretValue -AsPlainText -Force
$secret = Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $secretName -SecretValue $secureSecretValue -tags $tags
$secretUrl = $secret.Id
KEK を使用せずに OS ディスクをアタッチする場合は、次の手順で $secretUrl
を使用します。
KEK で暗号化されるディスク暗号化シークレット
必要であれば、シークレットを Key Vault にアップロードする前に、キー暗号化キーを使用してシークレットを暗号化できます。 最初にキー暗号化キーを使用してシークレットを暗号化するには、ラップ API を使用します。 このラップ操作の出力は、base64 URL エンコードされた文字列です。これは、Set-AzKeyVaultSecret
コマンドレットを使用してシークレットとしてアップロードできます。
# This is the passphrase that was provided for encryption during the distribution installation
$passphrase = "contoso-password"
Add-AzKeyVaultKey -VaultName $KeyVaultName -Name "keyencryptionkey" -Destination Software
$KeyEncryptionKey = Get-AzKeyVaultKey -VaultName $KeyVault.OriginalVault.Name -Name "keyencryptionkey"
$apiversion = "2015-06-01"
##############################
# Get Auth URI
##############################
$uri = $KeyVault.VaultUri + "/keys"
$headers = @{}
$response = try { Invoke-RestMethod -Method GET -Uri $uri -Headers $headers } catch { $_.Exception.Response }
$authHeader = $response.Headers["www-authenticate"]
$authUri = [regex]::match($authHeader, 'authorization="(.*?)"').Groups[1].Value
Write-Host "Got Auth URI successfully"
##############################
# Get Auth Token
##############################
$uri = $authUri + "/oauth2/token"
$body = "grant_type=client_credentials"
$body += "&client_id=" + $AadClientId
$body += "&client_secret=" + [Uri]::EscapeDataString($AadClientSecret)
$body += "&resource=" + [Uri]::EscapeDataString("https://vault.azure.net")
$headers = @{}
$response = Invoke-RestMethod -Method POST -Uri $uri -Headers $headers -Body $body
$access_token = $response.access_token
Write-Host "Got Auth Token successfully"
##############################
# Get KEK info
##############################
$uri = $KeyEncryptionKey.Id + "?api-version=" + $apiversion
$headers = @{"Authorization" = "Bearer " + $access_token}
$response = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers
$keyid = $response.key.kid
Write-Host "Got KEK info successfully"
##############################
# Encrypt passphrase using KEK
##############################
$passphraseB64 = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Passphrase))
$uri = $keyid + "/encrypt?api-version=" + $apiversion
$headers = @{"Authorization" = "Bearer " + $access_token; "Content-Type" = "application/json"}
$bodyObj = @{"alg" = "RSA-OAEP"; "value" = $passphraseB64}
$body = $bodyObj | ConvertTo-Json
$response = Invoke-RestMethod -Method POST -Uri $uri -Headers $headers -Body $body
$wrappedSecret = $response.value
Write-Host "Encrypted passphrase successfully"
##############################
# Store secret
##############################
$secretName = [guid]::NewGuid().ToString()
$uri = $KeyVault.VaultUri + "/secrets/" + $secretName + "?api-version=" + $apiversion
$secretAttributes = @{"enabled" = $true}
$secretTags = @{"DiskEncryptionKeyEncryptionAlgorithm" = "RSA-OAEP"; "DiskEncryptionKeyFileName" = "LinuxPassPhraseFileName"}
$headers = @{"Authorization" = "Bearer " + $access_token; "Content-Type" = "application/json"}
$bodyObj = @{"value" = $wrappedSecret; "attributes" = $secretAttributes; "tags" = $secretTags}
$body = $bodyObj | ConvertTo-Json
$response = Invoke-RestMethod -Method PUT -Uri $uri -Headers $headers -Body $body
Write-Host "Stored secret successfully"
$secretUrl = $response.id
KEK を使用して OS ディスクをアタッチする場合は、次の手順で $KeyEncryptionKey
と $secretUrl
を使用します。
OS ディスクをアタッチするときにシークレット URL を指定する
KEK を使用しない
OS ディスクをアタッチする際に、$secretUrl
を渡す必要があります。 この URL は、「KEK で暗号化されないディスク暗号化シークレット」セクションで生成されたものです。
Set-AzVMOSDisk `
-VM $VirtualMachine `
-Name $OSDiskName `
-SourceImageUri $VhdUri `
-VhdUri $OSDiskUri `
-Linux `
-CreateOption FromImage `
-DiskEncryptionKeyVaultId $KeyVault.ResourceId `
-DiskEncryptionKeyUrl $SecretUrl
KEK を使用する
OS ディスクをアタッチする際に、$KeyEncryptionKey
と $secretUrl
を渡します。 この URL は、「KEK で暗号化されるディスク暗号化シークレット」セクションで生成されたものです。
Set-AzVMOSDisk `
-VM $VirtualMachine `
-Name $OSDiskName `
-SourceImageUri $CopiedTemplateBlobUri `
-VhdUri $OSDiskUri `
-Linux `
-CreateOption FromImage `
-DiskEncryptionKeyVaultId $KeyVault.ResourceId `
-DiskEncryptionKeyUrl $SecretUrl `
-KeyEncryptionKeyVaultId $KeyVault.ResourceId `
-KeyEncryptionKeyURL $KeyEncryptionKey.Id