【问题标题】:Unable to get accessKey and SecretKey from Hadoop conf无法从 Hadoop conf 获取 accessKey 和 SecretKey
【发布时间】:2018-03-21 15:58:31
【问题描述】:

我的代码如下 -

import java.io.InputStream
import java.net.URI
import java.util

import com.amazonaws.auth.AWSCredentialsProviderChain
import com.amazonaws.{ClientConfiguration, Protocol}
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.model._
import org.apache.hadoop.conf.{Configuration => HadoopConfiguration}
import org.apache.hadoop.fs.{Path => HadoopPath}
import org.apache.hadoop.fs.s3a.{BasicAWSCredentialsProvider, S3AFileSystem}
import com.amazonaws.services.s3.model.ObjectListing

import scala.annotation.tailrec

object FileOperation {

  val uri = new URI("s3a://bucket-name/prefixKey/file.json")
  val fs: S3AFileSystem = new S3AFileSystem()

  def getAWSClient: AmazonS3Client = {
    val conf: HadoopConfiguration = new HadoopConfiguration(true)
    val awsConf: ClientConfiguration = new ClientConfiguration()

    val secureConnections: Boolean = conf.getBoolean("fs.s3a.connection.ssl.enabled", false)
    awsConf.setProtocol(if (secureConnections) Protocol.HTTPS else Protocol.HTTP)

    val accessKey: String = conf.get("fs.s3a.access.key", null.asInstanceOf[String])
    val secretKey: String = conf.get("fs.s3a.secret.key", null.asInstanceOf[String])

    println(s"inside getAWSClient accessKey -> $accessKey ; secretKey -> $secretKey")

    val credentials = new AWSCredentialsProviderChain(new BasicAWSCredentialsProvider(accessKey, secretKey))

    val s3: AmazonS3Client = new AmazonS3Client(credentials, awsConf)
    s3.setEndpoint(conf.get("fs.s3a.endpoint", null.asInstanceOf[String]))
    s3
  }

  def getEntries(recursive: Boolean): Seq[URI] = {

    @tailrec
    def collectEntries(summaries: util.Iterator[S3ObjectSummary], collected: Seq[HadoopPath]): Seq[HadoopPath] = {
      if (summaries.hasNext) {
        val summary: S3ObjectSummary = summaries.next()
        val newPath: String = "s3a://" + summary.getBucketName + "/" + summary.getKey

        collectEntries(summaries, collected :+ {
          fs.initialize(new URI(newPath), new HadoopConfiguration(true))
          new HadoopPath(new URI(newPath))
        })
      } else collected
    }

    val prefixKey: String = if (!(uri.getScheme != null && uri.getPath.isEmpty)) uri.getPath.substring(1) else ""

    val objects: ObjectListing = getAWSClient.listObjects(uri.getHost, prefixKey)

    if (objects.getObjectSummaries.isEmpty) throw new java.nio.file.NoSuchFileException(uri.toString)
    else {
      collectEntries(objects.getObjectSummaries.iterator(), Seq.empty).map(path => path.toUri)
    }

  }

  def asStream: InputStream = {
    val prefixKey1 = if (!(uri.getScheme != null && uri.getPath.isEmpty)) uri.getPath.substring(1) else ""
    val s3object: S3Object = getAWSClient.getObject(new GetObjectRequest(uri.getHost, prefixKey1))
    s3object.getObjectContent
  }

}

函数 getEntries 中对函数 getAWSClient 的调用有效,但 asStream 函数中的调用获取空的访问密钥和密钥。 getEntries 函数用于列出文件夹下的文件,而 asStream 函数返回这些文件的输入流,用于创建 BufferedSource 然后读取内容。

下面是 hadoop core-ste.xml 文件。有人可以帮我理解为什么 asStream 函数中的访问密钥和密钥显示为空。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Sample config for Hadoop S3A client. -->
<configuration>

    <property>
        <name>fs.s3a.access.key</name>
        <value>xxxxxxxx</value>
    </property>
    <property>
        <name>fs.s3a.secret.key</name>
        <value>yyyyyyy</value>
    </property>
    <property>
        <name>fs.s3a.connection.ssl.enabled</name>
        <value>false</value>
    </property>
    <property>
        <name>fs.s3a.endpoint</name>
        <value>dev:80</value>
    </property>
    <property>
        <name>fs.s3a.imp</name>
        <value>org.apache.hadoop.fs.s3a.S3A</value>
    </property>
    <property>
        <name>fs.s3a.path.style.access</name>
        <value>true</value>
    </property>
</configuration>

【问题讨论】:

  • 在 getAWSClient 函数中,如果我硬编码 accesskey 和 secretkey 的值,我的函数 getEntries 和 asStream 都可以正常工作。但这不是我可以在将投入生产的应用程序中做的事情

标签: amazon-s3 flink-streaming knox-amazon-s3-client


【解决方案1】:
  1. S3A 连接器不会提供其秘密,因为它们是“秘密”。
  2. 并且S3AFileSystem 类不希望initialize() 被多次调用。创建了诸如线程池和 AWS Transfer 管理器之类的昂贵的东西,并且只能在 FileSystem.close() 调用中清理。你的代码会泄露这些。如果我们知道有人试图这样做(现在我们这样做了!),我们将添加一个检查并快速失败。

如果您调用FileSystem.listFiles(path, true),您将获得一个路径下所有对象的递归列表,其中每千个后代条目中只有一个由 S3 发出的 HTTP 请求;这就是你似乎在用 listObjects. 做的事情

哦,如果您想要 FS 使用的配置,请致电 fs.getConf()。如果它们在 XML 文件中传递,那将包含秘密。如果将它们保存在 JCECKs 文件或其他安全存储中,则获取起来有点棘手。

【讨论】:

    猜你喜欢
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2015-08-14
    • 2019-08-23
    • 1970-01-01
    • 2023-04-07
    相关资源
    最近更新 更多