Search code examples
javaaws-lambdasslcontext

Reuse SSLContext object in AWS Lambda Environment


I have a JAVA 8 AWS lambda function that has some pretty expensive setup when the container is first spun up. It must make calls to pull various credentials/cacerts. I would like to cache this set up (the output of which is an SSLContext object that is used for making calls to another api).

I have not had to do this before, and my question that I cannot seem to find an answer for is this:

Are there any issues reusing the SSLContext object over and over again while the Lambda Container is alive? this could be 15 minutes or 5 hours, or 2 days, etc.. as long as there is traffic coming through it, it will be alive.

None of the credentials will change, and the SSLContext object would be identical between all invocations.

Do SSLContext objects have a TTL? The code to create the SSLConext is fairly boilerplate. This method is called after I have done the expensive pulls to get the certs/cred and I want to cache this SSLContext object:

public SSLContext getContext(){
        KeyStore clientStore = KeyStore.getInstance(KEY_INSTANCE);
        keyStoreInputstream = //GET STREAM
        clientStore.load(keyStoreInputstream, caCertCred.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientStore, KEY.toCharArray());
        KeyManager[] kms = kmf.getKeyManagers();

        trustStoreInputStream =  //GET STREAM
        KeyStore trustStore = KeyStore.getInstance(TRUST_INSTANCE);
        trustStore.load(trustStoreInputStream, caCertCred.toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
        TrustManager[] tms = tmf.getTrustManagers();

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kms, tms, new SecureRandom());
        return sslContext;

}


Solution

  • The short answer: Use a class-level variable.

    In AWS Lambda, class level variables are "global" variables. So if you declare a variable outside the handleRequest(...) method, the Lambda container will keep that variable initialized with the same value. When the lambda function executes again, you just have to reuse the variable as it is.

    Here's an example of how it works:

    public class LambdaExample implements RequestStreamHandler {
    
        private LambdaLogger logger;
        private SSLContext sslContext;
    
        @Override
        public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
            logger = context.getLogger();
    
            // do some work
    
    
            if(sslContext == null) {
                // this means SSLContext needs to be initialized - probably a new container
                initSslContext();
            } else {
                // this means SSLContext is already initialized - just use it as it is
            }
    
            // use SSLContext
        }
    
        private void initSslContext() {
            // note: you need to create the KeyStore, KeyManagerFactory
            //  and re-initialize the SSLContext here because it's null
        }
    }
    

    Note:
    Usually, global variables have some downside but I think in your case, it wouldn't create any issues. You can watch the following video to really understand how global variables work in AWS Lambda.
    https://www.youtube.com/watch?v=-P7oB8NQpiI