【问题标题】:Apache Camel AWS S3: credential expiration and temporary credentialsApache Camel AWS S3:凭证到期和临时凭证
【发布时间】:2017-12-28 21:53:29
【问题描述】:

Apache Camel 与 AWS S3 的接口很好,但我发现它没有正确构建的场景。回顾我在网上看到的所有 Camel 示例,我从未见过有人在非本地环境中使用推荐的行业标准 AWS 临时凭证。使用可使用约 6 个月的静态凭据既是安全问题,也是手动负担(刷新),实际上不应在除本地环境之外的任何地方使用。

鉴于自定义的 s3 客户端设置,Camel 可以获取临时凭证,但是,指向 AWS S3 的 Camel 路由将在某个时间点过期。 Camel 不够聪明,无法知道这一点,它将继续尝试轮询 S3 存储桶,而不会无限期地抛出任何异常或超时错误。

我尝试向我的端点添加超时配置,如下所示:

aws-s3://" + incomingAWSBucket + "?" + "amazonS3Client=#amazonS3Client&timeout=4000

谁能解释如何将 Camel 与 AWS 临时凭证连接或在 AWS 凭证过期时抛出异常(鉴于上述设置)?

感谢您的帮助!


更新:

我向 Apache Camel 推送了一项功能来处理上述问题: https://github.com/apache/camel/blob/master/components/camel-aws-s3/src/main/docs/aws-s3-component.adoc#use-useiamcredentials-with-the-s3-component

【问题讨论】:

  • 你能告诉更多,你使用的是哪个 Camel 版本,你是在路由中使用那个端点还是什么?如果凭据过期,您想做什么
  • Camel 版本 2.20.0,我有一个指向 AWS s3 的路由,“to”路由是我的本地目录。最后,如果凭据不再起作用(基本上是超时异常),我希望骆驼抛出异常。
  • 我还没有证明这一点,但似乎在骆驼进程中使用依赖于 AWS 默认凭证链的自定义 S3 客户端将导致客户端自行管理凭证。我将在完成实验后更新此内容:AmazonS3ClientBuilder.standard().withRegion(Regions.US_WEST_2).build();

标签: java amazon-s3 apache-camel


【解决方案1】:

如果其他人想要的话,这个问题的答案对于一个教程来说已经足够密集了。现在,我将把它复制并粘贴到正确的论坛和帖子中以宣传:

没有太多的抱怨,我只想说,Camel 的强大,它的文档和示例库对于 AWS 世界的生产场景来说真的很缺乏...... 叹息...... 对于任何开源库来说,这都是一个拗口,而且可能是一个延伸。

我通过参考官方camel-s3 documentation 了解了如何解决凭证问题,首先了解如何创建高级 S3 配置(依赖于 aws sdk 本身——你可以在那里看到一个简单的例子——它使s3 客户端手动)。 在我弄清楚这一点后,我去了aws sdk documentation on IAM credentials 想知道这如何在 EC2 实例上工作,因为我能够自己构建客户端。在上述文档中,也有一些简单的示例。在使用列出的示例进行测试后,我发现凭证刷新(此问题的唯一目的)不起作用。一开始它可以获得凭据,但在我的测试期间手动过期后它没有刷新它们。 最后,我发现您可以指定一个提供程序链来自行处理凭据的刷新。解释这一点的 aws 文档是 here

最后,我仍然需要为轮询 aws s3 存储桶的本地骆驼设置提供静态凭据,但是,我在 ec2s 上的远程环境可以使用可以完美刷新自身的临时凭据访问它们。哇! :)

为此,我简单地创建了一个工厂,该工厂使用本地骆驼设置进行本地开发和依赖临时 IAM 凭证的远程骆驼设置。这为我节省了安全问题和需要为所有远程环境手动刷新凭据的工作!

我不会解释如何创建工厂或如何完全设置我的本地和远程配置,但我将包含我的 AmazonS3ClientBuilder 代码示例,它为远程设置创建 S3 客户端。

AmazonS3ClientBuilder.standard()
   .withCredentials(new InstanceProfileCredentialsProvider(false))
   .withRegion(Regions.US_WEST_2)
   .build();

如果我想知道我是如何做到这一点的,我可以提供一个示例项目来展示整个过程。

根据要求,这是我的 s3 客户端的本地和远程实现: 本地:

public class LocalAWSS3ClientManagerImpl implements AWSS3ClientManager {
    private static Logger logger = LoggerFactory.getLogger(LocalAWSS3ClientManagerImpl.class);
    private PriorityCodeSourcesRoutesProperties priorityCodeSourcesRoutesProperties;
    private SimpleRegistry registry = new SimpleRegistry();
    private CamelContext camelContext;

public LocalAWSS3ClientManagerImpl(PriorityCodeSourcesRoutesProperties priorityCodeSourcesRoutesProperties) {
    this.priorityCodeSourcesRoutesProperties = priorityCodeSourcesRoutesProperties;
    registry.put("amazonS3Client", getS3Client());
    camelContext = new DefaultCamelContext(registry);
    logger.info("Creating an AWS S3 manager for a local instance (you should not see this on AWS EC2s).");
}

private AmazonS3 getS3Client() {
    try {
        String awsBucketAccessKey = priorityCodeSourcesRoutesProperties.getAwsBucketAccessKey();
        String awsBucketSecretKey = priorityCodeSourcesRoutesProperties.getAwsBucketSecretKey();
        AWSCredentials awsCredentials = new BasicAWSCredentials(awsBucketAccessKey, awsBucketSecretKey);
        return AmazonS3ClientBuilder.standard().withCredentials(
                new AWSStaticCredentialsProvider(awsCredentials)).build();
    } catch (RuntimeException ex) {
        logger.error("Could not create AWS S3 client with the given credentials from the local config.");
    }
    return null;
}

public Endpoint getIncomingAWSEndpoint(final String incomingAWSBucket, final String region,
        final String fileNameToSaveAndDownload) {
    return camelContext.getEndpoint(
            "aws-s3://" + incomingAWSBucket + "?" + "amazonS3Client=#amazonS3Client"
            + "&region=" + region + "&deleteAfterRead=false" + "&prefix=" + fileNameToSaveAndDownload);
}

public Endpoint getOutgoingLocalEndpoint(final String outgoingEndpointDirectory,
        final String fileNameToSaveAndDownload) {
    return camelContext.getEndpoint(
            "file://" + outgoingEndpointDirectory + "?" + "fileName="
            + fileNameToSaveAndDownload + "&readLock=markerFile");
}
}

远程:

public class RemoteAWSS3ClientManagerImpl implements AWSS3ClientManager {
private static Logger logger = LoggerFactory.getLogger(RemoteAWSS3ClientManagerImpl.class);
private PriorityCodeSourcesRoutesProperties priorityCodeSourcesRoutesProperties;
private SimpleRegistry registry = new SimpleRegistry();
private CamelContext camelContext;

public RemoteAWSS3ClientManagerImpl(PriorityCodeSourcesRoutesProperties priorityCodeSourcesRoutesProperties) {
    this.priorityCodeSourcesRoutesProperties = priorityCodeSourcesRoutesProperties;
    registry.put("amazonS3Client", getS3Client());
    camelContext = new DefaultCamelContext(registry);
    logger.info("Creating an AWS S3 client for a remote instance (normal for ec2s).");
}

private AmazonS3 getS3Client() {
    try {
        logger.info("Attempting to create an AWS S3 client with IAM role's temporary credentials.");
        return AmazonS3ClientBuilder.standard()
                                    .withCredentials(new InstanceProfileCredentialsProvider(false))
                                    .withRegion(Regions.US_WEST_2)
                                    .build();
    } catch (RuntimeException ex) {
        logger.error("Could not create AWS S3 client with the given credentials from the instance. "
                     + "The default credential chain was used to create the AWS S3 client. "
                     + ex.toString());
    }
    return null;
}

public Endpoint getIncomingAWSEndpoint(final String incomingAWSBucket, final String region,
        final String fileNameToSaveAndDownload) {
    return camelContext.getEndpoint(
            "aws-s3://" + incomingAWSBucket + "?" + "amazonS3Client=#amazonS3Client"
            + "&region=" + region + "&deleteAfterRead=false" + "&prefix=" + fileNameToSaveAndDownload);
}

public Endpoint getOutgoingLocalEndpoint(final String outgoingEndpointDirectory,
        final String fileNameToSaveAndDownload) {
    return camelContext.getEndpoint(
            "file://" + outgoingEndpointDirectory + "?" + "fileName="
            + fileNameToSaveAndDownload + "&readLock=markerFile");
}

}

【讨论】:

  • 这真的很有趣。在 Camel 2.21.x 中,我们正在稍微更改客户端配置github.com/apache/camel/commit/… 你能指出一个示例项目吗?
  • 我可以做一个,但除非绝对必要,否则我宁愿不做。当我这周有时间时,我将添加完整的课程,以便更多地了解我如何组装远程和本地客户端。
  • 关于您发送的提交,我看不出这如何显着扩展功能。它仍然依赖于静态凭据(这可能是一个很好的默认行为),但是,如果需要,可以修改代码以正确处理两种情况(远程和本地)。
  • 另外,我对为 Camel 做出贡献非常感兴趣,但我不知道如何开始。
  • 您可以在这里获取一些信息:github.com/apache/camel/blob/master/CONTRIBUTING.md
猜你喜欢
  • 1970-01-01
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多