How to Connect to Redis With the ElastiCache IAM Credential Provider

Redis is an open-source, in-memory data structure widely used to implement databases, caches, and message brokers, but it also satisfies other use cases. Amazon ElastiCache is a solution offered by Amazon Web Services (AWS) that simplifies the process of deploying, operating, and scaling in-memory caches in the Cloud. ElastiCache includes support for both Redis and Memcached distributed in-memory stores, as it enhances their many useful features and functionality.

Although Redis does not provide out-of-the-box support for the Java programming language, Java developers can work with Redis using a third-party Redis Java framework such as Redisson. Redisson is a Redis Java client that implements dozens of familiar Java constructs, classes, objects, interfaces, and services, making it easy for Java developers to get started.

Identity and access management (IAM) comprises a set of tools and processes to ensure that only certain people have access to the resources they need to do their jobs. IAM is a key security concern when working with AWS and other public Cloud providers.

Users can connect to Amazon ElastiCache for Redis using AWS IAM credentials. But what about users of third-party Redis Java clients like Redisson? The good news is that Redisson implements a version of AWS IAM authentication for Java Redis developers. Below is a code snippet illustrating how to connect to Redis with ElastiCache in Java and Redisson:

String userId = "AWS user id";
String region = "AWS region";
String rgId = "AWS replication group id";
IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userId, rgId, region);
AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain();
AWSAuthCredentialsProvider redisCredentialsProvider 
            = new AWSAuthCredentialsProvider(userId, iamAuthTokenRequest, awsCredentialsProvider);

Config c = new Config();
c.useClusterServers()
   .addNodeAddress("rediss://aws.redis.endpoint:port");
   .setCredentialsResolver(redisCredentialsProvider);

RedissonClient client = Redisson.create(c);

One important observation in the code above is the use of the AWSAuthCredentialsProvider class, which implements the CredentialsResolver interface. These are both Redisson-specific. The CredentialsResolver is invoked when creating a connection during Redis server authentication. The AWSAuthCredentialsProvider is a version of the CredentialsResolver interface that has been created specifically for AWS authentication.

Below is the full source code of the AWSAuthCredentialsProvider:

public class AWSAuthCredentialsProvider implements CredentialsResolver {

    private final String userName;
    private final IAMAuthTokenRequest iamAuthTokenRequest;
    private final AWSCredentialsProvider awsCredentialsProvider;

    private volatile CompletionStage future;
    private volatile Long lastTime = System.currentTimeMillis();

    public AWSAuthCredentialsProvider(String userName, IAMAuthTokenRequest iamAuthTokenRequest,
                                      AWSCredentialsProvider awsCredentialsProvider) {
        this.userName = userName;
        this.iamAuthTokenRequest = iamAuthTokenRequest;
        this.awsCredentialsProvider = awsCredentialsProvider;
    }

    @Override
    public CompletionStage resolve(InetSocketAddress address) {
        if (System.currentTimeMillis() - lastTime > 900*1000 || future == null) {
            try {
                String token = iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials());
                future = CompletableFuture.completedFuture(new Credentials(userName, token));
                lastTime = System.currentTimeMillis();
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException(e);
            }
        }
        return future;
    }

}

This class takes into account three parameters: the AWS username, an object that generates an IAM authentication token, and an object that provides the necessary AWS credentials (the access key and secret key). The resolve() method makes a request for new credentials every 900 seconds and returns a wrapper that contains the username and authentication token.

To use this setup, you will have to properly configure the dependencies in your Java project. Below is the necessary Maven dependency for connecting to Redis with the ElastiCache IAM credential provider in Redisson:

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-core</artifactId>
    <version>1.12.367</version>
</dependency>

If you are using Gradle instead, the required dependency is the following:

implementation "com.amazonaws:aws-java-sdk-core:1.12.341"
Similar articles