描述
在PySpark中,即使DataFrame可以保存到S3/S3A(不是AWS,而是S3兼容的存储器(,但其数据仍会以未加密的方式保存,尽管使用了设置fs.s3a.encryption.algorithm
(SSE-C
(和fs.s3a.encryption.key
。
再现性
生成如下密钥:
encKey=$(openssl rand -base64 32)
启动PySpark外壳:
pyspark --master spark://[some_host]:7077
--packages io.delta:delta-core_2.12:2.0.0,org.apache.hadoop:hadoop-aws:3.3.1,com.amazonaws:aws-java-sdk-bundle:1.11.901,org.apache.hadoop:hadoop-common:3.3.1
--conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension"
--conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
在PySpark中,一个玩具示例:
sc._jsc.hadoopConfiguration().set("fs.s3a.access.key", "[access.key]")
sc._jsc.hadoopConfiguration().set("fs.s3a.secret.key", "[secret.key]")
sc._jsc.hadoopConfiguration().set("fs.s3a.endpoint", "[s3.compliant.endpoint]")
sc._jsc.hadoopConfiguration().set("fs.s3a.encryption.algorithm", "SSE-C")
sc._jsc.hadoopConfiguration().set("fs.s3a.encryption.key", "[the_encKey_above]")
from pyspark.sql.types import StructType,StructField, StringType, IntegerType
data2 = [("James","","Smith","36636","M",3000),
("Michael","Rose","","40288","M",4000),
("Robert","","Williams","42114","M",4000),
("Maria","Anne","Jones","39192","F",4000),
("Jen","Mary","Brown","","F",-1)
]
schema = StructType([
StructField("firstname",StringType(),True),
StructField("middlename",StringType(),True),
StructField("lastname",StringType(),True),
StructField("id", StringType(), True),
StructField("gender", StringType(), True),
StructField("salary", IntegerType(), True)
])
df = spark.createDataFrame(data=data2,schema=schema)
#df.write.format("csv").option("header", "true").save("s3a://data/test")
df.repartition(1).write.format("csv").option("header", "true").save("s3a://data/test")
我们可以看到创建的文件夹s3a://data/test
,其中有一个CSV文件。但不幸的是,该文件是未加密的。也就是说,它甚至可以通过网络浏览器手动下载,然后用记事本查看!设置fs.s3a.encryption.algorithm
似乎被忽略了。
环境
- Apache Spark v3.2.2
- Hadoop aws v3.3.1/Hadoop common v3.3.1
- openjdk 11.0.16.1 2022-08-12(Temurin(
- Python 3.10.4
- Ubuntu 22.04 LTS
调试
有趣的是,如果使用AWS CLI:,那么同一个端点对上传的文件进行加密没有问题
aws --endpoint-url https://[s3.compliant.endpoint]
s3api put-object
--body "/home/[a_user]/Desktop/a_file.csv"
--bucket "data"
--key "test/a_file.csv"
--sse-customer-algorithm AES256
--sse-customer-key $encKey
--sse-customer-key-md5 $md5Key
aws -version
# aws-cli/2.7.35 Python/3.9.11 Linux/5.15.0-48-generic exe/x86_64.ubuntu.22 prompt/off
我阅读了使用加密S3数据的手册指南,但没有任何帮助。
找到了一个解决方案:
库hadoop-aws v3.3.1
/aws-java-sdk-bundle v1.11.901
/hadoop-common v3.3.1
一定有一些错误,或者只是与S3的最新协议不兼容(截至2022.10.06(。可以通过使用库的最新版本来克服上述问题,即:hadoop-aws v3.3.4
(因此是aws-java-sdk-bundle v1.12.262
依赖项(和hadoop-common v3.3.4
(以匹配hadoop-aws
(。
在3.3.2至3.3.4的发行说明中,可能有一些与AWS/S3相关的修复程序有助于解决该问题。
- https://hadoop.apache.org/docs/r3.3.2/hadoop-project-dist/hadoop-common/release/3.3.2/CHANGELOG.3.3.2.html
- https://hadoop.apache.org/docs/r3.3.3/hadoop-project-dist/hadoop-common/release/3.3.3/CHANGELOG.3.3.3.html
- https://hadoop.apache.org/docs/r3.3.4/hadoop-project-dist/hadoop-common/release/3.3.4/CHANGELOG.3.3.4.html
总结一下,对于PySpark,使用:
pyspark --master spark://[some_host]:7077
--packages io.delta:delta-core_2.12:2.0.0,org.apache.hadoop:hadoop-aws:3.3.4,com.amazonaws:aws-java-sdk-bundle:1.12.262,org.apache.hadoop:hadoop-common:3.3.4
--conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension"
...
使用hadoop 3.3.1或更早版本时,请使用fs.s3a.server-side-encryption算法和"fs.s3a.服务器端加密密钥";;";fs.s3a.encryption。*";选项仅在hadoop3.3.2中提供,并在hadoop-13887 中支持客户端加密