Criptografia modular em Parquet
Se seus dados forem armazenados no formato colunar, será possível usar a criptografia modular de Parquet para criptografar colunas sensíveis ao gravar arquivos Parquet e decriptografar essas colunas ao ler os arquivos criptografados. Criptografar dados no nível da coluna possibilita que você decida quais colunas criptografar e como controlar o acesso da coluna.
Além de assegurar a privacidade, a criptografia modular do Parquet também protege a integridade dos dados armazenados. Qualquer violação no conteúdo de arquivo é detectada e aciona uma exceção do lado do leitor.
Os principais recursos incluem:
A criptografia e a decriptografia modulares do Parquet são executadas no cluster do Spark. Portanto, dados sensíveis e as chaves de criptografia não são visíveis para o armazenamento.
Os recursos de Parquet padrão, como codificação, compactação, projeção colunar e push-down do predicado, continuam a funcionar como de costume em arquivos com formato de criptografia modular de Parquet.
É possível escolher um dos dois algoritmos de criptografia que são definidos na especificação de Parquet. Ambos os algoritmos suportam a criptografia de coluna, no entanto:
- O algoritmo padrão
AES-GCMfornece proteção total contra a violação de dados e partes de metadados em arquivos Parquet. - O algoritmo alternativo
AES-GCM-CTRsuporta a proteção de integridade parcial de arquivos Parquet. Apenas as partes de metadados são protegidas contra violação, não partes de dados. Uma vantagem desse algoritmo é que ele tem uma sobrecarga de rendimento inferior em comparação com o algoritmoAES-GCM.
- O algoritmo padrão
É possível escolher quais colunas 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 principal módulo de metadados do Parquet (o rodapé do arquivo) é criptografado para ocultar o esquema do arquivo e a lista de colunas sensíveis. No entanto, pode-se optar por não criptografar os rodapés do arquivo a fim de permitir leitores legados (como outras distribuições Spark que ainda não suportam a criptografia modular do Parquet) para ler as colunas não criptografadas nos arquivos criptografados.
As chaves de criptografia podem ser gerenciadas de uma das duas maneiras:
- Diretamente por seu aplicativo. Consulte Gerenciamento de chaves por aplicativo.
- Por um sistema de gerenciamento de chaves (KMS) que gera, armazena e destrói chaves de criptografia usadas pelo serviço Spark. Essas chaves nunca deixam o servidor KMS e, portanto, são invisíveis para outros componentes, incluindo o serviço Spark. Consulte Gerenciamento de chaves por KMS.
Observação: seu aplicativo ou KMS deve gerenciar apenas chaves mestras de criptografia.Para cada coluna sensível, deve-se especificar qual chave mestra usar para criptografia. Além disso, uma chave mestra deve ser especificada para o rodapé de cada arquivo criptografado (quadro de dados). Por padrão, a chave de rodapé será usada para criptografia de rodapé. No entanto, se você escolher um modo de rodapé de texto sem formatação, o rodapé não será criptografado e a chave será usada apenas para verificação de integridade do rodapé.
Os parâmetros de criptografia podem ser passados pela configuração padrão do Spark Hadoop, por exemplo, definindo os valores de configuração na configuração do Hadoop do SparkContext do aplicativo:
sc.hadoopConfiguration.set("<parameter name>" , "<parameter value>")Como alternativa, é possível transmitir valores de parâmetro por meio de opções de gravação:
<data frame name>.write .option("<parameter name>" , "<parameter value>") .parquet("<write path>")
Executando com criptografia modular do Parquet
A criptografia modular do Parquet está disponível apenas em blocos de notas Spark que são executados em uma instância de serviço do IBM Analytics Engine. A criptografia modular do Parquet não é compatível com blocos de notas executados em um ambiente Spark.
Para ativar a criptografia modular do Parquet, configure as propriedades a seguir do caminho de classe do Spark para apontar para os arquivos jar do Parquet que implementam a criptografia modular do Parquet e para o arquivo jar de gerenciamento de chave:
Navegue até Ambari > Spark > Configuração -> spark2-default customizado.
Inclua os dois parâmetros a seguir para apontar explicitamente para a localização dos arquivos JAR. Certifique-se de editar os caminhos para usar a versão real de arquivos jar no cluster.
spark.driver.extraClassPath=/home/common/lib/parquetEncryption/ibm-parquet-kms-<latestversion>-jar-with-dependencies.jar:/home/common/lib/parquetEncryption/parquet-format-<latestversion>.jar:/home/common/lib/parquetEncryption/parquet-hadoop-<latestversion>.jar spark.executor.extraClassPath=/home/common/lib/parquetEncryption/ibm-parquet-<latestversion>-jar-with-dependencies.jar:/home/common/lib/parquetEncryption/parquet-format-<latestversion>.jar:/home/common/lib/parquetEncryption/parquet-hadoop-<latestversion>.jar
Parâmetros obrigatórios
Os parâmetros a seguir 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 de 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 configurado, uma exceção será lançada, pois esses parâmetros são obrigatórios para arquivos criptografados.
Parâmetros opcionais
Os parâmetros opcionais a seguir podem ser usados ao gravar dados criptografados:
O algoritmo de criptografia
AES-GCM-CTRPor padrão, a criptografia modular de Parquet utiliza o algoritmo
AES-GCMque fornece proteção integral contra a violação de dados e metadados em arquivos Parquet. No entanto, como o Spark 2.3.0 é executado em Java 8, que não suporta a aceleração de AES em hardware de CPU (isso foi incluído apenas no Java 9), a sobrecarga de verificação de integridade de dados pode afetar o rendimento da carga de trabalho em determinadas situações.Para compensar isso, é possível desativar o suporte de verificação de integridade de dados e gravar os arquivos criptografados com o algoritmo alternativo
AES-GCM-CTR, que verifica a integridade das partes de metadados apenas e não a das partes de dados e possui uma sobrecarga de rendimento inferior em comparação com o algoritmoAES-GCM.parameter name: "encryption.algorithm" parameter value: "AES_GCM_CTR_V1"Modo de rodapé de texto sem formatação para leitores anteriores
Por padrão, o principal módulo de metadados do Parquet (o rodapé do arquivo) é criptografado para ocultar o esquema do arquivo e a lista de colunas sensíveis. No entanto, pode-se decidir não criptografar os rodapés do arquivo a fim de permitir outros leitores Spark e Parquet (que ainda não suportam a criptografia modular do Parquet) para ler as colunas não criptografadas nos arquivos criptografados. Para desativar a criptografia de rodapé, configure o parâmetro a seguir:
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 seja criptografado, a chave é usada para assinar o conteúdo do rodapé, o que significa que novos leitores poderão verificar sua integridade. Os leitores anteriores não são afetados pela adição da assinatura de 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: gravando 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: lendo dados criptografados:
sc._jsc.hadoopConfiguration().set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==") encryptedParquetPath = "squares.parquet.encrypted" parquetFile = spark.read.parquet(encryptedParquetPath) parquetFile.show()
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()
Internos de manipulação de chaves de criptografia
Ao gravar um arquivo de Parquet, é gerada uma chave de criptografia de dados (DEK) aleatória para cada coluna criptografada e para o rodapé. Essas chaves são usadas para criptografar os dados e os módulos de metadados no arquivo Parquet.
A chave de criptografia de dados é criptografada com uma chave de criptografia chaves (KEK), também gerada dentro do Spark/Parquet para cada chave mestra. A chave de criptografia de chaves é criptografada com uma chave mestra de criptografia (MEK) localmente.
As chaves de criptografia de dados criptografados e as chaves de criptografia de chaves são armazenadas nos metadados de arquivo do Parquet, juntamente com a identidade de chave mestra. Cada chave de criptografia de chaves tem uma identidade única (gerada localmente como um valor aleatório de 16 bytes seguro), também armazenada nos metadados do arquivo.
Ao ler um arquivo de Parquet, o identificador da chave mestra de criptografia (MEK), a chave de criptografia de chaves (KEK) criptografada com seu identificador e a chave de criptografia de dados (DEK) criptografada são extraídos dos metadados do arquivo.
A chave de criptografia de chaves é decriptografada com a chave mestra de criptografia localmente. Em seguida, a chave de criptografia de dados (DEK) é decriptografada localmente, usando a chave de criptografia de chaves (KEK).