Criptografia modular Parquet
Se seus dados estiverem armazenados em formato colunar, você pode usar a criptografia modular do Parquet para criptografar colunas confidenciais ao gravar arquivos Parquet e descriptografar essas colunas ao ler os arquivos criptografados. A criptografia de dados no nível da coluna permite que você decida quais colunas criptografar e como controlar o acesso a elas.
Além de garantir a privacidade, a criptografia modular do Parquet também protege a integridade dos dados armazenados. Qualquer alteração no conteúdo do arquivo é detectada e gera uma exceção no lado do leitor.
As principais características incluem:
A criptografia e a descriptografia modulares do Parquet são realizadas no cluster do Spark. Portanto, os dados confidenciais e as chaves de criptografia não ficam visíveis para o sistema de armazenamento.
Os recursos padrão do Parquet, como codificação, compactação, projeção colunar e push-down de predicados, continuam funcionando normalmente em arquivos com o formato de criptografia modular do Parquet.
Você pode escolher um dos dois algoritmos de criptografia definidos na especificação do Parquet. No entanto, ambos os algoritmos suportam criptografia por coluna:
- O algoritmo padrão
AES-GCMoferece proteção total contra a adulteração de dados e metadados em arquivos Parquet. - O algoritmo alternativo
AES-GCM-CTRoferece proteção parcial da integridade dos arquivos Parquet. Apenas as partes de metadados estão protegidas contra adulterações, não as partes de dados. Uma vantagem desse algoritmo é que ele apresenta uma menor sobrecarga de throughput em comparação com oAES-GCMalgoritmo.
- O algoritmo padrão
Você pode escolher quais colunas deseja criptografar. Outras colunas não serão criptografadas, reduzindo o sobrecarte de rendimento.
Colunas diferentes podem ser criptografadas com chaves diferentes.
Por padrão, o módulo principal de metadados do Parquet (o rodapé do arquivo) é criptografado para ocultar o esquema do arquivo e a lista de colunas confidenciais. No entanto, você pode optar por não criptografar os rodapés dos arquivos para permitir que leitores mais antigos (como outras distribuições do Spark que ainda não suportam a criptografia modular do Parquet) leiam as colunas não criptografadas nos arquivos criptografados.
As chaves de criptografia podem ser gerenciadas de duas maneiras:
- Diretamente pelo seu aplicativo. Consulte “Gerenciamento de chaves por aplicativo ”.
- Por um sistema de gerenciamento de chaves (KMS) que gera, armazena e destrói as chaves de criptografia utilizadas pelo serviço Spark. Essas chaves nunca saem do servidor KMS e, portanto, são invisíveis para outros componentes, incluindo o serviço Spark. Consulte a gestão de chaves pelo KMS.
Observação: seu aplicativo ou KMS deve gerenciar apenas chaves de criptografia mestre.Para cada coluna confidencial, é necessário especificar qual chave mestra deve ser usada para a criptografia. Além disso, é necessário especificar uma chave mestra para o rodapé de cada arquivo criptografado (quadro de dados). Por padrão, a chave de rodapé será usada para a criptografia do rodapé. No entanto, se você escolher o modo de rodapé em texto simples, o rodapé não será criptografado, e a chave será usada apenas para verificar a integridade do rodapé.
Os parâmetros de criptografia podem ser passados por meio da configuração padrão do Spark Hadoop, por exemplo, definindo valores de configuração no arquivo Hadoop do arquivo de configuração SparkContext: da aplicação
sc.hadoopConfiguration.set("<parameter name>" , "<parameter value>")Como alternativa, você pode passar os valores dos parâmetros por meio das opções de gravação:
<data frame name>.write .option("<parameter name>" , "<parameter value>") .parquet("<write path>")
Parâmetros obrigatórios
Os seguintes parâmetros são necessários para gravar dados criptografados:
Lista de colunas a serem criptografadas, com as chaves mestras de criptografia:
parameter name: "encryption.column.keys" parameter value: "<master key ID>:<column>,<column>;<master key ID>:<column>,.."A chave do rodapé:
parameter name: "encryption.footer.key" parameter value: "<master key ID>"Por exemplo:
dataFrame.write .option("encryption.footer.key" , "k1") .option("encryption.column.keys" , "k2:SSN,Address;k3:CreditCard") .parquet("<path to encrypted files>")Importante:Se nem o parâmetro
encryption.column.keys, nem o parâmetroencryption.footer.keyfor configurado, o arquivo não será criptografado Se apenas um desses parâmetros for definido, será lançada uma exceção, pois esses parâmetros são obrigatórios para arquivos criptografados.
Parâmetros opcionais
Os seguintes parâmetros opcionais podem ser usados ao gravar dados criptografados:
O algoritmo de criptografia
AES-GCM-CTRPor padrão, a criptografia modular do Parquet utiliza o
AES-GCMalgoritmo que oferece proteção total contra a adulteração de dados e metadados nos arquivos Parquet. No entanto, como o Spark 2.3.0 é executado no Java 8, que não oferece suporte à aceleração AES no hardware da CPU (essa funcionalidade só foi adicionada no Java 9), a sobrecarga da verificação da integridade dos dados pode afetar a taxa de processamento da carga de trabalho em determinadas situações.Para compensar isso, você pode desativar o suporte à verificação de integridade de dados e gravar os arquivos criptografados com o algoritmo alternativo
AES-GCM-CTR, que verifica apenas a integridade das partes de metadados e não a das partes de dados, e apresenta uma sobrecarga de throughput menor em comparação com oAES-GCMalgoritmo.parameter name: "encryption.algorithm" parameter value: "AES_GCM_CTR_V1"Modo de rodapé em texto simples para leitores mais antigos
Por padrão, o módulo principal de metadados do Parquet (o rodapé do arquivo) é criptografado para ocultar o esquema do arquivo e a lista de colunas confidenciais. No entanto, você pode optar por não criptografar os rodapés dos arquivos para permitir que outros leitores do Spark e do Parquet (que ainda não suportam a criptografia modular do Parquet) leiam as colunas não criptografadas nos arquivos criptografados. Para desativar a criptografia do rodapé, defina o seguinte parâmetro:
parameter name: "encryption.plaintext.footer" parameter value: "true"Importante:O parâmetro
encryption.footer.keytambém deve ser especificado no modo de rodapé de texto simples. Embora o rodapé não esteja criptografado, a chave é usada para assinar o conteúdo do rodapé, o que significa que novos leitores podem verificar sua integridade. Os leitores da versão anterior não são afetados pela adição da assinatura no rodapé.
Exemplos de uso
Os fragmentos de código de amostra a seguir para Python mostram como criar quadros de dados, gravados em arquivos parquet criptografados e lidos a partir de arquivos parquet criptografados.
Python : Gravação de dados criptografados:
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 : Leitura de dados criptografados:
sc._jsc.hadoopConfiguration().set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==") encryptedParquetPath = "squares.parquet.encrypted" parquetFile = spark.read.parquet(encryptedParquetPath) parquetFile.show()
Exemplo de envio de um trabalho do Spark que utiliza criptografia modular do Parquet
O exemplo a seguir mostra como enviar um trabalho do Spark que utiliza criptografia modular do Parquet para a instância do Spark. O exemplo faz uso de modelos padrão do Spark para enviar a tarefa do spark Python do arquivo InMemoryKMS.py. Este exemplo pressupõe que este arquivo está presente em um volume de zen::kms-volume armazenamento no diretório raiz.
{
"application_details": {
"application": "/kms-app/kms.py",
"conf": {
"ae.spark.executor.count": 2,
"spark.driver.memory": "4G",
"spark.executor.memory": "4G"
}
},
"volumes": [
{
"name": "zen::kms-volume",
"mount_path": "/kms-app"
}
]
}
O conteúdo do arquivo de tarefa Python InMemoryKMS.py é o seguinte:
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()
Detalhes do gerenciamento de chaves de criptografia
Ao gravar um arquivo Parquet, é gerada uma chave de criptografia de dados aleatória (DEK) para cada coluna criptografada e para o rodapé. Essas chaves são usadas para criptografar os módulos de dados e metadados no arquivo Parquet.
A chave de criptografia de dados é então criptografada com uma chave de criptografia de chave (KEK), também gerada no Spark/Parquet para cada chave mestra. A chave de criptografia é criptografada localmente com uma chave mestra de criptografia (MEK).
As chaves de criptografia dos dados criptografados e as chaves de criptografia das chaves são armazenadas nos metadados do arquivo Parquet, juntamente com a identidade da chave mestra. Cada chave de criptografia possui uma identidade única (gerada localmente como um valor aleatório seguro de 16 bytes), também armazenada nos metadados do arquivo.
Ao ler um arquivo Parquet, o identificador da chave mestra de criptografia (MEK), a chave de criptografia da chave (KEK) com seu identificador e a chave de criptografia dos dados (DEK) são extraídos dos metadados do arquivo.
A chave de criptografia é descriptografada localmente com a chave mestra de criptografia. Em seguida, a chave de criptografia de dados (DEK) é descriptografada localmente, utilizando a chave de criptografia de chaves (KEK).