Rou*_*her 2 java credentials keystore truststore amazon-web-services
我正在尝试实施以下 AWS 文章中介绍的解决方案:
所以我做了接下来的步骤:
创建本地密钥库:
keystore winpty openssl pkcs12 -export -in eeb81a0eb6-certificate.pem.crt -inkey eeb81a0eb6-private.pem.key -name myname -out my.p12 -password pass:mypass
keytool -importkeystore -destkeystore mykeystore.jks -srckeystore my.p12 -srcstoretype PKCS12 -deststorepass mypass -srcstorepass mypass
创建本地信任库:
keytool -keystore my_ca.jks -alias myalias -import -file AmazonRootCA1.pem
我的代码:
public class AWSSessionCredentialsProviderImpl implements AWSSessionCredentialsProvider {
private static final Logger LOGGER = LogManager.getLogger(AWSSessionCredentialsProviderImpl.class.getName());
private final Gson gson = new Gson();
private SdkHttpClient client;
private HttpExecuteRequest request;
private String awsAccessKeyId;
private String awsSecretAccessKeyId;
private String awsSessionToken;
public void init(String clientId) throws IOException, URISyntaxException {
System.setProperty("javax.net.ssl.trustStore", Configuration.KEYSTOREPATH_CA.toAbsolutePath().toString());
System.setProperty("javax.net.ssl.trustStoreType", "jks");
try {
System.setProperty("javax.net.ssl.trustStorePassword", new String(Files.readAllBytes(Configuration.KEYSTOREPATH_CA_PASS)));
} catch (IOException e) {
throw new IOException("Read password of trust store is failed", e);
}
System.setProperty("javax.net.ssl.keyStore", Configuration.KEYSTOREPATH.toAbsolutePath().toString());
System.setProperty("javax.net.ssl.keyStoreType", "jks");
try {
System.setProperty("javax.net.ssl.keyStorePassword", new String(Files.readAllBytes(Configuration.KEYSTOREPATH_PASS)));
} catch (IOException e) {
throw new IOException("Read password of key store is failed", e);
}
client = ApacheHttpClient.builder().build();
SdkHttpRequest httpRequest;
try {
httpRequest = SdkHttpFullRequest.builder()
.method(SdkHttpMethod.GET)
.uri(new URI(Configuration.CLIENT_ENDPOINT))
.putHeader("x-amzn-iot-thingname", clientId)
.build();
} catch (URISyntaxException e) {
throw new URISyntaxException(Configuration.CLIENT_ENDPOINT, "Building URI from client endpoint is failed");
}
request = HttpExecuteRequest.builder()
.request(httpRequest)
.build();
try {
setCredentials();
} catch (IOException e) {
throw new IOException("Set temporary credentials is failed", e);
}
}
@Override
public void refresh() {
try {
setCredentials();
} catch (IOException e) {
LOGGER.error("Refresh session credentials is failed", e);
}
}
@Override
public AWSSessionCredentials getCredentials() {
return new BasicSessionCredentials(awsAccessKeyId, awsSecretAccessKeyId, awsSessionToken);
}
private void setCredentials() throws IOException {
HttpExecuteResponse response = client.prepareRequest(request).call();
String credStr = IoUtils.toUtf8String(response.responseBody().get());
CredentialsJson credJson = gson.fromJson(credStr, CredentialsJson.class);
awsAccessKeyId = credJson.credentials.accessKeyId;
awsSecretAccessKeyId = credJson.credentials.secretAccessKey;
awsSessionToken = credJson.credentials.sessionToken;
}
}
Run Code Online (Sandbox Code Playgroud)
AWSSessionCredentialsProviderImpl credentialsProvider = new AWSSessionCredentialsProviderImpl();
credentialsProvider.init("someid");
s3Client = AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(credentialsProvider)
.build();
s3Client.putObject(request);
Run Code Online (Sandbox Code Playgroud)
我得到以下异常:
导致:
sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径
我不明白如果我能成功获得临时凭证,为什么会出现此异常。
这个问题可能与很多事情有关。
最有可能的是,您的 Java 程序将无法与远程对等方建立信任关系,这可能是因为 AWS CA 不是预配置的 JVM 可信 CA 之一。
我认为解决该问题的最佳方法是将SdkHttpClient
已有的信息也传递给 S3 客户端。
请注意,在您的示例代码中AmazonS3ClientBuilder
,您使用的是 AWS Java SDK 版本 1 类,同时其余代码使用的是 AWS SDK v2。
也许您可以将代码更新到最新版本的 S3Client并尝试如下操作:
System.setProperty("javax.net.ssl.trustStore", Configuration.KEYSTOREPATH_CA.toAbsolutePath().toString());
System.setProperty("javax.net.ssl.trustStoreType", "jks");
try {
System.setProperty("javax.net.ssl.trustStorePassword", new String(Files.readAllBytes(Configuration.KEYSTOREPATH_CA_PASS)));
} catch (IOException e) {
throw new IOException("Read password of trust store is failed", e);
}
System.setProperty("javax.net.ssl.keyStore", Configuration.KEYSTOREPATH.toAbsolutePath().toString());
System.setProperty("javax.net.ssl.keyStoreType", "jks");
try {
System.setProperty("javax.net.ssl.keyStorePassword", new String(Files.readAllBytes(Configuration.KEYSTOREPATH_PASS)));
} catch (IOException e) {
throw new IOException("Read password of key store is failed", e);
}
SdkHttpClient client = ApacheHttpClient.builder().build();
// The idea is reuse the configured HTTP client, modify it as per your needs
AWSSessionCredentialsProviderImpl credentialsProvider = new AWSSessionCredentialsProviderImpl(client);
credentialsProvider.init("someid");
S3Client s3 = S3Client.builder()
.httpClient(client)
.region(region)
.credentialsProvider(credentialsProvider)
.build();
Run Code Online (Sandbox Code Playgroud)
请确保您的信任存储区包含实际的 SSL 证书。您拥有AWS的根CA证书,但可能与实际服务不对应。
如有必要,您可以通过以下方式获取服务 SSL 证书:
System.setProperty("javax.net.ssl.trustStore", Configuration.KEYSTOREPATH_CA.toAbsolutePath().toString());
System.setProperty("javax.net.ssl.trustStoreType", "jks");
try {
System.setProperty("javax.net.ssl.trustStorePassword", new String(Files.readAllBytes(Configuration.KEYSTOREPATH_CA_PASS)));
} catch (IOException e) {
throw new IOException("Read password of trust store is failed", e);
}
System.setProperty("javax.net.ssl.keyStore", Configuration.KEYSTOREPATH.toAbsolutePath().toString());
System.setProperty("javax.net.ssl.keyStoreType", "jks");
try {
System.setProperty("javax.net.ssl.keyStorePassword", new String(Files.readAllBytes(Configuration.KEYSTOREPATH_PASS)));
} catch (IOException e) {
throw new IOException("Read password of key store is failed", e);
}
SdkHttpClient client = ApacheHttpClient.builder().build();
// The idea is reuse the configured HTTP client, modify it as per your needs
AWSSessionCredentialsProviderImpl credentialsProvider = new AWSSessionCredentialsProviderImpl(client);
credentialsProvider.init("someid");
S3Client s3 = S3Client.builder()
.httpClient(client)
.region(region)
.credentialsProvider(credentialsProvider)
.build();
Run Code Online (Sandbox Code Playgroud)
请根据您所在的地区更改命令。您需要从响应中提取 PEM 内容。
正如答案的评论中所示,另一种选择可以是取消设置System
在调用之前获取凭据时建立的属性S3Client
:
openssl s_client -connect s3.us-west-1.amazonaws.com:443
Run Code Online (Sandbox Code Playgroud)
它将为AWS SDK提供调用S3的全新环境。
归档时间: |
|
查看次数: |
13695 次 |
最近记录: |