Mr. Wonderful
Mr. Wonderful

Reputation: 199

How to call ssl endpoint fon AWS Lambda function

I have an AWS Lambda function that gets triggered by the Alexa command. On every Alexa command, I want to call an external API endpoint to do the desired operation.

I have a jar that calls the API and has the below externalService class with invokeCommand function. The jar has been added as a dependency under my Java project.

if(value.equals("something")) {
   externalService.invokeCommand();
   }

invokeCommand calls the external API which is protected by SSL certificate and throws an error

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

In Elastic Beanstalk I can create a zip folder with Jar, Keystore, and procfile and I can supply keystore as an argument in the procfile which will run the jar with the keystore and that'll allow access to SSL secured endpoint.

if(value.equals("something")) {
   externalService.invokeCommand(); // error on AWS Lambda
   }

However, I don't think I can do the same with Lambda which is not allowing me to call SSL secured endpoint.

Upvotes: 3

Views: 6920

Answers (2)

RAVI KUMAR
RAVI KUMAR

Reputation: 31

You have too create truststore programitically See below code for reference

        // Declare path of trust store and create file
        String trustStorePath = "/tmp/trust";
        // try creating above directory and path if you get error no such file 

        // Create Truststore using Key store api
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

        // locate the default truststore
        String filename = System.getProperty("java.home")
                + "/lib/security/cacerts".replace('/', File.separatorChar);

        try (FileInputStream fis = new FileInputStream(filename)) {

            keyStore.load(fis, "changeit".toCharArray());
        }

        // Add Certificate to Key store
        CertificateFactory certF = CertificateFactory.getInstance("X.509");
        Certificate cert = certF.generateCertificate(new FileInputStream("your certificate path"));
        keyStore.setCertificateEntry("any alias", cert);

        // Write Key Store
        try (FileOutputStream out = new FileOutputStream(trustStoreFile)) {
            keyStore.store(out, "changeit".toCharArray());
        }

        // Set Certificates to System properties
        System.setProperty("javax.net.ssl.trustStore", trustStorePath);
        System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

This you can test locally as well on aws lambda. Hope this will solve the issue

  • You can keep you certificate in s3 or keep it in resources of lambda directory

Upvotes: 1

Mr Chow
Mr Chow

Reputation: 372

I believe one option would be to package the certificates into the Jar/zip for your Lambda function itself which would put them on your classpath. Once they are on your classpath you can set them up programmatically using

    System.setProperty("javax.net.ssl.keyStore", KEYSTORE_FILE);
    System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE);
    System.setProperty("javax.net.ssl.keyStoreType", "JKS");
    System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_FILE);
    System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE);
    System.setProperty("javax.net.ssl.trustStoreType", "JKS");

Where you'd define KEYSTORE_FILE like

URL trustStoreResource = LdapConfig.class.getResource( "/keystore.jks" );
String KEYSTORE_FILE= trustStoreResource.toURI().getPath();
System.setProperty("javax.net.ssl.keyStore", KEYSTORE_FILE);

Upvotes: 0

Related Questions