org.apache.hadoop.security.accesscontrolexception:尝试在ec2上使用hadoop java API通过s3n uri访问s3 bucket时,权限被拒绝

t5zmwmid  于 2021-06-04  发布在  Hadoop
关注(0)|答案(1)|浏览(382)

情景

我创建一个名为“my role”的aws iam角色,将ec2指定为受信任实体,即使用信任关系策略文档:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

角色具有以下策略:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:AbortMultipartUpload",
        "s3:DeleteObject",
        "s3:DeleteObjectVersion",
        "s3:GetBucketAcl",
        "s3:GetBucketCORS",
        "s3:GetBucketLocation",
        "s3:GetBucketLogging",
        "s3:GetBucketNotification",
        "s3:GetBucketPolicy",
        "s3:GetBucketRequestPayment",
        "s3:GetBucketTagging",
        "s3:GetBucketVersioning",
        "s3:GetBucketWebsite",
        "s3:GetLifecycleConfiguration",
        "s3:GetObject",
        "s3:GetObjectAcl",
        "s3:GetObjectTorrent",
        "s3:GetObjectVersion",
        "s3:GetObjectVersionAcl",
        "s3:GetObjectVersionTorrent",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads",
        "s3:ListBucketVersions",
        "s3:ListMultipartUploadParts",
        "s3:PutObject",
        "s3:PutObjectAcl",
        "s3:PutObjectVersionAcl",
        "s3:RestoreObject"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}

我使用awscli从命令行启动了一个ec2示例(amazonlinux2014.09.1),将“我的角色”指定为示例概要文件,一切正常。我通过运行以下命令来验证示例是否有效地承担了“我的角色”: curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ 查询示例元数据,从中得到响应 my-role ; curl http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role 我从中获得与“我的角色”关联的临时凭据。
此类凭证检索响应的示例如下:

{
  "Code" : "Success",
  "LastUpdated" : "2015-01-19T10:37:35Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "an-access-key-id",
  "SecretAccessKey" : "a-secret-access-key",
  "Token" : "a-token",
  "Expiration" : "2015-01-19T16:47:09Z"
}
``` `aws s3 ls s3://my-bucket/` 从中我正确地得到了一个包含“我的桶”下的第一个子目录的列表(启动此ami时,默认情况下会安装和配置aws cli。ec2示例和s3 bucket在同一个aws帐户中)
我在这个示例上运行/安装了一个tomcat7服务器和容器,在这个示例上部署了一个j2ee1.7servlet,没有任何问题。
这样的servlet应该在本地文件系统上从s3 bucket下载一个文件,特别是从 `s3://my-bucket/custom-path/file.tar.gz` 使用hadoop java API(请注意,我尝试了hadoop公共工件2.4.x、2.5.x、2.6.x,但没有任何积极的结果。我将在下面发布使用2.5.x时遇到的异常)
在servlet中,我从上面提到的示例元数据url中检索新的凭据,并使用它们配置我的hadoop java api示例:

...
Path path = new Path("s3n://my-bucket/");
Configuration conf = new Configuration();
conf.set("fs.defaultFS", path.toString());
conf.set("fs.s3n.awsAccessKeyId", myAwsAccessKeyId);
conf.set("fs.s3n.awsSecretAccessKey", myAwsSecretAccessKey);
conf.set("fs.s3n.awsSessionToken", mySessionToken);
...

显然, `myAwsAccessKeyId` ,  `myAwsSecretAccessKey` ,和 `mySessionToken` 是我之前用实际值设置的java变量。然后,我有效地获得一个文件系统示例,使用:

FileSystem fs = path.getFileSystem(conf);

我能够检索与文件系统(fs.getconf().get(key name))相关的所有配置,并验证所有配置都是按照假设的那样配置的。

### 问题

我不能下载 `s3://my-bucket/custom-path/file.tar.gz` 使用:

...
fs.copyToLocalFile(false, new Path(path.toString()+"custom-path/file.tar.gz"), outputLocalPath);
...

如果我使用hadoopcommon2.5.x,我会得到 `IOException` :
org.apache.hadoop.security.accesscontrolexception:权限被拒绝:s3n://my bucket/custom path/file.tar.gz位于org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.processexception(jets3tnativefilesystemstore)。java:449)位于org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.processexception(jets3tnativefilesystemstore)。java:427)在org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.handleexception(jets3tnativefilesystemstore)。java:411)位于org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.retrievemetadata(jets3tnativefilesystemstore)。java:181)位于sun.reflect.nativemethodaccessorimpl.invoke0(本机方法)sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl。java:57)在sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl。java:43)在java.lang.reflect.method.invoke(方法。java:606)在org.apache.hadoop.io.retry.retryinvocationhandler.invokemethod(retryinvocationhandler。java:187)在org.apache.hadoop.io.retry.retryinvocationhandler.invoke(retryinvocationhandler。java:102)org.apache.hadoop.fs.s3native.$proxy12.retrievemetadata(未知源),org.apache.hadoop.fs.s3native.natives3filesystem.getfilestatus(natives3filesystem)。java:467)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:337)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:289)在org.apache.hadoop.fs.filesystem.copytolocalfile(filesystem。java:1968)在org.apache.hadoop.fs.filesystem.copytolocalfile(filesystem。java:1937) ...
如果我使用hadoopcommon2.4.x,我会得到一个 `NullPointerException` :
org.apache.hadoop.fs.s3native.natives3filesystem.getfilestatus(natives3filesystem)上的java.lang.nullpointerexception。java:433)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:337)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:289)在org.apache.hadoop.fs.filesystem.copytolocalfile(filesystem。java:1968)在org.apache.hadoop.fs.filesystem.copytolocalfile(文件系统)。java:1937) ...
只是为了记录,如果不设置任何aws凭据,我会得到:
aws access key id和secret access key必须分别指定为s3n url的用户名或密码,或者通过设置fs.s3n.awsaccesskeyid或fs.s3n.awssecretaccesskey属性来指定。

### 期末笔记

如果我尝试从示例中使用awscli命令从完全相同的uri(但用s3代替s3n)下载该文件,则完全没有问题。
如果我尝试下载hadoop发行版(如2.4.1)https://archive.apache.org/dist/hadoop/core/hadoop-2.4.1/),解压缩它,从示例元数据url检索临时aws凭据并尝试运行 `<hadoop-dir>/bin/hadoop fs -cp s3n://<aws-access-key-id>:<aws-secret-access-key>@my-bucket/custom-path/file.tar.gz .` 我又一次得到了npe:
位于org.apache.hadoop.fs.s3native.natives3filesystem.liststatus(natives3filesystem)的致命内部错误java.lang.nullpointerexception。java:479)在org.apache.hadoop.fs.shell.pathdata.getdirectorycontents(路径数据。java:268)在org.apache.hadoop.fs.shell.command.recursepath(command。java:347)在org.apache.hadoop.fs.shell.ls.processpathargument(ls。java:96)在org.apache.hadoop.fs.shell.command.processargument(command。java:260)在org.apache.hadoop.fs.shell.command.processarguments(command。java:244)在org.apache.hadoop.fs.shell.command.processrawarguments(command。java:190)在org.apache.hadoop.fs.shell.command.run(command。java:154)在org.apache.hadoop.fs.fsshell.run(fsshell。java:255)在org.apache.hadoop.util.toolrunner.run(toolrunner。java:70)在org.apache.hadoop.util.toolrunner.run(toolrunner。java:84)在org.apache.hadoop.fs.fsshell.main(fsshell。java:308)
抱歉发了这么长的帖子,我只是尽量详细。谢谢你的帮助。
2w3rbyxf

2w3rbyxf1#

您正在使用sts/临时aws凭据;这些似乎目前不受 s3 或者
s3n FileSystem hadoop中的实现。
awssts/临时凭证不仅包括一个(访问密钥、密钥),还包括一个会话令牌。hadoop s3 以及
s3n FileSystem (s) 还不支持包含会话令牌(即您的 fs.s3n.awsSessionToken 不受支持且被
s3n FileSystem .
从amazons3-hadoop wiki。。。
(注:未提及 fs.s3.awsSessionToken ):
配置为使用s3/s3n文件系统
编辑您的 core-site.xml 包含s3密钥的文件

<property>
     <name>fs.s3.awsAccessKeyId</name>
     <value>ID</value>
   </property>

   <property>
     <name>fs.s3.awsSecretAccessKey</name>
     <value>SECRET</value>
   </property>

如果您在github.com上查看apache/hadoop中的s3credentials.java,就会注意到s3凭证的表示中完全没有会话令牌的概念。
提交了一个补丁来解决这个限制(这里详细说明);然而,它还没有被整合。
如果您使用的是aws iam示例角色,则可能需要探索使用新的
s3a FileSystem 这是hadoop2.6.0中添加的。它声称支持基于iam角色的身份验证(即,根本不必显式指定密钥)。
hadoop jira票证描述了如何配置
s3a FileSystem :
从https://issues.apache.org/jira/browse/hadoop-10400 : fs.s3a.access.key -您的aws访问密钥id(角色身份验证时省略) fs.s3a.secret.key -您的aws密钥(角色身份验证时省略)

相关问题