Ejercicio: Uso de firmas de acceso compartido para delegar el acceso a Azure Storage

Completado

Azure Storage permite autorizar el acceso a archivos con una clave compartida, con una firma de acceso compartido (SAS) o mediante Microsoft Entra ID. Con una SAS, puede controlar lo que un cliente puede hacer con los archivos y durante cuánto tiempo.

El sistema de diagnóstico de imágenes de la empresa accede a las imágenes de los pacientes de forma interna a través de una clave compartida. Tiene que crear una API para permitir el acceso de terceros a las imágenes de diagnóstico. Va a crear una página de prueba en la aplicación web para ver cómo una SAS puede ayudar a conceder acceso seguro a los clientes de terceros.

En este ejercicio, creará una cuenta de almacenamiento y cargará algunas imágenes de pacientes de ejemplo. Implementará la aplicación web existente del equipo y comprobará que puede acceder al almacenamiento. El último paso consiste en agregar código de C# y JavaScript para generar un token de SAS a petición a fin de ver las imágenes de forma segura.

Screenshot of your company's patient diagnostic image system showing three images.

Creación de una cuenta de almacenamiento y carga de imágenes

  1. Con Azure Cloud Shell, escriba el código siguiente para crear una cuenta de almacenamiento para las imágenes de los pacientes. El código genera un nombre de cuenta de almacenamiento.

    export STORAGENAME=medicalrecords$RANDOM
    
    az storage account create \
        --name $STORAGENAME \
        --access-tier hot \
        --kind StorageV2 \
        --resource-group "<rgn>[sandbox resource group name]</rgn>"
    
  2. Cree un contenedor en la cuenta de almacenamiento para almacenar las imágenes.

    az storage container create \
        --name patient-images \
        --account-name $STORAGENAME \
        --public-access off
    
  3. Clone la aplicación web existente del equipo. Este repositorio contiene imágenes de ejemplo usadas por el equipo en las pruebas.

    git clone https://github.com/MicrosoftDocs/mslearn-control-access-to-azure-storage-with-sas.git sas
    
  4. Use el comando upload-batch de la CLI de Azure para cargar las imágenes en la cuenta de almacenamiento.

    az storage blob upload-batch \
        --source sas \
        --destination patient-images \
        --account-name $STORAGENAME \
        --pattern *.jpg
    

Prueba del sistema de imágenes de diagnóstico de pacientes

  1. Abra el archivo appsettings.json en el editor de código para poder agregar la cadena de conexión de la cuenta de almacenamiento.

    code sas/appsettings.json
    
  2. En Cloud Shell, escriba el código siguiente para obtener la cadena de conexión a la cuenta de almacenamiento.

    az storage account show-connection-string --name $STORAGENAME
    

    Debería ver una respuesta en este formato:

    {
      "connectionString": "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=medicalrecords3215;AccountKey=UGLNuJWUBtodz+VbhhFcMwkzDpX49Wf7FxtuQDTOHhH+LpCtSQ2LBP0Ju8TQby5CeOt7DMYBgH45SX9yFwqPvA=="
    }
    

    Copie el valor connectionString, incluidas las comillas.

  3. En el editor de código, reemplace el valor ConnectionString "[connection string]" por la cadena que ha copiado.

  4. Copie el valor de AccountName= en el cuerpo de la cadena de conexión.

  5. Reemplace el valor del parámetro AccountName por el valor de nombre de cuenta que ha copiado.

  6. Copie el valor de AccountKey= en el cuerpo de la cadena de conexión (no incluya las comillas). Asegúrese de incluir == al final del valor.

  7. Reemplace el valor del parámetro AccountKey por el valor de clave de cuenta que ha copiado.

  8. El archivo appsettings.json debe tener un aspecto similar a esta salida.

    {
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*",
      "StorageAccount": {
        "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=medicalrecords3215;AccountKey=UGLNuJWUBtodz+VbhhFcMwkzDpX49Wf7FxtuQDTOHhH+LpCtSQ2LBP0Ju8TQby5CeOt7DMYBgH45SX9yFwqPvA==;EndpointSuffix=core.windows.net",
        "Container" : "patient-images",
        "AccountName":"medicalrecords3215",
        "AccountKey":"UGLNuJWUBtodz+VbhhFcMwkzDpX49Wf7FxtuQDTOHhH+LpCtSQ2LBP0Ju8TQby5CeOt7DMYBgH45SX9yFwqPvA=="
      }  
    }
    
  9. Presione Ctrl+S y después Ctrl+Q para guardar y cerrar el editor de código.

  10. Abra un puerto para acceder a la aplicación web cuando se ejecuta en Cloud Shell.

    curl -X POST http://localhost:8888/openPort/8000;
    

    Este comando devuelve un valor url desde la que se puede acceder a la aplicación.

    {"message":"Port 8000 is open","url":"https://gateway11.northeurope.console.azure.com/n/cc-4016c848/cc-4016c848/proxy/8000/"}
    
  11. Ejecute la aplicación.

    cd sas
    dotnet run
    

    Una vez compilada la aplicación, la consola de Cloud Shell muestra detalles similares al ejemplo siguiente.

    Hosting environment: Development
    Content root path: /home/<yourusername>/sas
    Now listening on: https://localhost:8001
    Now listening on: http://localhost:8000
    Application started. Press Ctrl+C to shut down.
    
  12. En un explorador, pegue la dirección URL devuelta por el comando cURL anterior. Asegúrese de incluir la barra diagonal (/) al final de la dirección.

    La dirección URL debe tener este formato: https://gateway11.northeurope.console.azure.com/n/cc-4016c848/cc-4016c848/proxy/8000/.

    Si se le pide que inicie sesión, actualice la ventana del explorador. Aparece el sistema de imágenes de diagnóstico de pacientes de Lamna Healthcare.

  13. Seleccione Get all patients (Obtener todos los pacientes) para ver una lista de todas las imágenes de la cuenta de almacenamiento.

Adición de código para crear una SAS

  1. En Cloud Shell, presione Ctrl+C para detener la aplicación web.

  2. Ahora se mejorará la clase PatientRecordController para crear una SAS a petición y devolverla al front-end de la aplicación web.

  3. Escriba el código siguiente para abrir el archivo PatientRecordController.cs en el editor de código.

    code Controllers/PatientRecordController.cs
    
  4. Agregue el código siguiente a la parte inferior de la clase en el método GET PatientRecord/patient-nnnnnn.

    // GET PatientRecord/patient-nnnnnn/secure
    [HttpGet("{Name}/{secure}")]
    public PatientRecord Get(string name, string flag)
    {
        BlobClient blob = _container.GetBlobClient(name);
        return new PatientRecord { name=blob.Name, imageURI=blob.Uri.AbsoluteUri, sasToken=GetBlobSas(blob) };
    }
    

    Este método devuelve la imagen de paciente solicitada con una SAS que se puede usar para acceder a ella.

  5. Agregue un método que crea la SAS para el blob.

    // Build a SAS token for the given blob
    private string GetBlobSas(BlobClient blob)
    {
        // Create a user SAS that only allows reading for a minute
        BlobSasBuilder sas = new BlobSasBuilder 
        {
            BlobContainerName = blob.BlobContainerName,
            BlobName = blob.Name,
            Resource = "b",
            ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(1)
        };
        // Allow read access
        sas.SetPermissions(BlobSasPermissions.Read);
    
        // Use the shared key to access the blob
        var storageSharedKeyCredential = new StorageSharedKeyCredential(
            _iconfiguration.GetValue<string>("StorageAccount:AccountName"),
            _iconfiguration.GetValue<string>("StorageAccount:AccountKey")
        );
    
        return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
    }
    

    Este método usa el objeto BlobClient pasado para crear un elemento BlobSasBuilder a fin de generar una SAS de solo lectura que expira en un minuto.

  6. Presione Ctrl+S para guardar el archivo y después Ctrl+Q para salir del editor.

Adición de código para usar la SAS

Ahora agregará código a la página web para solicitar la SAS para la imagen.

  1. Escriba el comando siguiente para editar la página external.cshtml.

    code Pages/external.cshtml
    
    
  2. Cerca del final del archivo, en el cliente de escucha de clic para #btn-submit, modifique la línea $.get para agregar + '/secure':

    $('#btn-submit').click(function(){
        $('#result').empty();
        $.get('api/PatientRecords/' + $('#patientID').val() + '/secure', function (data) {
            var imageURL = data.imageURI + $('#sasKey').val();
            $('#result').html('<img id="patientScan" class="alert alert-success" src="' + imageURL + '" alt="patient scan" onerror="this.classList.remove(\'alert-success\'); this.classList.add(\'alert-danger\')"//>');
        }, 'json');
    });
    
  3. Debajo de la función del cliente de escucha de clic #btn-submit, en la parte inferior del archivo, encima de la etiqueta </script>, agregue el código siguiente:

    $('#btn-getKey').click(function(){
        $.get('api/PatientRecords/' + $('#patientID').val() + '/secure', function (data) {
            $('#sasKey').val(data.sasToken);
        }, 'json');
    });
    

    Este código de jQuery agrega un cliente de escucha de clic en el botón btn-getKey. El código ejecuta una llamada Ajax a la nueva dirección URL segura para el archivo de imagen especificado. Cuando devuelve un valor, rellena el cuadro de entrada de la clave con la SAS.

  4. Presione Ctrl+S para guardar los cambios y después Ctrl+Q para salir del editor.

Prueba de los cambios

  1. Ejecute la aplicación actualizada.

    dotnet run
    
  2. En el explorador, actualice la pestaña del sitio web. Seleccione Get all patients (Obtener todos los pacientes) y, después, copie uno de los nombres de archivo de imagen.

  3. En el menú de la parte superior de la página web, seleccione External companies (Empresas externas).

  4. Pegue el nombre de archivo en el campo Patient image filename (Nombre del archivo de imagen de paciente).

  5. Seleccione View scan (Ver examen). No se puede acceder a la imagen de examen de pacientes porque no se ha creado una SAS.

    Nota:

    Si ve la consola en el explorador, verá que el servidor web ha devuelto un mensaje con el código de error 404.

  6. Seleccione Obtener clave, lo que debe rellenar el campo Clave con una SAS.

  7. Seleccione View scan (Ver examen). Debería aparecer la imagen de diagnóstico del paciente.

    Screenshot of API for external companies showing a patient's image.

  8. En el explorador, haga clic con el botón derecho en la imagen y copie su dirección.

  9. Abra una nueva pestaña del explorador, pegue la dirección de la imagen copiada en la barra de direcciones y presione Entrar. Si ha transcurrido más de un minuto desde que ha creado la SAS, verá un mensaje de error. Si ha pasado menos de un minuto, debería mostrarse la imagen.

    Nota:

    Es posible que tenga que actualizar la página.

    <Error>
        <Code>AuthenticationFailed</Code>
        <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly, including the signature.
        RequestId:03eda893-f01e-0028-2d73-c5c947000000
        Time:2021-01-07T16:02:55.3752851Z</Message>
        <AuthenticationErrorDetail>Signed expiry time [Tue, 07 Jan 2021 16:02:00 GMT] must be after signed start time [Tue, 07 Jan 2021 16:02:55 GMT]</AuthenticationErrorDetail>
    </Error>
    

    Nota:

    Para ver este mensaje de error en algunos exploradores, es posible que tenga que abrir una nueva ventana del explorador que no haya almacenado la imagen en caché.

  10. En Cloud Shell, presione Ctrl+C para salir de la aplicación web.