DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • AWS Cloud Security: Key Components, Common Vulnerabilities, and Best Practices
  • Setting Up CORS and Integration on AWS API Gateway Using CloudFormation
  • The Future of Rollouts: From Big Bang to Smart and Secure Approach to Web Application Deployments
  • Explore Redis for User Session Management on AWS Elasticache

Trending

  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems
  • How to Create a Successful API Ecosystem
  • Apple and Anthropic Partner on AI-Powered Vibe-Coding Tool – Public Release TBD
  • Code Reviews: Building an AI-Powered GitHub Integration
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Using IAM Authentication for Redis on AWS

Using IAM Authentication for Redis on AWS

In this article, learn how to securely connect your Go applications to Amazon MemoryDB (or ElastiCache) for Redis using IAM.

By 
Abhishek Gupta user avatar
Abhishek Gupta
DZone Core CORE ·
Dec. 07, 23 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
5.9K Views

Join the DZone community and get the full member experience.

Join For Free

Amazon MemoryDB for Redis has supported username/password-based authentication using Access Control Lists since the very beginning. But you can also use IAM-based authentication that allows you to associate IAM users and roles with MemoryDB users so that applications can use IAM credentials to authenticate to the MemoryDB cluster. With this authentication method, you don't need to use a (long-lived) user password. Instead, you use an authentication token generated using AWS Signature Version 4.

There are many benefits to this approach. Instead of managing username and password-based credentials, you can use IAM to centrally manage access to MemoryDB clusters. For client applications running on Amazon EC2, Amazon EKS, AWS Lambda, AWS App Runner, etc., you can inject these credentials (depending on the platform e.g. profile credentials in EC2 and instance role in App Runner) - this provides greater security.

MemoryDB documentation has an example for a Java application with the Lettuce client. The process is similar for other languages, but you still need to implement it. So, let's learn how to do it for a Go application with the widely used go-redis client.

As a bonus, this is also applicable to ElastiCache for Redis, which also supports IAM authentication. There are minor differences which I will list at the end of the blog.

Let's get started...

1. Configure the MemoryDB Cluster Along With User and IAM Role

Start by creating a MemoryDB user, Access Control list (ACL) and add the user to it. Make sure to use IAM as the authentication type.

Now, create the MemoryDB cluster. Make sure to choose version 7.0 or above and choose the ACL you created before.

Redis version compatibility

While the cluster is being provisioned, create an IAM role. Use the following Trust Relationship to allow connectivity from an EC2 instance:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Principal": {
                "Service": [
                    "ec2.amazonaws.com"
                ]
            }
        }
    ]
}


Use the following permissions: replace the MemoryDB cluster, IAM username, AWS account ID, and region.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                memorydb:Connect"
            ],
            "Resource": [
                "arn:aws:memorydb:<enter aws region>:<enter aws account ID>:cluster/<enter memorydb cluster name>",
                "arn:aws:memorydb:<enter aws region>:<enter aws account ID>:user/<enter memorydb iam user name>"
            ]
        }
    ]
}


2. Configure AWS Cloud9 Environment

Create an AWS Cloud9 environment to execute the client application that will connect to MemoryDB.

  • Make sure to use the same VPC and subnet as the MemoryDB cluster
  • Update the MemoryDB subnet group to add an inbound rule for the client application connectivity.

Refer to the Getting Started with Redis on AWS - the easy way! blog post that already has this covered.

3. Run the Client App

Once the MemoryDB cluster and Cloud9 instance are ready, go ahead and execute the client application.

Open the Cloud9 instance terminal, and clone the following GitHub repository:

git clone https://github.com/build-on-aws/aws-redis-iam-auth-golang
cd aws-redis-iam-auth-golang


Update the run.sh file to enter the MemoryDB cluster endpoint and username. For example:

export SERVICE_NAME=memorydb
export CLUSTER_NAME=demo-iam-cluster
export CLUSTER_ENDPOINT=clustercfg.demo-iam-cluster.xyzxy4.memorydb.us-west-1.amazonaws.com:6379
export USERNAME=demo-iam-user


Once the app is up and running, simply invoke its HTTP endpoints to verify that it works with IAM authentication.

curl -i -X POST -d '{"key":"foo1", "value":"bar2"}' localhost:8080
curl -i -X POST -d '{"key":"foo2", "value":"bar2"}' localhost:8080

curl -i localhost:8080/foo1

curl -i localhost:8080/not_there


The application is super simple. That's on purpose. Let's move on to the important bits, which is about the IAM authentication part.

IAM Authentication Logic: Behind the Scenes

You can refer to the authentication code in the GitHub repository.

1. We first create a HTTP GET request that contains the cluster name as part of the URL along with the username, the action (connect) and token expiry (900 seconds) as query parameters:

//...
  queryParams := url.Values{
    "Action":        {connectAction},
    "User":          {userName},
    "X-Amz-Expires": {strconv.FormatInt(int64(tokenValiditySeconds), 10)},
  }

  authURL := url.URL{
    Host:     clusterName,
    Scheme:   "http",
    Path:     "/",
    RawQuery: queryParams.Encode(),
  }

  req, err := http.NewRequest(http.MethodGet, authURL.String(), nil)
//...


2. The request is then signed using PresignHTTP:

func (atg AuthTokenGenerator) Generate() (string, error) {

    signedURL, _, err := atg.signer.PresignHTTP(
        context.Background(),
        atg.credentials,
        atg.req,
        hexEncodedSHA256EmptyString,
        atg.serviceName,
        atg.region,
        time.Now().UTC(),
    )

  //...
}


3. The token generator is invoked in a CredentialsProvider during client creation:

//...
    generator, err := auth.New(serviceName, clusterName, username, region)

    client = redis.NewClusterClient(
        &redis.ClusterOptions{
            Username: username,
            Addrs:    []string{clusterEndpoint},
            NewClient: func(opt *redis.Options) *redis.Client {

                return redis.NewClient(&redis.Options{
                    Addr: opt.Addr,

                    CredentialsProvider: func() (username string, password string) {
                        token, err := generator.Generate()
                        return opt.Username, token
                    },
                    TLSConfig: &tls.Config{InsecureSkipVerify: true},
                })
            },
        })
//...


This Can Also Be Used for ElastiCache!

The same approach applies - with a few changes. First, the IAM policy has to be updated to reflect ElastiCache resources (obviously!).

For example:

{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect" : "Allow",
        "Action" : [
          "elasticache:connect"
        ],
        "Resource" : [
          "arn:aws:elasticache:<enter aws region>:<enter aws account id>:<enter type - replicationgroup or serverlesscache>:<enter replicationgroup or serverlesscache name>",
          "arn:aws:elasticache:<enter aws region>:<enter aws account id>:user:<enter username>"
        ]
      }
    ]
  }


Before you run the application, update the SERVICE_NAME environment variable to elasticache as well as the endpoint URL, cluster name, and IAM username for the ElastiCache instance.

This example assumes you are using a Redis Cluster connection mode (which is the only option in the case of MemoryDB). But in the case of ElastiCache, be mindful of whether you are using cluster-mode-enabled configuration. If not, you will have to tweak the code to use redis.NewClient (instead of redis.NewClusterClient). The CredentialsProvider option will be available, nonetheless.

Conclusion

Using IAM authentication has its benefits. Instead of managing usernames and passwords in multiple locations/applications, delegate the heavy lifting to IAM. All you need is to provide configure appropriate permissions (principle of "least privilege").

But you also need to be aware of the limitations; e.g., IAM authentication is not supported in MULTI EXEC commands. For a complete list, refer to the documentation.

Have you tried using IAM authentication with MemoryDB or ElastiCache for Redis in other programming languages? Let me know.

Happy building!

AWS AWS Lambda authentication Redis (company) security

Published at DZone with permission of Abhishek Gupta, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • AWS Cloud Security: Key Components, Common Vulnerabilities, and Best Practices
  • Setting Up CORS and Integration on AWS API Gateway Using CloudFormation
  • The Future of Rollouts: From Big Bang to Smart and Secure Approach to Web Application Deployments
  • Explore Redis for User Session Management on AWS Elasticache

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!