AnalyticDB for MySQL の 常時秘匿コンピュートエンジンの高性能版は、Basic Edition の機能を基盤として構築されています。Parquet モジュラー暗号化機能をサポートし、コミュニティ版の Spark、Hadoop、Hive などのコンピュートエンジンと互換性があります。このエディションは、安全なデータ転送とストレージを保証し、データ処理効率を向上させます。このトピックでは、Apache Spark 常時秘匿コンピュートエンジンの高性能版を使用してデータを暗号化し、暗号文テーブルに対して SQL クエリを実行する方法について説明します。
前提条件
AnalyticDB for MySQL の Enterprise Edition、Basic Edition、または Data Lakehouse Edition のクラスターが作成されていること。
AnalyticDB for MySQL クラスターと同じリージョンに Object Storage Service (OSS) バケットが作成されていること。
AnalyticDB for MySQL クラスター用のデータベースアカウントが作成されていること。
Alibaba Cloud アカウントを使用する場合は、特権アカウントを作成するだけで済みます。
Resource Access Management (RAM) ユーザーを使用する場合は、特権アカウントと標準アカウントを作成し、標準アカウントを RAM ユーザーに関連付ける必要があります。
RAM ユーザーに、AliyunADBFullAccess、AliyunADBSparkProcessingDataRole、および AnalyticDB for MySQL のデータベースとテーブルに対する読み取り/書き込み権限が付与されていること。詳細については、「アカウントの権限付与」をご参照ください。
データ準備
暗号化するデータファイルは Parquet フォーマットである必要があります。以下の手順を完了するには、Spark Confidential Computing サンプルデータをダウンロードしてください。
操作手順
プレーンテキストデータは、AnalyticDB for MySQL コンソールで暗号化するか、暗号化ツールを使用して暗号化できます。暗号化したいデータがオンプレミスデバイスに保存されている場合は、暗号化ツールを使用してデータを暗号化できます。データがクラウドデータベースに保存されている場合は、AnalyticDB for MySQL コンソールでデータを暗号化できます。暗号化方法によって操作が異なります:
コンソールでのデータ暗号化:プレーンテキストデータを OSS にアップロードしてから暗号化します。
暗号化ツールを使用したデータ暗号化:データをローカルで暗号化してから、暗号文を OSS にアップロードします。
コンソールでのデータ暗号化と暗号文テーブルの作成
「データ準備」セクションのプレーンテキストデータを OSS バケットにアップロードします。この例では
oss://testBucketName/adb/Spark/customerを使用します。詳細については、「単純アップロード」をご参照ください。AnalyticDB for MySQL コンソールにログインします。コンソールの左上でリージョンを選択します。左側のナビゲーションウィンドウで、クラスターリスト をクリックします。管理するクラスターを見つけて、クラスター ID をクリックします。
左側のナビゲーションウィンドウで、 を選択します。
[SQLConsole] ウィンドウで、Spark エンジンとジョブリソースグループを選択します。
次の文を実行して、暗号文テーブルを作成します。
Confidential Computing を有効にし、カスタマーマスターキーを設定して、データベースを作成します。
-- ネイティブコンピューティングを有効にします。 SET spark.adb.native.enabled=true; -- リソースを設定します。 SET spark.driver.resourceSpec=medium; SET spark.executor.instances=2; SET spark.executor.resourceSpec=medium; SET spark.app.name=Spark SQL Encryption Test; -- 暗号文の読み書きを有効にし、マスターキーのリスト、KMS クライアント、CryptoFactory を設定します。これを有効にすると、エンジンはプレーンテキストと暗号文の両方をサポートします。 SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; -- データベースを作成します。 CREATE database IF NOT EXISTS adb_external_db;パラメーターの説明:
パラメーター
説明
spark.hadoop.parquet.encryption.key.list
カスタマーマスターキー (CMK) のリスト。CMK はキー ID に対応します。複数の CMK はカンマ (,) で区切ります。各キー ID と CMK はコロン (:) で区切ります。フォーマット:
<キー ID 1>:<Base64 エンコードされた CMK 1>,<キー ID 2>:<Base64 エンコードされた CMK 2>。詳細については、「キーの概要」をご参照ください。この例では
kf:MDEyMzQ1Njc4OTAxMjdy****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****を使用します警告OpenSSL などの汎用ツールを使用して、カスタマーマスターキーをランダムに生成できます。カスタマーマスターキーは、暗号化されたデータにアクセスするためのルート認証情報です。キーを紛失すると、既存のデータにアクセスできなくなります。カスタマーマスターキーは安全に保管してください。
spark.hadoop.parquet.encryption.kms.client.class
KMS クライアントのクラス名。これを
io.glutenproject.encryption.InMemoryKMSに設定します。spark.hadoop.parquet.crypto.factory.class
CryptoFactory のクラス名。これを
org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactoryに設定します。プレーンテキストデータを格納するために、
customerという名前の外部テーブルを作成します。LOCATION パラメーターは、プレーンテキストデータの OSS パスを指定します。この例では、oss://testBucketName/adb/Spark/customerを使用します。SET spark.adb.native.enabled=true; SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; CREATE TABLE IF NOT EXISTS adb_external_db.customer ( c_custkey long, c_name string, c_address string, c_nationkey long, c_phone string, c_acctbal decimal(12, 2), c_mktsegment string, c_comment string ) USING parquet LOCATION 'oss://testBucketName/adb/Spark/customer';説明adb_external_dbデータベースにプレーンテキストテーブルが既に存在する場合、このステップはスキップできます。データが別のクラウドデータベースに保存されている場合は、対応する外部テーブルを作成します。外部テーブルを作成する構文については、「CREATE EXTERNAL TABLE」をご参照ください。
暗号文データを格納するために、
enc_customerという名前の外部テーブルを作成します。この例では、enc_customer外部テーブルはoss://testBucketName/adb/Spark/enc_customerに格納されます。SET spark.adb.native.enabled=true; SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; CREATE TABLE IF NOT EXISTS adb_external_db.enc_customer USING Parquet OPTIONS ( 'parquet.encryption.column.keys'='kc1:c_name;kc2:c_phone', 'parquet.encryption.footer.key'='kf' ) LOCATION 'oss://testBucketName/adb/Spark/enc_customer' AS SELECT * FROM adb_external_db.customer;パラメーターの説明:
パラメーター
必須
説明
parquet.encryption.column.keys
はい
キー ID に対応する CMK を使用して列を暗号化します。1 つの CMK で複数の列を暗号化できます。キー ID と列名はコロン (:) で区切ります。複数の列はカンマ (,) で区切ります。異なる CMK はセミコロン (;) で区切ります。
parquet.encryption.footer.key
はい
フッターキー。Parquet ファイルのメタデータなどの情報を暗号化するために使用されます。
説明フッターは Parquet ファイルの末尾にあるデータ構造です。通常、バージョン番号、グループメタデータ、列メタデータ、キーメタデータなどのファイルメタデータを格納します。
重要parquet.encryption.column.keys と parquet.encryption.footer.key パラメーターは同時に設定する必要があります。そうしないと、ファイルは暗号化されません。
(オプション) 外部テーブル
customerを削除します。DROP TABLE IF EXISTS adb_external_db.customer;重要DROP TABLE 文は、
customer外部テーブルのメタデータのみを削除します。プレーンテキストデータの漏洩を防ぐには、対応するデータファイルを OSS から手動で削除する必要があります。
enc_customer_outputという名前の外部テーブルを作成し、enc_customerテーブルからの SQL 計算結果をenc_customer_output外部テーブルに書き込みます。enc_customer_output外部テーブルのデータはoss://testBucketName/adb/Spark/enc_customer_outputに格納されます。SET spark.adb.native.enabled=true; SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; CREATE TABLE IF NOT EXISTS adb_external_db.enc_customer_output USING Parquet OPTIONS ( 'parquet.encryption.column.keys'='kc1:c_name;kc2:c_phone', 'parquet.encryption.footer.key'='kf' ) LOCATION 'oss://testBucketName/adb/Spark/enc_customer_output' AS SELECT * FROM adb_external_db.enc_customer WHERE c_custkey < 15;計算結果を復号します。
customer_outputという名前の外部テーブルを作成します。enc_customer_outputテーブルのデータを復号し、復号したデータをcustomer_output外部テーブルに書き込みます。customer_output外部テーブルのデータはoss://testBucketName/adb/Spark/customer_outputに格納されます。SET spark.adb.native.enabled=true; SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; CREATE TABLE IF NOT EXISTS adb_external_db.customer_output USING Parquet LOCATION 'oss://testBucketName/adb/Spark/customer_output' AS SELECT * FROM adb_external_db.enc_customer_output;customer_outputテーブルのデータをクエリします。SELECT * FROM adb_external_db.customer_output;
暗号化ツールを使用したデータ暗号化と暗号文テーブルの作成
暗号化ツールを使用して、ローカルに保存されているプレーンテキストデータを暗号文データセットに暗号化します。暗号化ツールの詳細については、「Spark 暗号化ツール」をご参照ください。
import org.apache.spark.sql.SparkSession import org.apache.spark.sql.functions._ import org.apache.spark.SparkConf // SparkSession を初期化し、暗号化および復号パラメーターを入力します。 val conf = new SparkConf() .set("spark.hadoop.parquet.encryption.kms.client.class", "org.apache.parquet.crypto.keytools.mocks.InMemoryKMS") .set("spark.hadoop.parquet.encryption.key.list", "kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****") .set("spark.hadoop.parquet.crypto.factory.class", "org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory") val spark = SparkSession.builder().appName("SquareDataFrame").config(conf).getOrCreate() // プレーンテキストの customer ファイルを読み取ります。 val df = spark.read.parquet("customer") // プレーンテキストの customer ファイルを暗号化します。name 列は kc1 で暗号化され、フッターは kf で暗号化されます。結果の暗号文ファイルは enc_customer です。 df.write .option("parquet.encryption.column.keys" , "kc1:c_name") .option("parquet.encryption.footer.key" , "kf") // 暗号文データセットが保存されるローカルパス。 .parquet("enc_customer")パラメーターの説明:
パラメーター
必須
説明
spark.hadoop.parquet.encryption.kms.client.class
はい
KMS クライアントのクラス名。
データをローカルで暗号化する場合は、これを
org.apache.parquet.crypto.keytools.mocks.InMemoryKMSに設定します。コンソールで暗号文テーブルを作成する場合は、これを
io.glutenproject.encryption.InMemoryKMSに設定します。
spark.hadoop.parquet.encryption.key.list
はい
CMK のリスト。CMK はキー ID に対応します。複数の CMK はカンマ (,) で区切ります。各キー ID と CMK はコロン (:) で区切ります。フォーマット:
<キー ID 1>:<Base64 エンコードされた CMK 1>,<キー ID 2>:<Base64 エンコードされた CMK 2>。詳細については、「キーの概要」をご参照ください。この例では
kf:MDEyMzQ1Njc4OTAxMjdy****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****を使用します警告OpenSSL などの汎用ツールを使用して、カスタマーマスターキーをランダムに生成できます。カスタマーマスターキーは、暗号化されたデータにアクセスするためのルート認証情報です。キーを紛失すると、既存のデータにアクセスできなくなります。カスタマーマスターキーは安全に保管してください。
spark.hadoop.parquet.crypto.factory.class
はい
CryptoFactory のクラス名。これを
org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactoryに設定します。parquet.encryption.column.keys
はい
キー ID に対応する CMK を使用して列を暗号化します。1 つの CMK で複数の列を暗号化できます。キー ID と列名はコロン (:) で区切ります。複数の列はカンマ (,) で区切ります。異なる CMK はセミコロン (;) で区切ります。
parquet.encryption.footer.key
はい
フッターキー。Parquet ファイルのメタデータなどの情報を暗号化するために使用されます。
説明フッターは Parquet ファイルの末尾にあるデータ構造です。通常、バージョン番号、グループメタデータ、列メタデータ、キーメタデータなどのファイルメタデータを格納します。
暗号文データセット
enc_customer.parquetを OSS にアップロードします。この例ではoss://testBucketName/adb/Spark/enc_customer.parquetを使用します。詳細については、「単純アップロード」をご参照ください。暗号文テーブルを作成します。
AnalyticDB for MySQL コンソールにログインします。コンソールの左上でリージョンを選択します。左側のナビゲーションウィンドウで、クラスターリスト をクリックします。管理するクラスターを見つけて、クラスター ID をクリックします。
左側のナビゲーションウィンドウで、 を選択します。
[SQLConsole] タブで、Spark エンジンとジョブリソースグループを選択します。
次の文を実行して、暗号文テーブルを作成します。
ネイティブコンピューティングを有効にし、データベースを作成できます。
-- ネイティブコンピューティングを有効にします。 SET spark.adb.native.enabled=true; -- リソースを設定します。 SET spark.driver.resourceSpec=medium; SET spark.executor.instances=2; SET spark.executor.resourceSpec=medium; -- 暗号文の読み書きを有効にし、マスターキーのリスト、KMS クライアント、CryptoFactory を設定します。これを有効にすると、エンジンはプレーンテキストと暗号文の両方をサポートします。 SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; -- データベースを作成します。 CREATE DATABASE IF NOT EXISTS adb_external_db;外部テーブル
enc_customerを作成します。LOCATION パラメーターは、enc_customer暗号文データセットの OSS パスを指定します。この例ではoss://testBucketName/adb/Spark/enc_customer.parquetを使用します。SET spark.adb.native.enabled=true; SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; CREATE TABLE IF NOT EXISTS adb_external_db.enc_customer USING parquet LOCATION 'oss://testBucketName/adb/Spark/enc_customer';
enc_customer_outputという名前の外部テーブルを作成し、enc_customerテーブルからの SQL クエリ結果をenc_customer_output外部テーブルに書き込みます。enc_customer_outputテーブルのデータはoss://testBucketName/adb/Spark/enc_customer_outputに格納されます。SET spark.adb.native.enabled=true; SET spark.hadoop.parquet.encryption.key.list=kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****; SET spark.hadoop.parquet.encryption.kms.client.class=io.glutenproject.encryption.InMemoryKMS; SET spark.hadoop.parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; CREATE TABLE IF NOT EXISTS adb_external_db.enc_customer_output USING Parquet OPTIONS ( 'parquet.encryption.column.keys'='kc1:c_name;kc2:c_phone', 'parquet.encryption.footer.key'='kf' ) LOCATION 'oss://testBucketName/adb/Spark/enc_customer_output' AS SELECT * FROM adb_external_db.enc_customer WHERE c_custkey < 15;暗号文の結果をダウンロードして復号します。
OSS パス
oss://testBucketName/adb/Spark/enc_customer_outputから暗号文の計算結果をローカルデバイスにダウンロードします。詳細については、「ファイルのダウンロード」をご参照ください。暗号文の結果データセットを復号し、復号したファイルを
customer_outputとして保存します。// 暗号文データセットを復号します。 val conf = new SparkConf() .set("spark.hadoop.parquet.encryption.kms.client.class", "org.apache.parquet.crypto.keytools.mocks.InMemoryKMS") .set("spark.hadoop.parquet.encryption.key.list", "kf:MDEyMzQ1Njc4OTAxMjM0****,kc1:bvCDwqcOJGSdZSEMLjfk****,kc2:kflI/sq+uf50Qhl1MmtG****") .set("spark.hadoop.parquet.crypto.factory.class", "org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory") val spark = SparkSession.builder().appName("SquareDataFrame").config(conf).getOrCreate() val df2 = spark.read.parquet("enc_customer_output") // 復号したファイルをローカルデバイスにダウンロードします。 df2.write .parquet("customer_output")