Protección de la privacidad de los datos de atención médica: una guía en Google Cloud Platform (GCP)

May 10 2022
Los datos de atención médica son increíblemente confidenciales y es responsabilidad de todos garantizar que estos datos estén protegidos. Dado que la atención médica está cambiando de digital, gracias en parte a la pandemia mundial, la protección de la privacidad de los datos al tiempo que permite el acceso necesario es especialmente importante.

Los datos de atención médica son increíblemente confidenciales y es responsabilidad de todos garantizar que estos datos estén protegidos. Dado que la atención médica está cambiando de digital, gracias en parte a la pandemia mundial, la protección de la privacidad de los datos al tiempo que permite el acceso necesario es especialmente importante. Afortunadamente, existen servicios y herramientas que nos permiten usar los datos de manera efectiva y al mismo tiempo garantizar la privacidad del paciente. El objetivo de este blog es repasar las implementaciones técnicas de los servicios dentro de Google Cloud Platform (GCP) que ayudan a lograr el equilibrio adecuado; Exploraremos los servicios de GCP, incluidos Data Loss Prevention (DLP) y Identity and Access Management (IAM), y profundizaremos en los detalles de implementación técnica a lo largo del camino.

Los datos son la fuerza impulsora detrás de la mejora de la experiencia de atención médica. ¡Los datos son una necesidad cuando se trata de generar recomendaciones, notificaciones, personalización e incluso características de un producto! Y dado que estos datos deben ser respaldados por ingenieros, analistas y equipos técnicos, no es factible restringir todo el acceso a los datos. Por otro lado, sería irresponsable permitir el acceso completo por el bien de los "requisitos de operación comercial". Entonces, ¿cuál es el secreto para encontrar una solución? Acceso limitado y parcial: ¡podemos proporcionar acceso a los datos de una manera que los hace no identificables y al mismo tiempo permitir que nuestros equipos hagan su trabajo!

Lo primero es lo primero: League, un orgulloso socio de GCP , sigue el método HIPAA Safe Harbor para desidentificar datos. En pocas palabras, el método Safe Harbor mantiene que al ocultar 18 identificadores particulares pertenecientes a un usuario (es decir, nombre, fecha de nacimiento, SSN, etc.). Con este enfoque, podemos esperar razonablemente que los datos no sean identificables o anonimizados. Si bien existen matices complejos en este método, las dos técnicas de implementación que se describen a continuación se basan en este enfoque.

Términos importantes a tener en cuenta: los datos que pueden identificar a una persona de manera única se denominan información de identificación personal (PII) y un subconjunto de PII relacionado con la información médica se denomina información de salud protegida (PHI). Además: tenga en cuenta que los ejemplos a continuación son ficticios con fines educativos y no representan ningún dato real.

Acceso a datos limitado y parcial

Caso de uso uno

Digamos que tenemos un problema en el que los miembros de la Liga ya no ven los fondos de su cuenta de gastos de salud en su billetera digital y necesitamos solucionar el problema. ¿Cómo podemos proporcionar acceso limitado y parcial a los datos para que un ingeniero de datos pueda investigar sin comprometer la privacidad de los miembros?

Nuestra solución fácil: protección IAM a nivel de columna. Digamos que tenemos la tabla user_funds_allocation que contiene 6 campos:

Según el método Safe Harbor, si un ingeniero de datos solo pudiera acceder a los campos join_date y fund_allocated, no se identificaría a ningún miembro y la privacidad se mantendría intacta. Con esta información limitada, el ingeniero podría identificar que el campo de fondos asignados nulos está limitado a un rango específico de join_date, lo que los lleva a identificar un marco de tiempo para un error en el proceso de registro. Al permitir el acceso limitado y parcial a esta tabla a través de la exclusión de todos los campos de puerto seguro, le hemos dado a nuestro ingeniero suficientes datos para investigar mientras mantenemos a los miembros no identificables. Esta es nuestra primera línea de defensa: la seguridad de IAM de nivel de columna de Google Cloud en BigQuery, que restringe el acceso a los campos de PHI. En el Apéndice A se proporciona un ejemplo completo de implementación.

Caso de uso dos

Digamos que el problema en nuestro primer caso de uso se relaciona con un conjunto particular de miembros, y necesitamos más información sobre las políticas de sus empleadores para solucionar más problemas. La tabla user_funds_allocation ya no contiene suficiente información y necesitamos investigar otra tabla llamada user_employer_information.

El próximo paso lógico para nuestro ingeniero sería unir ambas tablas usando el campo user_id, para identificar información sobre la configuración del empleador para la asignación de fondos. Sin embargo, con el primer caso de uso, nuestro ingeniero no tiene acceso al campo user_id y es necesario explorar una nueva solución.

Aquí viene nuestra segunda línea de defensa: seguir brindando acceso limitado y parcial, pero de una manera diferente. La siguiente opción es permitir el acceso a un cifradoversión de user_id, para que aún podamos unir las tablas sin exponer ningún dato subyacente. El cifrado determinista a nivel de campo (FLE) se aplica a través del servicio de prevención de pérdida de datos (DLP) de Google Cloud, lo que nos permite seguir usando el campo sin acceder a su valor real. El DLP de Google Cloud también proporciona otras técnicas de desidentificación, como el cambio de fecha y la agrupación, útiles para los campos de fecha y número, como puede ver a continuación. Vale la pena mencionar que Google Cloud ya cifra los datos en reposo de forma predeterminada; esta solución de encriptación a nivel de campo agrega encriptación adicional encima, actuando como una capa adicional de protección.

En este caso de uso, no necesitamos saber la identificación del miembro específico, solo necesitamos poder vincularlo con la información de su empleador. Sin dejar de cumplir con la técnica de puerto seguro, podemos aplicar FLE a nuestro ID de usuario, nombre, apellido y almacenamiento hasta la fecha de nacimiento para que nuestro ingeniero pueda continuar investigando. Esto produciría las tablas a continuación.

Asignación_de_fondos_de_usuario_cifrado:

Información_del_empleador_del_usuario_encriptado:

Con estas dos tablas disponibles, los datos aún no son identificables para el ingeniero y pueden unir ambas tablas y continuar con su investigación. Ganar-ganar! El ejemplo completo de implementación se proporciona en el Apéndice B. Vale la pena señalar que hay advertencias para esta técnica, específicamente cuando los grupos de muestra son pequeños y están sujetos a una reidentificación razonablemente inferida; en esos casos, League modifica su enfoque para evitar la reidentificación.

¿Por qué necesitamos ambos métodos?

Ahora bien, si los dos enfoques descritos anteriormente brindan el mismo nivel de protección, pero el segundo (FLE) es más útil, ¿por qué no ceñirse únicamente a FLE? La respuesta simple: practicidad y el poder de múltiples capas de protección. El cifrado puede ser más costoso, más lento y más complejo que el control de acceso a nivel de columna, incluso cuando se realiza con un gran servicio como DLP. Al combinar ambos enfoques, podemos implementar un término medio manejable para toda la protección de datos y podemos aumentar nuestra experiencia de resolución de problemas para tablas específicas para las que a menudo se requiere. Esto conduciría a algo como esto:

Proteger la privacidad de los datos es una prioridad máxima y la seguridad de los datos no es una casilla de verificación binaria: es un proceso en constante evolución que requiere una comprensión profunda de las limitaciones técnicas y los requisitos de privacidad. En League, reevaluamos constantemente las formas de priorizar la privacidad, al mismo tiempo que mantenemos la facilidad de uso para poder brindar un servicio excepcional a nuestra base de miembros.

Apéndice A

Este apéndice repasa la implementación técnica de la seguridad a nivel de columna, como se describe en el caso de uso uno. Esta es una implementación simple a través de Data Catalog, BigQuery y la configuración de IAM de acuerdo con la introducción de seguridad a nivel de columna de Google . Pasos de alto nivel:

Crear etiquetas de taxonomía

  1. Ingrese la información de taxonomía y las etiquetas de política. En nuestro ejemplo, tenemos 3 categorías: PHI, Quasi_PHI (cualquier área gris o desconocida), Non_PHI
  2. Haz clic en Crear
  3. Seleccione la sección "Aplicar control de acceso" una vez creada
  1. Determine a qué columnas de su tabla desea aplicar la política. En el ejemplo 1 anterior, tenemos una tabla con ID de usuario, nombre, apellido, fecha de nacimiento, fondos asignados y fecha de ingreso. El nombre del conjunto de datos/tabla es SampleDataset.user_funds_allocation. Aplicaríamos la etiqueta "PHI" a user_id, first_name, last_name y birth_date.
  2. Al consultar la tabla, podemos ver todos los datos:

Actualice el esquema para usar etiquetas de políticas siguiendo los pasos descritos en el ejemplo de Google aquí .

  1. Obtenga el nombre completo de su etiqueta de política para cada etiqueta que desee aplicar. Puede hacerlo seleccionando el icono del portapapeles junto a la identificación de la etiqueta en la página de taxonomía (primera sección).
  2. Aplique las etiquetas a su tabla de BigQuery según los pasos del código a continuación, en la línea de comandos.
  3. # export existing schema
    bq show --schema --format=prettyjson \
       PROJECT:SampleDataset.user_funds_allocation > schema.json
    # edit the schema to include the "policyTag" section as per below.
    nano schema.json
    [
      {
        "mode": "NULLABLE",
        "name": "user_id",
        "type": "STRING",
        "policyTags": {
         "names": ["projects/PROJECT/locations/LOCATION/taxonomies/TAXONOMY_ID/policyTags/POLICY_ID"]
       }
      },
      {
        "mode": "NULLABLE",
        "name": "first_name",
        "type": "STRING",
        "policyTags": {
         "names": ["projects/PROJECT/locations/location/taxonomies/TAXONOMY_ID/policyTags/POLICY_ID"]
      },
      {
        "mode": "NULLABLE",
        "name": "last_name",
        "type": "STRING",
        "policyTags": {
         "names": ["projects/PROJECT/locations/LOCATION/taxonomies/TAXONOMY_ID/policyTags/POLICY_ID"]
      },
      {
        "mode": "NULLABLE",
        "name": "birth_date",
        "type": "DATE",
        "policyTags": {
         "names": ["projects/PROJECT/locations/LOCATION/taxonomies/TAXONOMY_ID/policyTags/POLICY_ID"]
      },
      {
        "mode": "NULLABLE",
        "name": "funds_allocated",
        "type": "FLOAT"
      },
      {
        "mode": "NULLABLE",
        "name": "join_date",
        "type": "DATE"
      }
    ]
    # update the schema with the new tag values
    bq update PROJECT:SampleDataset.user_funds_allocation schema.json
    

Con el acceso parcial actual, puedo obtener una vista previa de los campos a los que tengo acceso en la tabla (funds_allocated y join_date).

apéndice B

Este apéndice repasa la implementación técnica del cifrado a nivel de campo, como se describe en el caso de uso dos. Se logra mediante la creación de un trabajo de flujo de datos que encripta ciertos campos de acuerdo con una configuración de plantilla de desidentificación en Google Data Loss Protection (DLP). El código utilizado para configurar las claves de cifrado está en python.

El siguiente diagrama muestra la infraestructura general que implementa este apéndice.

Los pasos a continuación configuran su canalización según el diagrama anterior.

Creación de claves y cubos (pasos 1 y 2)

  • Establezca los parámetros de los artefactos que usará, según el bloque de código anterior (project_id, location_id, key_ring_name, key_name, bucket_name)
  • Cree el depósito que contendrá los datos que se desidentificarán ( fuente de Google ). Esta será la entrada para el trabajo de flujo de datos creado en un paso posterior. El siguiente código cubre este paso.
  • Cree las claves necesarias para el cifrado. El resto del fragmento de código anterior crea 2 claves: una clave de cifrado de datos (DEK) que se usa para cifrar los datos en sí y una clave de cifrado de clave (KEK) que se usa para cifrar el DEK para mayor seguridad. El KEK vive en Google KMS.
  • import google.api_core.exceptions
    from google.cloud import storage
    from google.cloud import kms
    import base64
    import secrets
    import time
    # set your parameters
    project_id = “your-gcp-project”
    location_id = “global”
    key_ring_name = “sample-key-ring”
    key_name = “sample-key
    bucket_name = “sample-de-id-bucket”
    
    # step 2; create bucket if needed
    try:
     storage_client = storage.Client()
     bucket = storage_client.bucket(bucket_name)
     new_bucket = storage_client.create_bucket(bucket, location=”us”)
    except google.api_core.exceptions.Conflict:
     # bucket already exists
     pass
    
    # step 3; create DEK & KEK keys
    client = kms.KeyManagementServiceClient()
    # create a key ring & resulting KEK (step 3a)
    location_name = f’projects/{project_id}/locations/{location_id}’
    key_ring = {}
    try:
     created_key_ring = client.create_key_ring(
     request={‘parent’: location_name, ‘key_ring_id’: key_ring_name, ‘key_ring’: key_ring})
     key_ring_full_name = created_key_ring.name
    except google.api_core.exceptions.AlreadyExists:
     # key ring already exists
     key_ring_full_name = f”projects/{project_id}/locations/{location_id}/keyRings/{key_ring_name}”
    purpose = kms.CryptoKey.CryptoKeyPurpose.ENCRYPT_DECRYPT
    algorithm = kms.CryptoKeyVersion.CryptoKeyVersionAlgorithm.GOOGLE_SYMMETRIC_ENCRYPTION
    key = {
     ‘purpose’: purpose,
     ‘version_template’: {
     ‘algorithm’: algorithm,
     },
     # Rotate the key every 90 days.
     ‘rotation_period’: {
     ‘seconds’: 60 * 60 * 24 * 90
     },
     ‘next_rotation_time’: {
     ‘seconds’: int(time.time()) + 60 * 60 * 24 * 90
     }
    }
    try:
     created_key = client.create_crypto_key(request={‘parent’: key_ring_full_name, ‘crypto_key_id’: key_name, ‘crypto_key’: key})
     kek_key_name = created_key.name
    except google.api_core.exceptions.AlreadyExists:
     kek_key_name = f”{key_ring_full_name}/cryptoKeys/{key_name}”
    # wrap the DEK with the KEK (step 3b)
    dek = secrets.token_bytes(16)
    kms_client = kms.KeyManagementServiceClient()
    wrapped_dek = kms_client.encrypt(
     request={‘name’: kek_key_name, ‘plaintext’: base64.b64encode(dek)}
    )
    wrapped_dek_encoded = base64.b64encode(wrapped_dek.ciphertext)
    # print the info you need for the next steps!
    print(“\nHere is some info for the DLP Template in step 4: “)
    print(f”The Resource Location: {location_id}”)
    print(f”The Crypto Resource name: {kek_key_name}”)
    print(f”The wrapped key (between quotes): {wrapped_dek_encoded}”)
    

  • Vaya a GCP > Prevención de pérdida de datos > Configuración > Crear plantilla Tipo de plantilla: anular la identificación
    Tipo de transformación de datos: registro
    Ubicación del recurso: global (a menos que haya otros requisitos)
  • Haga clic en continuar. Seleccione la configuración para Desidentificación: Cada regla de transformación se puede aplicar a 1 o más campos. En nuestro ejemplo, encriptaremos user_id, first_name, last_name a través de encriptación determinista y cambiaremos la fecha para birth_date. Como resultado, tendremos 2 reglas de transformación.
  • Configuración para cada regla:
    Campo(s) o columna(s) para transformar: ID_usuario, nombre, apellido
    Tipo de transformación: Transformación de campo primitivo
    Método de transformación: Pseudonimizar (token criptográfico determinista)
    Opciones de clave: Clave criptográfica envuelta en KMS. Establezca el nombre del recurso de clave criptográfica y la clave envuelta creada en la sección Creación de clave.
  • Ejemplo de regla de transformación para user_id, first_name y last_name
  • Vaya a GCP > Flujo de datos > Crear trabajo a partir de plantilla, en el proyecto en el que desea crear el trabajo. Asígnele el nombre correspondiente y seleccione la plantilla "Enmascaramiento de datos/Tokenización de Cloud Storage a BigQuery (usando Cloud DLP)".
  • Complete la sección de parámetros requeridos:
    Ingrese los archivos de almacenamiento en la nube: nombre del depósito que creó en el paso 1, junto con el patrón de coincidencia de archivos que desea que siga.
    Conjunto de datos de BigQuery: el conjunto de datos de destino donde aterrizarán los datos no identificados (cifrados).
    ID de proyecto de Cloud DLP: es el proyecto en el que desea que se ejecute la parte de DLP bajo
    Google Nombre de la plantilla de DLP: es el nombre de la plantilla creada en el paso 3
    Ubicación temporal: ubicación de los archivos temporales de su trabajo de flujo de datos
  • Ejemplo de configuración de trabajo de flujo de datos

En esta etapa, se anulará la identificación de todos los datos agregados al depósito que creó en el paso 1 según la plantilla especificada en el paso 3, a través del trabajo de flujo de datos creado en el paso 4. Para anular la identificación sistemática de las tablas de BigQuery existentes, debemos cierre el ciclo creando una exportación desde la tabla al depósito de GCS de origen del paso 1. La siguiente secuencia de comandos se puede automatizar según sea necesario, o el trabajo de flujo de datos se puede editar para leer directamente desde BigQuery en lugar de un depósito de GCS. Fuente de Google aquí

from google.cloud import bigquery
client = bigquery.Client()
bucket_name = "sample-de-id-bucket"
project = "PROJECT"
dataset_id = "SOURCE_DATASET"
table_id = "SOURCE_TABLE"

destination_uri = "gs://{}/{}".format(bucket_name, "shakespeare.csv")
dataset_ref = bigquery.DatasetReference(project, dataset_id)
table_ref = dataset_ref.table(table_id)

extract_job = client.extract_table(
    table_ref,
    destination_uri,
    # Location must match that of the source table.
    location="US",
)  # API request
extract_job.result()

© Copyright 2021 - 2022 | unogogo.com | All Rights Reserved