Поделиться через


Примеры скриптов шифрования дисков Azure для виртуальных машин под управлением Linux

Внимание

Эта статья ссылается на CentOS, дистрибутив Linux, который является состоянием "Конец жизни" (EOL). Обратите внимание на использование и план соответствующим образом. Дополнительные сведения см. в руководстве centOS End Of Life.

Область применения: ✔️ Виртуальные машины Linux ✔️ Гибкие масштабируемые наборы

В этой статье приводятся примеры сценариев для подготовки предварительно зашифрованных виртуальных жестких дисков и других задач.

Примечание.

Если не указано иное, все скрипты используют последнюю версию Шифрования дисков Azure (ADE) без поддержки AAD.

Примеры сценариев PowerShell для шифрования дисков Azure

  • Вывод списка всех зашифрованных виртуальных машин в подписке

    Все виртуальные машины, зашифрованные с помощью ADE, и версию расширения во всех группах ресурсов в подписке можно найти с помощью этого скрипта PowerShell.

    Кроме того, эти командлеты отобразят все виртуальные машины, зашифрованные с помощью ADE (без версии расширения):

    $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}
    
  • Получение списка всех зашифрованных экземпляров Масштабируемых наборов виртуальных машин в подписке

    Вы можете найти все экземпляры Масштабируемых наборов виртуальных машин, зашифрованных с помощью ADE, во всех группах ресурсов в подписке и узнать версию расширения с помощью этого скрипта PowerShell.

  • Вывод списка всех секретов шифрования дисков, используемых для шифрования виртуальных машин в хранилище ключей

    Get-AzKeyVaultSecret -VaultName $KeyVaultName | where {$_.Tags.ContainsKey('DiskEncryptionKeyFileName')} | format-table @{Label="MachineName"; Expression={$_.Tags['MachineName']}}, @{Label="VolumeLetter"; Expression={$_.Tags['VolumeLetter']}}, @{Label="EncryptionKeyURL"; Expression={$_.Id}}
    

Использование скрипта PowerShell для Шифрование дисков Azure необходимых компонентов

Если вы уже знакомы с предварительными требованиями для шифрования дисков Azure, можно использовать соответствующий сценарий PowerShell предварительных требований. Пример использования этого сценария PowerShell см. в статье Краткое руководство. Шифрование виртуальной машины IaaS под управлением Windows с помощью Azure PowerShell. Вы можете удалить комментарии из раздела сценария, начиная со строки 211, чтобы шифровать все диски имеющихся виртуальных машин в имеющейся группе ресурсов.

В следующей таблице показано, какие параметры могут использоваться в сценарии PowerShell:

Параметр Описание Обязательный?
$resourceGroupName Имя группы ресурсов, к которой принадлежит хранилище ключей. При отсутствии группы ресурсов с таким именем — она будет создана. Истина
$keyVaultName Имя хранилища ключей, в котором будут размещаться ключи шифрования. При отсутствии хранилища ключей с таким именем — оно будет создано. Истина
$location Расположение хранилища ключей. Убедитесь, что хранилище ключей и виртуальные машины, которые предстоит зашифровать, находятся в одном расположении. Получите список расположений с помощью команды Get-AzLocation. Истина
$subscriptionId Идентификатор подписки Azure для использования. Вы можете получить идентификатор подписки с помощью команды Get-AzSubscription. Истина
$aadAppName Имя приложения Microsoft Entra, которое будет использоваться для записи секретов в KeyVault. Будет создано приложение с таким именем (если оно еще не создано). Если это приложение уже есть, передайте параметр aadClientSecret в сценарий. False
$aadClientSecret Секрет клиента приложения Microsoft Entra, созданного ранее. False
$keyEncryptionKeyName Имя дополнительного ключа шифрования ключа в хранилище ключей. При отсутствии ключа с таким именем — он будет создан. False

Шифрование или расшифровка виртуальных машин без приложения Microsoft Entra

Шифрование или расшифровка виртуальных машин с помощью приложения Microsoft Entra (предыдущий выпуск)

Шифрование диска ОС на работающей виртуальной машине Linux

Предварительные требования для шифрования диска ОС

  • Виртуальная машина должна использовать дистрибутив, совместимый с шифрованием диска ОС. Список дистрибутивов см. в статье Операционные системы с поддержкой шифрования дисков Azure.
  • Виртуальная машина должна быть создана из образа Marketplace в Azure Resource Manager.
  • Виртуальная машина Azure по крайней мере с 4 ГБ ОЗУ (рекомендуемый размер — 7 ГБ). Дополнительные сведения см. в разделе "Требования к памяти".
  • (Для RHEL и CentOS.) Отключите SELinux. Чтобы отключить SELinux на виртуальной машине, ознакомьтесь с разделом "4.4.2. Disabling SELinux" (4.4.2. Отключение SELinux) руководства пользователя и администратора SELinux.
  • После отключения SELinux перезагрузите виртуальную машину по крайней мере один раз.

Шаги

  1. Создайте виртуальную машину с помощью одного из дистрибутивов, указанных ранее.

  2. Настройте виртуальную машину в соответствии с потребностями. Если вы собираетесь включить шифрование всех дисков (диска ОС и дисков данных), то диски данных необходимо указать и подключить в файле /etc/fstab.

    Примечание.

    Чтобы указать диски данных в файле /etc/fstab, используйте значение UUID=... (в этом случае не нужно указывать имя блочного устройства, например /dev/sdb1). В процессе шифрования порядок дисков на виртуальной машине изменится. Если на виртуальной машине используется определенный порядок блочных устройств, то при их подключении после шифрования произойдет сбой.

  3. Выйдите из сеансов SSH.

  4. Чтобы зашифровать ОС, задайте при включении шифрования для параметра volumeType значение All или OS.

    Примечание.

    Все пользовательские процессы, не запущенные как службы systemd, необходимо завершить с помощью SIGKILL. Перезагрузите виртуальную машину. В случае включения шифрования диска ОС на работающей виртуальной запланируйте период простоя.

  5. Периодически отслеживайте ход выполнения шифрования, следуя инструкциям из следующего раздела.

  6. Как только командлет Get-AzVmDiskEncryptionStatus вернет значение VMRestartPending, перезапустите виртуальную машину, выполнив вход, либо с помощью портала, PowerShell или интерфейса командной строки.

    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
    

    Перед перезагрузкой рекомендуется сохранить диагностические данные загрузки виртуальной машины.

Мониторинг хода выполнения шифрования операционной системы

Мониторинг хода выполнения шифрования ОС можно выполнять тремя способами.

  • Используйте командлет 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
    

    На виртуальных машинах с хранилищем класса Premium шифрование диска ОС длится 40–50 минут с момента появления сообщения "OS disk encryption started" (Начато шифрование диска ОС).

    В связи с ошибкой № 388 в WALinuxAgent в некоторых дистрибутивах 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 прокрутите вниз, чтобы увидеть состояние шифрования дисков.

    Представление экземпляра виртуальной машины

  • Просмотрите диагностические данные загрузки. Сообщения расширения шифрования дисков Azure должны начинаться с [AzureDiskEncryption].

  • Выполните вход на виртуальную машину с помощью протокола SSH и скопируйте журнал расширения, расположенный по следующему пути:

    /var/log/azure/Microsoft.Azure.Security.AzureDiskEncryptionForLinux

    Мы советуем не входить на виртуальную машину, пока шифруется ее диск ОС. Копируйте журналы только в том случае, когда два других способа не дали результата.

Подготовка предварительно зашифрованного виртуального жесткого диска Linux

Шаги подготовки предварительно зашифрованных виртуальных жестких дисков могут отличаться в зависимости от дистрибутива. Доступны примеры подготовки Ubuntu, openSUSE и CentOS 7.

Настройте шифрование во время установки дистрибутива следующим образом.

  1. Во время настройки разделов дисков выберите Configure encrypted volumes (Настройка зашифрованных томов).

    Настройка зашифрованных томов при настройке Ubuntu 16.04

  2. Создайте отдельный загрузочный диск (незашифрованный). Зашифруйте корневой диск.

    Выбор устройств для шифрования при настройке Ubuntu 16.04

  3. Укажите парольную фразу. Это парольная фраза, которую вы передали в хранилище ключей.

    Указание парольной фразы при настройке Ubuntu 16.04

  4. Завершите настройку разделов.

    Завершение секционирования при настройке Ubuntu 16.04

  5. После загрузки виртуальной машины отобразится запрос парольной фразы. Введите парольную фразу, указанную на шаге 3.

    Указание парольной фразы во время загрузки при настройке Ubuntu 16.04

  6. Подготовьте виртуальную машину к передаче в Azure, следуя этим инструкциям. Пока не выполняйте последний шаг (отзыв виртуальной машины).

Настройте шифрование для Azure, выполнив следующие шаги.

  1. Создайте файл в разделе /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
    
  2. Измените настройки шифрования в /etc/crypttab. Он должен выглядеть так:

     xxx_crypt uuid=xxxxxxxxxxxxxxxxxxxxx none luks,discard,keyscript=/usr/local/sbin/azure_crypt_key.sh
    
  3. Добавьте в сценарий разрешения для исполняемого файла.

     sudo chmod +x /usr/local/sbin/azure_crypt_key.sh
    
  4. Изменение /etc/initramfs-tools/modules путем добавления строк:

     vfat
     ntfs
     nls_cp437
     nls_utf8
     nls_iso8859-1
    
  5. Выполните update-initramfs -u -k all и обновите initramfs, чтобы keyscript вступил в действие.

  6. Теперь виртуальную машину можно отозвать.

    Обновление initramfs при настройке Ubuntu 16.04

  7. Перейдите к следующему шагу и передайте свой виртуальный жесткий диск в Azure.

Передача зашифрованного виртуального жесткого диска в учетную запись хранения Azure

После включения шифрования DM-Crypt локальный зашифрованный виртуальный жесткий диск нужно отправить в учетную запись хранения.

    Add-AzVhd [-Destination] <Uri> [-LocalFilePath] <FileInfo> [[-NumberOfUploaderThreads] <Int32> ] [[-BaseImageUriToPatch] <Uri> ] [[-OverWrite]] [ <CommonParameters>]

Отправка секрета для предварительно зашифрованной виртуальной машины в хранилище ключей

При шифровании с помощью приложения 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, а затем отправить в хранилище ключей. Убедитесь также, что при создании секрета в хранилище ключей были установлены следующие теги.


 # 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

На следующем шаге используйте $secretUrl, чтобы подключить диск ОС, не применяя ключ шифрования ключей.

Секрет дискового шифрования, зашифрованный с помощью KEK

Перед передачей секрета в хранилище ключей его можно дополнительно зашифровать с помощью ключа шифрования ключей. Используйте API для создания оболочки, чтобы сначала зашифровать секрет с использованием ключа шифрования ключей. Эта операция возвращает значения, закодированные как строка URL-адреса в кодировке Base64, которые затем передаются в качестве секрета с помощью командлета 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

На следующем шаге мы используем $KeyEncryptionKey и $secretUrl, чтобы подключить диск ОС, применив ключ шифрования ключей.

Указание URL-адреса секрета при подключении диска ОС

Без использования ключа шифрования ключа

При подключении диска ОС необходимо передать $secretUrl. Этот URL-адрес был создан в разделе "Секрет шифрования дисков, не зашифрованный с помощью ключа шифрования ключей".

    Set-AzVMOSDisk `
            -VM $VirtualMachine `
            -Name $OSDiskName `
            -SourceImageUri $VhdUri `
            -VhdUri $OSDiskUri `
            -Linux `
            -CreateOption FromImage `
            -DiskEncryptionKeyVaultId $KeyVault.ResourceId `
            -DiskEncryptionKeyUrl $SecretUrl

С использованием ключа шифрования ключа

При подключении диска ОС передайте $KeyEncryptionKey и $secretUrl. Этот URL-адрес был создан в разделе "Секрет шифрования дисков, зашифрованный с помощью ключа шифрования ключей".

    Set-AzVMOSDisk `
            -VM $VirtualMachine `
            -Name $OSDiskName `
            -SourceImageUri $CopiedTemplateBlobUri `
            -VhdUri $OSDiskUri `
            -Linux `
            -CreateOption FromImage `
            -DiskEncryptionKeyVaultId $KeyVault.ResourceId `
            -DiskEncryptionKeyUrl $SecretUrl `
            -KeyEncryptionKeyVaultId $KeyVault.ResourceId `
            -KeyEncryptionKeyURL $KeyEncryptionKey.Id