データが列形式で保管されている場合は、Parquet モジュラー暗号化を使用して、Parquet ファイルの書き込み時に機密列を暗号化し、暗号化されたファイルの読み取り時にこれらの列を復号することができます。 列レベルでデータを暗号化すると、どの列を暗号化するか、および列アクセスを制御する方法を決定できます。
Parquet モジュラー暗号化は、機密の確保だけでなく、保管データの整合性も保護します。 ファイル内容の改ざんが検出されると、リーダー側の例外がトリガーされます。
主要機能は以下のとおりです:
Parquet モジュラー暗号化および復号は、Spark クラスターで実行されます。 したがって、機密データと暗号鍵は、ストレージには見えません。
Parquet モジュラー暗号化形式のファイルにも、エンコード、圧縮、列の射影、述部プッシュダウンなどの標準の Parquet 機能を通常どおり使用できます。
Parquet 仕様に規定されている 2 つの暗号化アルゴリズムから選択することができます。 どちらのアルゴリズムも、列の暗号化をサポートします。ただし、次の点に注意してください。
- デフォルトのアルゴリズム
AES-GCM
は、Parquet ファイルのデータ部分とメタデータ部分に対する全体的な改ざん防止を提供します。 - もう一方のアルゴリズム
AES-GCM-CTR
は、Parquet ファイルの整合性を部分的に保護します。 改ざんが防止されるのはメタデータ部分のみで、データ部分は防止されません。 このアルゴリズムの利点は、スループットのオーバーヘッドがAES-GCM
アルゴリズムよりも低いことです。
- デフォルトのアルゴリズム
暗号化する列を選択できます。 その他の列は暗号化されないため、スループットのオーバーヘッドが削減されます。
列ごとに別の鍵で暗号化することができます。
デフォルトでは、メインの Parquet メタデータ・モジュール (ファイルのフッター) は、ファイルのスキーマおよび機密列のリストを隠すために暗号化されます。 ただし、レガシー・リーダー (Parquet モジュラー暗号化をまだサポートしていない他の Spark ディストリビューションなど) が暗号化ファイル内の暗号化されていない列を読み取れるようにするために、ファイル・フッターを暗号化しないことを選択できます。
暗号鍵は、次の 2 つの方法のいずれかで管理できます。
- アプリケーションで直接行います。 アプリケーションによる鍵の管理を参照してください。
- Spark サービスによって使用される暗号鍵を生成、保管、および破棄する鍵管理システム (KMS) を使用する。 これらの鍵は KMS サーバーから送信されることがないため、Spark サービスなどの他のコンポーネントからは不可視です。 KMS による鍵管理を参照してください。
注: アプリケーションまたは KMS によって管理する必要があるのは、マスター暗号鍵 (MEK) のみです。
機密列ごとに、暗号化に使用するマスター鍵を指定する必要があります。 また、暗号化される各ファイル (データ・フレーム) のフッターにもマスター鍵を指定する必要があります。 デフォルトでは、そのフッター鍵はフッターの暗号化に使用されます。 ただし、プレーン・テキストのフッター・モードを選択した場合は、フッターは暗号化されないので、鍵はフッターの整合性検査にのみ使用されます。
標準の Spark Hadoop 構成を使用して暗号化パラメーターを渡すことができます。例えば、次のようにアプリケーションの SparkContext の Hadoop 構成に構成値を設定できます。
sc.hadoopConfiguration.set("<parameter name>" , "<parameter value>")
また、書き込みオプションを使用してパラメーター値を渡すこともできます。
<data frame name>.write .option("<parameter name>" , "<parameter value>") .parquet("<write path>")
Parquet モジュラー暗号化を使用した実行
Parquet モジュラー暗号化を使用できるのは、IBM Analytics Engine サービス・インスタンス内で実行されている Spark ノートブックのみです。 Parquet モジュラー暗号化は、Spark 環境で実行されているノートブックではサポートされません。
Parquet モジュラー暗号化を有効にするには、Parquet モジュラー暗号化を実装する Parquet jar ファイルと鍵管理 jar ファイルを指すように、次の Spark クラスパス・プロパティーを設定します。
「Ambari」>「Spark」>「Config」->「Custom spark2-default」にナビゲートします。
JAR ファイルの場所を明示的に指す次の 2 つのパラメーターを追加します。 パスは、クラスターの実際のバージョンの jar ファイルを使用するように編集してください。
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
必須パラメーター
暗号化データを書き込むには、以下のパラメーターが必要です。
マスター暗号鍵を伴う、暗号化する列のリスト。
parameter name: "encryption.column.keys" parameter value: "<master key ID>:<column>,<column>;<master key ID>:<column>,.."
フッター鍵:
parameter name: "encryption.footer.key" parameter value: "<master key ID>"
例:
dataFrame.write .option("encryption.footer.key" , "k1") .option("encryption.column.keys" , "k2:SSN,Address;k3:CreditCard") .parquet("<path to encrypted files>")
重要:encryption.column.keys
パラメーターもencryption.footer.key
パラメーターも設定されていない場合、ファイルは暗号化されません。 これらのパラメーターは暗号化されたファイルに必須であるため、これらのパラメーターのいずれか 1 つのみが設定されている場合、例外がスローされます。
オプション・パラメーター
暗号化データを書き込むときに、次のオプション・パラメーターを使用できます。
暗号化アルゴリズム
AES-GCM-CTR
デフォルトでは、Parquet モジュラー暗号化は、Parquet ファイルのデータおよびメタデータの改ざんに対する完全な保護を提供する
AES-GCM
アルゴリズムを使用します。 しかし、Spark 2.3.0 は、(Java 9 で初めて追加された) CPU ハードウェアの AES アクセラレーションをサポートしない Java 8 で実行されるので、状況によっては、データの整合性検査のオーバーヘッドがワークロードのスループットに影響を及ぼす可能性があります。これを補うために、データの整合性検査のサポートをオフに切り替え、代替アルゴリズム
AES-GCM-CTR
を使用して、暗号化されたファイルを書き込むことができます。このアルゴリズムは、メタデータ部分の整合性のみを検査してデータ部分の整合性は検査しないので、AES-GCM
アルゴリズムよりもスループット・オーバーヘッドが低くなります。parameter name: "encryption.algorithm" parameter value: "AES_GCM_CTR_V1"
レガシー・リーダー向けのプレーン・テキスト・フッター・モード
デフォルトでは、メインの Parquet メタデータ・モジュール (ファイルのフッター) は、ファイルのスキーマおよび機密列のリストを隠すために暗号化されます。 ただし、他の Spark リーダーおよび Parquet リーダー (Parquet モジュラー暗号化をまだサポートしていない) が暗号化ファイル内の暗号化されていない列を読み取れるようにするために、ファイル・フッターを暗号化しないことを決定できます。 フッター暗号化をオフにするには、次のパラメーターを設定します。
parameter name: "encryption.plaintext.footer" parameter value: "true"
重要:encryption.footer.key
パラメーターは、プレーン・テキスト・フッター・モードでも指定する必要があります。 フッターは暗号化されませんが、フッターの内容に署名するために鍵が使用されます。つまり、新しいリーダーはその整合性を検証できます。 レガシー・リーダーは、フッター・シグニチャーの追加による影響を受けません。
使用例
以下の Python のサンプル・コード・スニペットは、データ・フレームの作成方法、暗号化された Parquet ファイルへの書き込み方法、および暗号化された Parquet ファイルからの読み取り方法を示しています。
Python: 暗号化データの書き込み:
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: 暗号化データの読み取り:
sc._jsc.hadoopConfiguration().set("encryption.key.list", "key1: AAECAwQFBgcICQoLDA0ODw==, key2: AAECAAECAAECAAECAAECAA==") encryptedParquetPath = "squares.parquet.encrypted" parquetFile = spark.read.parquet(encryptedParquetPath) parquetFile.show()
Python ジョブ・ファイル InMemoryKMS.py
の内容は、以下のとおりです。
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()
暗号鍵の処理の内部詳細
Parquet ファイルを書き込むときには、暗号化される各列およびフッターに対してランダムなデータ暗号鍵 (DEK) が生成されます。 それらの鍵を使用して、Parquet ファイルのデータ・モジュールおよびメタデータ・モジュールが暗号化されます。
その後、データ暗号鍵が、鍵暗号鍵 (KEK) を使用して暗号化されます。この KEK も、マスター鍵ごとに Spark/Parquet の内部で生成されるものです。 鍵暗号鍵は、マスター暗号鍵 (MEK) を使用してローカルで暗号化されます。
暗号化されたデータ暗号鍵と鍵暗号鍵が、マスター鍵 ID と一緒に Parquet ファイルのメタデータに保管されます。 各鍵暗号鍵には固有の ID (セキュアでランダムな 16 バイトの値としてローカルに生成されます) があり、これもファイルのメタデータに保管されます。
Parquet ファイルを読み取るときには、マスター暗号鍵 (MEK)、暗号化された鍵暗号鍵 (KEK) とその ID、および暗号化されたデータ暗号鍵 (DEK) が、ファイルのメタデータから抽出されます。
鍵暗号鍵が、マスター暗号鍵を使用してローカルで復号されます。 次に、データ暗号鍵 (DEK) が、鍵暗号鍵 (KEK) を使用してローカルで復号されます。