首页 > 解决方案 > 无法从 spark 中的 sse-kms 加密 s3 对象中检索数据

问题描述

因为我使用的当前 spark 环境是 hadoop2.7 中的 spark 2.4,但是 hadoop2.7 不支持 SSE-KMS。来自 apache: HADOOP-13075,它是在 2.8 中引入的,在 hadoop 3.0 之后完全支持。然后从官方文档中添加 两个配置参数fs.s3a.server-side-encryption-algorithm& fs.s3a.server-side-encryption.key" 。

基于以前的文档,我添加了 package org.apache.hadoop:hadoop-aws:3.1.1& com.amazonaws:aws-java-sdk:1.9.5inspark-submit参数,并添加

spark._jsc.hadoopConfiguration().set("fs.s3a.server-side-encryption-algorithm", aws_sse_algorithm)`
spark._jsc.hadoopConfiguration().set("fs.s3a.server-side-encryption.key", aws_sse_key)

to spark config,aws_sse_algorithmSSE-KMS&sse_key由我们的管理员提供的。

与此同时,我基本上将所有我可以添加到配置中的参数。但是,我得到了这个异常:

Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.

当我在 spark 中检索 s3 对象时:

df = spark.read.json('s3a://XXXXXXX/XXXXX/XXXXXXXX/result.json') 
2019-08-09 14:54:09,525 ERROR executor.Executor: Exception in task 0.0 in stage 4.0 (TID 4)
**com.amazonaws.services.s3.model.AmazonS3Exception: Status Code: 400, AWS Service: Amazon S3, AWS Request ID: 7C1C371AE02F476A, AWS Error Code: InvalidArgument, 
AWS Error Message: Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.**, S3 Extended Request ID: hlCH96//G18Bs47fGJwxt+Ccpdf0YNOadt9bUPYei2InkkUeKCslq/4m353RnQEhopBfvjVIcx0=
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:798)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:421)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:232)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3528)
at com.amazonaws.services.s3.AmazonS3Client.getObject(AmazonS3Client.java:1111)
.......

我的完整代码:

import datetime, time 
from pyspark.sql import SparkSession 
from pyspark.sql import functions as func 
from pyspark.sql.functions import udf 
from pyspark.sql.types import StringType, IntegerType, DoubleType, ArrayType, StructType, StructField, MapType 
import boto3 
import json 
import pytz 
import configparser 
import argparse 
from dateutil.parser import parse

import os

os.environ['PYSPARK_SUBMIT_ARGS'] = "--packages=org.apache.hadoop:hadoop-aws:3.1.1,org.apache.hadoop:hadoop-common:3.1.1,org.apache.hadoop:hadoop-auth:3.1.1," \ ... "com.amazonaws:aws-java-sdk:1.9.5 " \ ... "pyspark-shell"

spark = SparkSession.builder.appName("test").getOrCreate() aws_sse_algorithm = 'SSE-KMS' 
aws_sse_key = 'arn:aws:kms:ap-southeast-1:XXXXXXX:key/XXXXXX'

aws_access_id = 'XXXXX' 
aws_access_key = 'XXXXX' 
aws_region = 'ap-southeast-1'

spark._jsc.hadoopConfiguration().set("fs.s3a.access.key", aws_access_id) spark._jsc.hadoopConfiguration().set("fs.s3a.secret.key", aws_access_key) spark._jsc.hadoopConfiguration().set("fs.s3a.fast.upload", "true") spark._jsc.hadoopConfiguration().set("fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem") spark._jsc.hadoopConfiguration().set("com.amazonaws.services.s3.enableV4", "true") spark._jsc.hadoopConfiguration().set("fs.s3a.aws.credentials.provider","org.apache.hadoop.fs.s3a.BasicAWSCredentialsProvider") spark._jsc.hadoopConfiguration().set("fs.s3a.endpoint", "s3."+aws_region+".amazonaws.com")

spark._jsc.hadoopConfiguration().set("fs.s3a.sse.enabled", "true") spark._jsc.hadoopConfiguration().set("fs.s3a.enableServerSideEncryption", "true")

spark._jsc.hadoopConfiguration().set("fs.s3a.server-side-encryption-algorithm", aws_sse_algorithm) spark._jsc.hadoopConfiguration().set("fs.s3a.server-side-encryption.key", aws_sse_key) spark._jsc.hadoopConfiguration().set("fs.s3a.sse.kms.keyId", aws_sse_key)

df = spark.read.json('s3a://XXXXXXX/XXXXX/XXXXXXXX/result.json')

我不确定它是否与本地 spark_classpath 中的 hadoop jars 仍然低于 2.7.3 版本有关。但是我将 3.1.1 jar 添加到 spark 的 --packages 部分。

标签: apache-sparkamazon-s3aws-kms

解决方案


如果您必须为 v4 签名设置 jvm 选项才能工作,那么您仍在使用 hadoop-2.7 s3a 实现。

  • 所有 hadoop-* JAR 必须是完全相同的版本,否则您将看到堆栈跟踪
  • aws-sdk 版本必须与构建和测试 hadoop-aws 的版本完全相同,否则您将看到不同的堆栈跟踪。

遗憾的是,在你拥有一组一致的 JAR 之前,你注定要失败。您最终只会浪费时间移动堆栈跟踪。首先正确获取这些依赖项。

这意味着:升级到 Hadoop 2.8+ 工件。完全


推荐阅读