Crittografia modulare di parquet
Se i tuoi dati vengono memorizzati in formato columnar, è possibile utilizzare la crittografia modulare Parquet per crittografare colonne sensibili durante la scrittura dei file di Parquet e decodificare queste colonne durante la lettura dei file crittografati. Crittografare i dati a livello di colonna, consente di decidere quali colonne crittografare e come controllare l'accesso alla colonna.
Oltre a garantire la privacy, la crittografia modulare Parquet protegge anche l'integrità dei dati memorizzati. Qualsiasi manomissione con contenuto di file viene rilevato e attiva un'eccezione del lato reader.
Le funzioni principali includono:
- La crittografia modulare e la decodifica viene eseguita sul cluster Spark. Pertanto, i dati sensibili e le chiavi di crittografia non sono visibili allo storage.
- Le funzioni di Parquet standard, come ad esempio la codifica, la compressione, la proiezione di columnar e il predicato push - down, continuano a funzionare come di consueto su file con formato di codifica modulare Parquet.
È possibile scegliere uno dei due algoritmi di codifica definiti nella specifica Parquet. Entrambi gli algoritmi supportano la crittografia delle colonne, tuttavia:
- L'algoritmo predefinito
AES-GCMfornisce una protezione completa contro la manomissione dei dati e delle parti dei metadati nei file di Parquet. - L'algoritmo alternativo
AES-GCM-CTRsupporta la protezione di integrità parziale dei file di Parquet. Solo le parti di metadati sono protette contro le manomissioni, non le parti di dati. Un vantaggio di questo algoritmo è che ha un sovraccarico di throughput inferiore rispetto all'algoritmoAES-GCM.
- L'algoritmo predefinito
- È possibile scegliere quali colonne crittografare. Altre colonne non verranno crittografate, riducendo la sovraccarica di throughput.
- Diverse colonne possono essere crittografate con diverse chiavi.
- Per impostazione predefinita, il modulo principale di metadati Parquet (il footer di file) è crittografato per nascondere lo schema di file e l'elenco delle colonne sensibili. Tuttavia, è possibile scegliere di non crittografare i footers del file al fine di abilitare i lettori legacy (come ad esempio altre distribuzioni Spark che non supportano ancora la crittografia modulare di Parquet) per leggere le colonne non crittografate nei file crittografati.
I tasti di crittografia possono essere gestiti in uno dei due modi:
- Direttamente dalla tua applicazione. Consultare Gestione chiave per applicazione.
Tramite un sistema di gestione chiavi (KMS) che genera, memorizza e distrugge i tasti di crittografia utilizzati dal servizio Spark. Queste chiavi non lasciano mai il server KMS e quindi sono invisibili ad altri componenti, tra cui il servizio Spark. Consultare Gestione chiave da parte di KMS.
Nota: Solo i tasti di crittografia master (MEKs) devono essere gestiti dalla propria applicazione o da un KMS.
Per ogni colonna sensibile è necessario specificare quale chiave principale utilizzare per la crittografia. Inoltre, deve essere specificato un tasto master per il piè di pagina di ogni file crittografato (frame frame). Per impostazione predefinita, la chiave di piè di pagina verrà utilizzata per la crittografia a piè di pagina. Tuttavia, se si sceglie una modalità di testo semplice, il piè di pagina non verrà crittografato e la chiave verrà utilizzata solo per la verifica dell'integrità del piè di pagina.
I parametri di crittografia possono essere passati tramite la configurazione standard Spark Hadoop , ad esempio impostando i valori di configurazione nella configurazione Hadoop dello SparkContext dell'applicazione:
sc.hadoopConfiguration.set("<parameter name>" , "<parameter value>")In alternativa, è possibile passare i valori dei parametri attraverso le opzioni di scrittura:
<data frame name>.write .option("<parameter name>" , "<parameter value>") .parquet("<write path>")
Parametri obbligatori
Per la scrittura dei dati crittografati sono richiesti i seguenti parametri:
- Elenco delle colonne da crittografare, con le chiavi di codifica master:
parameter name: "encryption.column.keys" parameter value: "<master key ID>:<column>,<column>;<master key ID>:<column>,.." La chiave di piè di pagina:
parameter name: "encryption.footer.key" parameter value: "<master key ID>"Ad esempio:
dataFrame.write .option("encryption.footer.key" , "k1") .option("encryption.column.keys" , "k2:SSN,Address;k3:CreditCard") .parquet("<path to encrypted files>")Importante: se non è impostato né il parametro
"encryption.column.keys"né il parametro"encryption.footer.key", il file non verrà crittografato. Se solo uno di questi parametri è impostato, viene lanciata un'eccezione, perché questi parametri sono obbligatori per i file crittografati.
Parametri facoltativi
I seguenti parametri opzionali possono essere utilizzati quando si scrivono dati crittografati:
L'algoritmo di codifica
AES-GCM-CTRPer impostazione predefinita, la crittografia modulare Parquet utilizza l'algoritmo
AES-GCMche fornisce una protezione completa contro la manomissione dei dati e dei metadati nei file di Parquet. Tuttavia, poiché Spark 2.3.0 corre su Java 8, che non supporta l'accelerazione AES nell'hardware della CPU (questo è stato aggiunto solo in Java 9), il sovraccarico della verifica dell'integrità dei dati può influenzare la velocità di trasmissione del carico di lavoro in determinate situazioni.Per compensare questo, è possibile disattivare il supporto di verifica dell'integrità dei dati e scrivere i file crittografati con l'algoritmo alternativo
AES-GCM-CTR, che verifica l'integrità delle parti di metadati solo e non quella delle parti di dati, e ha un sovraccarico di throughput inferiore rispetto all'algoritmoAES-GCM.parameter name: "encryption.algorithm" parameter value: "AES_GCM_CTR_V1"Modalità di piè di testo semplice per i lettori legacy
Per impostazione predefinita, il modulo principale di metadati Parquet (il footer di file) è crittografato per nascondere lo schema di file e l'elenco delle colonne sensibili. Tuttavia, è possibile decidere di non crittografare i fari di file al fine di abilitare altri lettori di Spark e Parquet (che non supportano ancora la crittografia modulare di Parquet) per leggere le colonne non crittografate nei file crittografati. Per commutare la crittografia del footer, impostare il seguente parametro:
parameter name: "encryption.plaintext.footer" parameter value: "true"Importante: il parametro
"encryption.footer.key"deve essere specificato anche nella modalità di piè di testo semplice. Anche se il piè di pagina non è criptato, la chiave è utilizzata per firmare il contenuto di piè di pagina, il che significa che i nuovi lettori potrebbero verificarne l'integrità. I lettori legacy non sono interessati dall'aggiunta della firma del piè di pagina.
Esempi di utilizzo
I seguenti snippet code di esempio per Python e Scala mostrano come creare frame di dati, scritti in file di parquet crittografati e letti da file di parquet crittografati.
Python: Scrittura dei dati crittografati:
from pyspark.sql import Row squaresDF = spark.createDataFrame( sc.parallelize(range(1, 6)) .map(lambda i: Row(int_column=i, square_int_column=i ** 2))) sc._jsc.hadoopConfiguration().set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==") sc._jsc.hadoopConfiguration().set("encryption.column.keys", "key1:square_int_column") sc._jsc.hadoopConfiguration().set("encryption.footer.key", "key2") encryptedParquetPath = "squares.parquet.encrypted" squaresDF.write.parquet(encryptedParquetPath)Python: Lettura dei dati crittografati:
sc._jsc.hadoopConfiguration().set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==") encryptedParquetPath = "squares.parquet.encrypted" parquetFile = spark.read.parquet(encryptedParquetPath) parquetFile.show()Scala: Scrittura dei dati crittografati:
case class SquareItem(int_column: Int, square_int_column: Double) val dataRange = (1 to 6).toList val squares = sc.parallelize( dataRange.map(i => new SquareItem(i, scala.math.pow(i,2)))) sc.hadoopConfiguration.set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==") sc.hadoopConfiguration.set("encryption.column.keys", "key1:square_int_column") sc.hadoopConfiguration.set("encryption.footer.key", "key2") val encryptedParquetPath = "squares.parquet.encrypted" squares.toDS().write.parquet(encryptedParquetPath)Scala: Reading dati crittografati:
sc.hadoopConfiguration.set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==") val encryptedParquetPath = "squares.parquet.encrypted" val parquetFile = spark.sqlContext.read.parquet(encryptedParquetPath) parquetFile.show()
Esempio di inoltro di un lavoro Spark che utilizza la crittografia modulare Parquet
Il seguente esempio mostra come inoltrare un lavoro Spark che utilizza la crittografia modulare di Parquet all'istanza di Spark. L'esempio include il modello personalizzato che specifica la versione Spark e le librerie di sistema preinstallate per la crittografia modulare Parquet, mostra come personalizzare le dimensioni hardware del cluster e aggiungere il percorso file al file di lavoro Scala InMemoryKMS.py.
Nota:
- Per la crittografia modulare Parquet e Spark 3,0 utilizzare il modello ID
spark-3.0.0-parquet-encryption-cp4d-template - Per la crittografia modulare Parquet e Spark 2,4 utilizzare il modello ID
spark-2.4.0-parquet-encryption-icp4d-template. Da notare che Spark 2,4 è stato rimosso in Cloud Pak for Data 4.0.7. È possibile utilizzare Spark 2,4 solo se si è su una versione Cloud Pak for Data prima del 4.0.7.
{
"engine": {
"type": "spark",
"template_id": "spark-3.0.0-parquet-encryption-cp4d-template",
"conf": {
"spark.app.name": "InMemoryKMS",
"spark.eventLog.enabled": "false"
},
"volumes": [{
"volume_name": "kms-volume",
"source_path": "KMS",
"mount_path": "/kms-app"
}],
"size": {
"num_workers": "2",
"worker_size": {
"cpu": 1,
"memory": "4g"
},
"driver_size": {
"cpu": 1,
"memory": "4g"
}
}
},
"application_arguments": [],
"application_jar": "/kms-app/InMemoryKMS.py",
"main_class": "org.apache.spark.deploy.SparkSubmit"
}
Il contenuto del file di lavoro Scala InMemoryKMS.py è il seguente:
from pyspark.sql import SparkSession
from pyspark import SparkContext
from pyspark.sql import Row
if __name__ == "__main__":
spark = SparkSession \
.builder \
.appName("InMemoryKMS") \
.getOrCreate()
sc = spark.sparkContext
##KMS operation
print("Setup InMemoryKMS")
hconf = sc._jsc.hadoopConfiguration()
encryptedParquetFullName = "testparquet.encrypted"
print("Write Encrypted Parquet file")
hconf.set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==")
btDF = spark.createDataFrame(sc.parallelize(range(1, 6)).map(lambda i: Row(ssn=i, value=i ** 2)))
btDF.write.mode("overwrite").option("encryption.column.keys", "key1:ssn").option("encryption.footer.key", "key2").parquet(encryptedParquetFullName)
print("Read Encrypted Parquet file")
encrDataDF = spark.read.parquet(encryptedParquetFullName)
encrDataDF.createOrReplaceTempView("bloodtests")
queryResult = spark.sql("SELECT ssn, value FROM bloodtests")
queryResult.show(10)
sc.stop()
spark.stop()
Interni di gestione delle chiavi di cifratura
Quando si scrive un file Parquet, viene generata una chiave di codifica dati casuale (DEK) per ogni colonna crittografata e per il piè di pagina. Questi tasti sono utilizzati per crittografare i dati e i moduli di metadati presenti nel file Parquet.
La chiave di codifica dei dati viene quindi crittografata con una chiave di crittografia chiave (KEK), generata anche all'interno di Spark / Parquet per ogni chiave principale. La chiave di crittografia chiave è crittografata con una chiave di codifica principale (MEK) localmente.
I tasti di crittografia dei dati crittografati e chiavi di crittografia chiave sono memorizzati nei metadati del file Parquet, insieme all'identità chiave principale. Ogni tasto di crittografia chiave ha un'identità unica (generata localmente come un valore casuale 16 - byte sicuro), memorizzata anche nei metadati del file.
Quando si legge un file di Parquet, l'identificativo della chiave di codifica principale (MEK) e il tasto crittografato della chiave crittografata (KEK) con il relativo identificativo e la chiave di codifica dei dati crittografati (DEK) vengono estratti dai metadati del file.
La chiave di crittografia chiave viene decodificata con la chiave di codifica master localmente. Poi la chiave di codifica dei dati (DEK) viene decodificata localmente, utilizzando la chiave di codifica chiave (KEK).
Ulteriori informazioni
Argomento principale: Librerie e script