我有一个Spark进程,从S3获取两个输入文件。在工作结束时,我只想用saveAsTextFile
方法将结果写回S3。但是,我收到Access Denied
错误。
我的政策规则是公开的,以确保我没有任何权限错误:
{
"Version": "2012-10-17",
"Id": "Policy1457106962648",
"Statement": [
{
"Sid": "Stmt1457106959104",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::<bucket-name>/*"
}
]
}
我在SparkContext
上设置了我的凭据,如下所示:
SparkConf conf = new SparkConf()
.setAppName("GraphAnalyser")
.setMaster("local[*]")
.set("spark.driver.memory", "2G");
.set("spark.hadoop.fs.s3.awsAccessKeyId", [access-key])
.set("spark.hadoop.fs.s3n.awsAccessKeyId", [access-key])
.set("spark.hadoop.fs.s3.awsSecretAccessKey", [secret-key])
.set("spark.hadoop.fs.s3n.awsSecretAccessKey", [secret-key]);
我使用s3n
协议的传递文件URL:
final String SC_NODES_FILE = "s3n://" + BUCKET_NAME + "/" + NODES_FILE;
final String SC_EDGES_FILE = "s3n://" + BUCKET_NAME + "/" + EDGES_FILE;
final String SC_OUTPUT_FILE = "s3n://" + BUCKET_NAME + "/output";
请注意,我访问输入文件没有问题。看起来Spark会为输出文件发送HEAD
请求,以确保它在尝试保存最终结果之前不存在。因为,s3返回Access Denied
而不是Not Found
。这可能是Spark抛出异常并退出的原因。
org.apache.hadoop.fs.s3.S3Exception: org.jets3t.service.S3ServiceException: S3 HEAD request failed for '/output.csv' - ResponseCode=403, ResponseMessage=Forbidden
Spark 1.6.0 aws-java-sdk(1.10.58) spark-core_2.10(1.6.0)
感谢您的帮助。非常感谢你。
答案 0 :(得分:3)
回答我自己的问题
事实证明,我需要s3:ListBucket
动作,仅当资源是存储桶本身时才适用,而不是存储桶中的密钥。
在我的原始政策文件中,我有以下资源:
"Resource": "arn:aws:s3:::<bucket-name>/*"
我不得不补充道:
"Resource": "arn:aws:s3:::<bucket-name>/*"
这是我的最终政策文件,对我有用:
{
"Id": "Policy145712123124123",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt145712812312323",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<bucket-name>",
"arn:aws:s3:::<bucket-name>/*"
],
"Principal": {
"AWS": [
"arn:aws:iam::<account-id>:user/<user-name>"
]
}
}
]
}