Share via


Scripts de ejemplo de Azure Disk Encryption para máquinas virtuales Linux

Precaución

En este artículo se hace referencia a CentOS, una distribución de Linux que está cerca de su estado Final de ciclo vida (EOL). Tenga en cuenta su uso y planifique en consecuencia. Para obtener más información, consulte la guía de fin de vida de CentOS.

Se aplica a: ✔️ máquinas virtuales Linux ✔️ conjuntos de escalado flexibles

En este artículo se proporcionan scripts de ejemplo tanto para preparar los discos duros virtuales previamente cifrados como para realizar otras tareas.

Nota

Todos los scripts hacen referencia a la versión más reciente de ADE que no sea de AAD, excepto donde se indique lo contrario.

Scripts de ejemplo de PowerShell para Azure Disk Encryption

  • Enumerar todas las máquinas virtuales cifradas en la suscripción

    Puede encontrar todas las VM cifradas con ADE y la versión de la extensión en todos los grupos de recursos presentes en una suscripción, mediante este script de PowerShell.

    Como alternativa, estos cmdlets mostrarán todas las VM cifradas con ADE (pero no la versión de la extensión):

    $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}
    
  • Enumeración de todas las instancias de VMSS cifradas de la suscripción

    Puede encontrar todas las instancias de VMSS cifradas con ADE y la versión de la extensión en todos los grupos de recursos presentes en una suscripción, mediante este script de PowerShell.

  • Enumerar todos los secretos de cifrado de disco usados para cifrar las máquinas virtuales en un almacén de claves

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

Uso del script de PowerShell de requisitos previos de Azure Disk Encryption

Si ya está familiarizado con los requisitos previos para Azure Disk Encryption, puede usar el script de PowerShell de requisitos previos de Azure Disk Encryption. Para un ejemplo de uso de este script de PowerShell, consulte la guía de inicio rápido para el cifrado de máquinas virtuales. Puede quitar los comentarios de una sección del script, a partir de la línea 211, para cifrar todos los discos de las máquinas virtuales de un grupo de recursos existente.

En la siguiente tabla se muestran los parámetros que se pueden usar en el script de PowerShell:

Parámetro Descripción ¿Obligatorio?
$resourceGroupName Nombre del grupo de recursos al que pertenece la instancia de KeyVault. Si no existe, se creará un grupo de recursos con este nombre. True
$keyVaultName Nombre de la instancia de KeyVault en donde se colocarán las claves de cifrado. Si no existe, se creará un almacén con este nombre. True
$location Ubicación de la instancia de KeyVault. Asegúrese de que la instancia de KeyVault y las máquinas virtuales que se van a cifrar están en la misma ubicación. Obtenga una lista de ubicaciones con Get-AzLocation. True
$subscriptionId Identificador de la suscripción de Azure que se va a utilizar. El identificador de la suscripción se puede obtener con Get-AzSubscription. True
$aadAppName Nombre de la aplicación de Microsoft Entra que se va a utilizar para escribir secretos en KeyVault. Si no existe, se creará una aplicación con este nombre. Si esta aplicación ya existe, pasará el parámetro aadClientSecret al script. False
$aadClientSecret Secreto de cliente de la aplicación de Microsoft Entra que se creó antes. False
$keyEncryptionKeyName Nombre de la clave de cifrado de clave opcional en KeyVault. Si no existe, se creará una clave con este nombre. False

Cifrado o descifrado de máquinas virtuales sin una aplicación de Microsoft Entra

Cifrado o descifrado de máquinas virtuales con una aplicación de Microsoft Entra (versión anterior)

Cifrado de la unidad del sistema operativo en una máquina virtual con Linux en ejecución

Requisitos previos para el cifrado de disco del sistema operativo

  • La máquina virtual debe usar una distribución compatible con el cifrado del disco del sistema operativo, como se muestra en el artículo Sistemas operativos compatibles con Azure Disk Encryption
  • La máquina virtual debe crearse a partir de la imagen de Marketplace en Azure Resource Manager.
  • La máquina virtual de Azure con al menos 4 GB de RAM (el tamaño recomendado es 7 GB). Consulte Requisitos de memoria para obtener más información.
  • (Para RHEL y CentOS) Deshabilite SELinux. Para deshabilitar SELinux, consulte "4.4.2. Disabling SELinux" (Deshabilitar SELinux) en el documento SELinux User's and Administrator's Guide (Guía del administrador y del usuario de SELinux) en la máquina virtual.
  • Después de deshabilitar SELinux, reinicie la máquina virtual al menos una vez.

Pasos

  1. Cree una máquina virtual mediante una de las distribuciones especificadas anteriormente.

  2. Configure la máquina virtual según sus necesidades. Si va a cifrar todas las unidades (sistema operativo y datos), las unidades de datos tienen que especificarse y montarse desde /etc/fstab.

    Nota

    Use UUID=... para especificar unidades de datos en /etc/fstab en lugar de especificar el nombre del dispositivo de bloque (por ejemplo, /dev/sdb1). Durante el cifrado, se cambia el orden de las unidades en la máquina virtual. Si la máquina virtual depende de un orden específico de dispositivos de bloque, se producirá un error de montaje después del cifrado.

  3. Cierre las sesiones de SSH.

  4. Para cifrar el sistema operativo, especifique volumeType como All u OS al habilitar el cifrado.

    Nota

    Todos los procesos de espacio de usuario que no se ejecutan como servicios systemd deben terminarse con SIGKILL. Reinicie la máquina virtual. Al habilitar el cifrado del disco de sistema operativo en una máquina virtual en ejecución, tenga en cuenta el tiempo de inactividad de la máquina virtual.

  5. Supervise periódicamente el progreso del cifrado con las instrucciones de la sección siguiente.

  6. Cuando Get-AzVmDiskEncryptionStatus muestre "VMRestartPending", inicie sesión en la máquina virtual para reiniciarla o hágalo mediante el portal, PowerShell o la CLI.

    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
    

    Antes de reiniciar, se recomienda que guarde los diagnósticos de arranque de la máquina virtual.

Supervisión del progreso de cifrado del sistema operativo

Hay tres maneras de supervisar el progreso de cifrado del sistema operativo:

  • Use el cmdlet Get-AzVmDiskEncryptionStatus e inspeccione el campo ProgressMessage:

    Get-AzVMDiskEncryptionStatus -ResourceGroupName $_.ResourceGroupName -VMName $_.Name
    
    OsVolumeEncrypted          : EncryptionInProgress
    DataVolumesEncrypted       : NotMounted
    OsVolumeEncryptionSettings : Microsoft.Azure.Management.Compute.Models.DiskEncryptionSettings
    ProgressMessage            : OS disk encryption started
    

    Una vez que la máquina virtual llega al mensaje de inicio del cifrado de disco del sistema operativo, el proceso tarda aproximadamente entre 40 y 50 minutos en una máquina virtual de almacenamiento Premium.

    Debido al problema 388 de WALinuxAgent, OsVolumeEncrypted y DataVolumesEncrypted se muestran como Unknown en algunas distribuciones. En WALinuxAgent versión 2.1.5 y versiones posteriores, este problema se ha corregido automáticamente. En caso de que se vea Unknown en la salida, puede comprobar el estado de cifrado del disco mediante el Explorador de recursos de Azure.

    Vaya al Explorador de recursos de Azure y expanda esta jerarquía en el panel de selección a la izquierda:

    |-- subscriptions
       |-- [Your subscription]
            |-- resourceGroups
                 |-- [Your resource group]
                      |-- providers
                           |-- Microsoft.Compute
                                |-- virtualMachines
                                     |-- [Your virtual machine]
                                          |-- InstanceView
    

    En el objeto InstanceView, desplácese hacia abajo para ver el estado de cifrado de las unidades de disco.

    Vista de instancia de máquina virtual

  • Fíjese en los diagnósticos de arranque. Los mensajes de la extensión ADE deben llevar el prefijo [AzureDiskEncryption].

  • Inicie sesión en la máquina virtual a través de SSH y obtenga el registro de la extensión de:

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

    Se recomienda que no inicie sesión en la máquina virtual con el cifrado del sistema operativo en curso. Copie los registros solo cuando los otros dos métodos no den resultado.

Preparación de un VHD con Linux precifrado

La preparación de disco duros virtuales previamente cifrados puede variar dependiendo de la distribución. Se pueden encontrar ejemplos sobre cómo preparar Ubuntu, openSUSE y CentOS 7.

Configure el cifrado durante la instalación de la distribución; para ello, siga estos pasos:

  1. Seleccione Configure encrypted volumes (Configurar volúmenes cifrados) al realizar la partición de los discos.

    Configuración de Ubuntu 16.04: configuración de volúmenes cifrados

  2. Cree una unidad de arranque independiente, que no debe estar cifrada. Cifre la unidad raíz.

    Configuración de Ubuntu 16.04: selección de dispositivos para cifrar

  3. Proporcione una frase de contraseña. Se trata de la frase de contraseña que se carga en el almacén de claves.

    Configuración de Ubuntu 16.04: suministro de la frase de contraseña

  4. Finalice la partición.

    Configuración de Ubuntu 16.04: finalización de la creación de particiones

  5. Cuando arranque la máquina virtual y se le pida una frase de contraseña, utilice la frase de contraseña que especificó en el paso 3.

    Configuración de Ubuntu 16.04: suministro de la frase de contraseña en el arranque

  6. Prepare la máquina virtual para su carga en Azure con estas instrucciones. No ejecute todavía el último paso (desaprovisionamiento de la máquina virtual).

Configure el cifrado para que funcione con Azure de esta manera:

  1. Cree un archivo en /usr/local/sbin/azure_crypt_key.sh, con el contenido del siguiente script. Preste atención a KeyFileName, porque es el nombre que Azure ha asignado al archivo de frase de contraseña.

    #!/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. Cambie la configuración de cifrado en /etc/crypttab. Debería ser parecido a este:

     xxx_crypt uuid=xxxxxxxxxxxxxxxxxxxxx none luks,discard,keyscript=/usr/local/sbin/azure_crypt_key.sh
    
  3. Agregue permisos de ejecución al script:

     sudo chmod +x /usr/local/sbin/azure_crypt_key.sh
    
  4. Edite /etc/initramfs-tools/modules anexando líneas:

     vfat
     ntfs
     nls_cp437
     nls_utf8
     nls_iso8859-1
    
  5. Ejecute update-initramfs -u -k all para actualizar initramfs a fin de que keyscript surta efecto.

  6. Ahora puede desaprovisionar la máquina virtual.

    Configuración de Ubuntu 16.04: update-initramfs

  7. Continúe con el paso siguiente y cargue el disco duro virtual en Azure.

Carga de un VHD cifrado a una cuenta de almacenamiento de Azure

Una vez que se cifre DM-Crypt, el disco duro virtual cifrado local debe cargarse en la cuenta de almacenamiento.

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

Carga del secreto de la máquina virtual previamente cifrada en el almacén de claves

Al cifrar mediante una aplicación de Microsoft Entra (versión anterior), el secreto de cifrado del disco que obtuvo con anterioridad se debe cargar como secreto en el almacén de claves. El almacén de claves debe tener habilitados el cifrado de discos y los permisos para el cliente de 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

Secreto del cifrado de disco no cifrado con una KEK

Para configurar el secreto en el almacén de claves, use Set-AzKeyVaultSecret. La frase de contraseña se codifica en forma de cadena base64 y, después, se carga en el almacén de claves. Además, asegúrese de que se establecen las siguientes etiquetas al crear el secreto en el almacén de claves.


 # 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

Use $secretUrl en el paso siguiente para conectar el disco del sistema operativo sin usar KEK.

Secreto del cifrado de disco cifrado con una KEK

Antes de cargar el secreto en el almacén de claves, puede cifrarlo si lo desea mediante una clave de cifrado de claves. Utilice la API de encapsulamiento para cifrar por primera vez el secreto mediante la clave de cifrado de claves. El resultado de esta operación de encapsulamiento es una cadena codificada en URL como base64 que luego se carga como secreto con el cmdlet 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

Use $KeyEncryptionKey y $secretUrl en el paso siguiente para conectar el disco del sistema operativo usando KEK.

Especificación de una dirección URL de secreto al adjuntar un disco del sistema operativo

Sin utilizar una KEK

Mientras esté adjuntando el disco del sistema operativo, tiene que pasar $secretUrl. La dirección URL se generó en la sección "Secreto de cifrado de disco no cifrado con una KEK".

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

Uso de una KEK

Cuando conecte un disco del sistema operativo, pase $KeyEncryptionKey y $secretUrl. La dirección URL se generó en la sección "Secreto del cifrado de disco cifrado con 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