简体   繁体   中英

AWS Secrets Manager Certificate issue

I am trying to run some java code to get a secret form AWS Secrets manager. The code is pretty basic.

    ClientConfiguration clientConfigurtion = new ClientConfiguration();
    clientConfigurtion.setProxyHost("myproxyhost");
    clientConfigurtion.setProxyPort(80);
    clientConfigurtion.setProxyUsername("XXX");
    clientConfigurtion.setProxyPassword("XXX");
    clientConfigurtion.setProxyProtocol(Protocol.HTTP);

    // Create a Secrets Manager client
    AWSSecretsManager client  = AWSSecretsManagerClientBuilder.standard()
            .withRegion(region).withClientConfiguration(clientConfigurtion)
            .build();

    // In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
    // See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
    // We rethrow the exception by default.

    String decodedBinarySecret;
    GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest()
            .withSecretId(secretName);
    GetSecretValueResult getSecretValueResult = null;

    try {
        getSecretValueResult = client.getSecretValue(getSecretValueRequest);
    } catch (DecryptionFailureException e) {
        // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw e;
    } catch (InternalServiceErrorException e) {
        // An error occurred on the server side.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw e;
    } catch (InvalidParameterException e) {
        // You provided an invalid value for a parameter.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw e;
    } catch (InvalidRequestException e) {
        // You provided a parameter value that is not valid for the current state of the resource.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw e;
    } catch (ResourceNotFoundException e) {
        // We can't find the resource that you asked for.
        // Deal with the exception here, and/or rethrow at your discretion.
        throw e;
    }

When I get to the line where it actually gets the secret value "getSecretValueResult = client.getSecretValue(getSecretValueRequest);"I get a stack trace.

In several places the trace contains this text.

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I assume that this means I'm missing some certificate but I don't know what to do to fix this.

I'm running this locally on a Mac.

Any help on getting around this certificate error is greatly appreciated.

I encountered the same issue and just got it working. The default truststore does not have a listing for https://secretsmanager.us-east-1.amazonaws.com . The way you can see the URL that the AWS client is trying to connect with (in your case it might be slightly different) is turn on the java system property javax.net.debug=all You can do that via command line or if using maven do it like this:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
            <configuration>
            <systemPropertyVariables>
                <javax.net.ssl.trustStore>c:\\path to your cert truststore\\cacerts</javax.net.ssl.trustStore>
                <javax.net.ssl.trustStorePassword>changeit</javax.net.ssl.trustStorePassword>

                <javax.net.debug>all</javax.net.debug>
                
            </systemPropertyVariables>
            </configuration>
        </plugin>  

Once you know the URL that the AWS client is trying to make the ssl handshake with (search the output/error log for "*** Certificate chain") and you'll see something like: *** Certificate chain chain [0] = [ [ Version: V3 Subject: CN=secretsmanager.us-east-1.amazonaws.com

Now the problem is getting this certificate. Pull up this URL in Chrome browser https://secretsmanager.us-east-1.amazonaws.com You'll have an error such as Missing Authentication Token

Then just hit F12 and then click on the security tab and download that certificate using the default values.

Now import that certificate into your Java truststore (I am using git bash shell if you are using DOS change the format of the paths accordingly):

$JAVA_HOME/bin/keytool -import -alias awsChromeCer2 -keystore /c/path to your keystore/cacerts -file /c/path to where you saved the certificate/awsChromeCert2.cer

verify it is there:

$JAVA_HOME/bin/keytool -list -keystore /c/path to your keystore/cacerts | grep aws

when it asks for a password the default might be: changeit

Now you should be able to run it successfully without getting this exception: com.amazonaws.SdkClientException: Unable to execute HTTP request: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Rather you will successfully retrieve the AWS secretsmanager secret that you were after. If you are using Maven ensure you have those variables defined like I put in the above section to point to your local truststore. Also ensure you have AWS credentials setup on your machine, but that is a separate issue.

I noticed the secretsmanager keys are rotating which means you have to download them close to the time when you will use it. If you want to automate that you could do something like this:

echo quit | openssl s_client -showcerts -servername secretsmanager.us-east-1.amazonaws.com -connect secretsmanager.us-east-1.amazonaws.com:443 > SM_cacert.pem

either edit the certificate (delete all the text after -----END CERTIFICATE----- just have one blank line after it)

OR

edit the certificate using code from bash shell

awk 'split_after == 1 {n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1}{print > "rds-ca-" n ".pem"}' < SM_cacert.pem

import the new certificate into your truststore

$JAVA_HOME/bin/keytool -import -alias awsFromOpenSsl -keystore /c/path to your truststore/cacerts -file /c/path to the new cert file/rds-ca-.pem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM