在不允许 getEnv 调用的受保护环境中创建 AmazonHttpClient

Posted

技术标签:

【中文标题】在不允许 getEnv 调用的受保护环境中创建 AmazonHttpClient【英文标题】:create AmazonHttpClient in a protected environment which does not allow getEnv calls 【发布时间】:2020-11-25 19:33:17 【问题描述】:

从AWS SDK 的版本 1.11.700 切换到 1.11.908,我们的一个库现在无法在受保护的环境中工作。更具体地说,新的 SDK 版本已更改 ClientConfiguration,因此它现在通过检查环境变量来实例化 RetryPolicy。

不幸的是,我们将把这个库部署到一个禁止(SecurityManager in place)访问环境变量的环境中。 这意味着我们所有依赖于AmazonHttpClient 的代码不再可用,因为:

要实例化 AmazonHttpClient,您必须传入有效的 ClientConfiguration(不接受 null) 要创建有效的ClientConfiguration,您需要能够读取环境变量

这是堆栈跟踪:

java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getenv.AWS_RETRY_MODE")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:886)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at com.boomi.security.ExtendedSecurityManager.checkPermissionImpl(ExtendedSecurityManager.java:207)
    at com.boomi.security.ExtendedSecurityManager.checkPermission(ExtendedSecurityManager.java:114)
    at java.lang.System.getenv(System.java:894)
    at com.amazonaws.retry.internal.RetryModeResolver.envVar(RetryModeResolver.java:67)
    at com.amazonaws.retry.internal.RetryModeResolver.resolveRetryMode(RetryModeResolver.java:72)
    at com.amazonaws.retry.internal.RetryModeResolver.<init>(RetryModeResolver.java:46)
    at com.amazonaws.retry.RetryPolicy.<clinit>(RetryPolicy.java:35)
    at com.amazonaws.retry.PredefinedRetryPolicies.<clinit>(PredefinedRetryPolicies.java:30)
    at com.amazonaws.ClientConfiguration.<clinit>(ClientConfiguration.java:89)

我们提出的所有选项都不适用于这种情况:

子类化 ClientConfiguration 以抑制异常:无法尝试捕获对 super() 构造函数的调用 ClientConfiguration 是一个类,因此我们没有要实现的接口 java.policy 无法修改以允许访问该属性:环境不在我们的控制范围内 异常是从而不是从引发的,因此它甚至与单个对象无关...

【问题讨论】:

您至少可以修改 java 策略文件吗? ~/.java.policy` 或 [java.home]/lib/security/java.policy 并添加以下内容:grant permission java.lang.RuntimePermission "getenv.AWS_RETRY_MODE", "read"; ; 谢谢,但是修改安全环境不是我们可以在那个环境下做的事情,我会澄清这个问题 【参考方案1】:

看起来 AmazonHttpClient 有一个 builder(),所以如果您在构建器上设置了 retryPolicy,ClientConfiguration 可能不会寻找 retryPolicy。

https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/http/AmazonHttpClient.Builder.html

---------------- 另一种选择:

我们可以在官方 SDK 代码中看到,ClientConfiguration() 构造函数可以采用另一个 ClientConfiguration,因此可以使用 extends 创建一个自定义的构造函数。

   public class ClientConfigurationByPassingSecurity extends ClientConfiguration
    
        @Override
        public RetryPolicy getRetryPolicy()
           return xx;
        
    
   

//通过这个自定义创建你的 AmazonHttpClient

ClientConfiguration customClientConfiguration = new ClientConfigurationByPassingSecurity ();

ClientConfiguration clientConfig = new ClientConfiguration(customClientConfiguration);


new AmazonHttpClient(clientConfig);

覆盖由于 getVars 而失败的任何方法。

【讨论】:

非常聪明的方法!不幸的是,这似乎不起作用,因为不幸的是,自定义重试策略正在 对象初始化之后被读取,而 AccessControlException 在类初始化期间被引发(即更早:-() 你是对的,@SimoneAvogadro 它们是静态变量,将在构造函数之前初始化。我调查了一下,问题从 RetryPolicy 开始,因为它正在调用 RetryModeResolver,它首先查看 env、系统属性,然后是配置文件。 github.com/aws/aws-sdk-java/blob/…看到你开了bug票,祝你好运

以上是关于在不允许 getEnv 调用的受保护环境中创建 AmazonHttpClient的主要内容,如果未能解决你的问题,请参考以下文章

采用抽象超类实例和“不允许访问受保护方法”错误的受保护方法

为什么派生类d的对象不能调用基类的受保护成员函数?

为啥我不能在同一类的受保护方法中调用方法[重复]

如何从 Derived 内部调用 Base 实例中的受保护成员函数?

从 C# 调用 FORTRAN DLL 的受保护内存冲突

在 C# 中调用类的受保护构造函数