Apache Camel AWS S3:凭据到期和临时凭证

时间:2017-12-28 21:53:29

标签: java amazon-s3 apache-camel

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

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

我试图将超时配置添加到我的端点,如下所示:

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

任何人都可以解释如何使用AWS临时凭证来连接Camel,或者如果AWS凭证到期则抛出异常(给定上述设置)?

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

如果其他人想要这个问题,这个问题的答案就足够密集了。现在,我将把它复制并粘贴到正确的论坛和帖子中以获取消息:

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

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

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

为此,我简单地创建了一个工厂,该工厂使用本地camel设置进行本地开发和远程camel设置,该设置依赖于临时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");
}

}