

# Data security in Amazon ElastiCache
<a name="encryption"></a>

To help keep your data secure, Amazon ElastiCache and Amazon EC2 provide mechanisms to guard against unauthorized access of your data on the server.

Amazon ElastiCache for Memcached provides encryption features for data on caches running Memcached versions 1.6.12 or later.

Amazon ElastiCache with Valkey and Redis OSS provides encryption features for data on caches running Valkey 7.2 or later, and Redis OSS versions 3.2.6 (scheduled for EOL, see [Redis OSS versions end of life schedule](engine-versions.md#deprecated-engine-versions)), 4.0.10 or later. Amazon ElastiCache also supports authenticating users with either IAM or Valkey and Redis OSS AUTH, and authorizing user operations using Role-Based Access Control (RBAC).
+ In-transit encryption encrypts your data whenever it is moving from one place to another, such as between nodes in your cluster or between your cache and your application.
+ At-rest encryption encrypts your on-disk data during sync and backup operations.

ElastiCache supports authenticating users using IAM and the Valkey and Redis OSS AUTH command, and authorizing user operations using Role-Based Access Control (RBAC).

![\[Image: ElastiCache for Valkey and Redis OSS Security Diagram\]](http://docs.aws.amazon.com/AmazonElastiCache/latest/dg/images/ElastiCache-Redis-Secure-Compliant.png)


*ElastiCache for Valkey and Redis OSS Security Diagram*

**Topics**
+ [ElastiCache in-transit encryption (TLS)](in-transit-encryption.md)
+ [At-Rest Encryption in ElastiCache](at-rest-encryption.md)
+ [Authentication and Authorization](auth-redis.md)

# ElastiCache in-transit encryption (TLS)
<a name="in-transit-encryption"></a>

To help keep your data secure, Amazon ElastiCache and Amazon EC2 provide mechanisms to guard against unauthorized access of your data on the server. By providing in-transit encryption capability, ElastiCache gives you a tool you can use to help protect your data when it is moving from one location to another. 

All Valkey or Redis OSS serverless caches have in-transit encryption enabled. For node-based clusters, you can enable in-transit encryption on a replication group by setting the parameter `TransitEncryptionEnabled` to `true` (CLI: `--transit-encryption-enabled`) when you create the replication group. You can do this whether you are creating the replication group using the AWS Management Console, the AWS CLI, or the ElastiCache API.

All serverless caches have in-transit encryption enabled. For node-based clusters, you can enable in-transit encryption on a cluster by setting the parameter `TransitEncryptionEnabled` to `true` (CLI: `--transit-encryption-enabled`) when you create the cluster using the `CreateCacheCluster` (CLI: `create-cache-cluster`) operation.

**Topics**
+ [In-transit encryption overview](#in-transit-encryption-overview)
+ [In-transit encryption conditions (Valkey and Redis OSS)](#in-transit-encryption-constraints)
+ [In-transit encryption conditions (Memcached)](#in-transit-encryption-constraints)
+ [In-transit encryption best practices](#in-transit-encryption-best-practices)
+ [Further Valkey and Redis OSS options](#in-transit-encryption-see-also)
+ [Enabling in-transit encryption for Memcached](#in-transit-encryption-enable-existing-mc)
+ [Enabling in-transit encryption](in-transit-encryption-enable.md)
+ [Connecting to ElastiCache (Valkey) or Amazon ElastiCache for Redis OSS with in-transit encryption using valkey-cli](connect-tls.md)
+ [Enabling in-transit encryption on a node-based Redis OSS cluster using Python](in-transit-encryption-enable-python.md)
+ [Best practices when enabling in-transit encryption](enable-python-best-practices.md)
+ [Connecting to nodes enabled with in-transit encryption using Openssl (Memcached)](#in-transit-encryption-connect-mc)
+ [Creating a TLS Memcached client using Java](#in-transit-encryption-connect-java)
+ [Creating a TLS Memcached client using PHP](#in-transit-encryption-connect-php-mc)

## In-transit encryption overview
<a name="in-transit-encryption-overview"></a>

Amazon ElastiCache in-transit encryption is a feature that allows you to increase the security of your data at its most vulnerable points—when it is in transit from one location to another. Because there is some processing needed to encrypt and decrypt the data at the endpoints, enabling in-transit encryption can have some performance impact. You should benchmark your data with and without in-transit encryption to determine the performance impact for your use cases.

ElastiCache in-transit encryption implements the following features:
+ **Encrypted client connections**—client connections to cache nodes are TLS encrypted.
+ **Encrypted server connections—**data moving between nodes in a cluster is encrypted.
+ **Server authentication**—clients can authenticate that they are connecting to the right server.
+ **Client authentication**—using the Valkey and Redis OSS AUTH feature, the server can authenticate the clients.

**Note**  
ElastiCache does not support mTLS (mutual TLS).

## In-transit encryption conditions (Valkey and Redis OSS)
<a name="in-transit-encryption-constraints"></a>

The following constraints on Amazon ElastiCache in-transit encryption should be kept in mind when you plan your node-based cluster implementation:
+ In-transit encryption is supported on replication groups running Valkey and Redis OSS.
+ Modifying the in-transit encryption setting, for an existing cluster, is supported on replication groups running Valkey 7.2 and later, and Redis OSS version 7 and later.
+ In-transit encryption is supported only for replication groups running in an Amazon VPC.
+ In-transit encryption is not supported for replication groups running the following node types: M1, M2.

  For more information, see [Supported node types](CacheNodes.SupportedTypes.md).
+ In-transit encryption is enabled by explicitly setting the parameter `TransitEncryptionEnabled` to `true`.
+ Ensure that your caching client supports TLS connectivity and that you have enabled it in client configuration. 
+ Starting April 28, 2026, AWS will update the minimum supported TLS version to 1.2 on ElastiCache for Valkey version 7.2 and above, and ElastiCache for Redis OSS version 6 and above. Customers must update their client software before that date. This update helps you meet security, compliance, and regulatory needs. 

## In-transit encryption conditions (Memcached)
<a name="in-transit-encryption-constraints"></a>

The following constraints on Amazon ElastiCache in-transit encryption should be kept in mind when you plan your node-based cluster implementation:
+ In-transit encryption is supported on clusters running Memcached versions 1.6.12 and later.
+ In-transit encryption supports Transport Layer Security (TLS) versions 1.2 and 1.3.
+ In-transit encryption is supported only for clusters running in an Amazon VPC.
+ In-transit encryption is not supported for replication groups running the following node types: M1, M2, M3, R3, T2.

  For more information, see [Supported node types](CacheNodes.SupportedTypes.md).
+ In-transit encryption is enabled by explicitly setting the parameter `TransitEncryptionEnabled` to `true`.
+ You can enable in-transit encryption on a cluster only when creating the cluster. You cannot toggle in-transit encryption on and off by modifying a cluster. 
+ Ensure that your caching client supports TLS connectivity and that you have enabled it in client configuration.

## In-transit encryption best practices
<a name="in-transit-encryption-best-practices"></a>
+ Because of the processing required to encrypt and decrypt the data at the endpoints, implementing in-transit encryption can reduce performance. Benchmark in-transit encryption compared to no encryption on your own data to determine its impact on performance for your implementation.
+ Because creating new connections can be expensive, you can reduce the performance impact of in-transit encryption by persisting your TLS connections.

## Further Valkey and Redis OSS options
<a name="in-transit-encryption-see-also"></a>

For further information on options available for Valkey and Redis OSS, see the followling links.
+ [At-Rest Encryption in ElastiCache](at-rest-encryption.md)
+ [Authenticating with the Valkey and Redis OSS AUTH command](auth.md)
+ [Role-Based Access Control (RBAC)](Clusters.RBAC.md)
+ [Amazon VPCs and ElastiCache security](VPCs.md)
+ [Identity and Access Management for Amazon ElastiCache](IAM.md)

## Enabling in-transit encryption for Memcached
<a name="in-transit-encryption-enable-existing-mc"></a>

To enable in-transit encryption when creating a Memcached cluster using the AWS Management Console, make the following selections:
+ Choose Memcached as your engine.
+ Choose engine version 1.6.12 or later.
+ Under **Encryption in transit**, choose **Enable**.

 For the step-by-step process, see [Creating a cluster for Valkey or Redis OSS](Clusters.Create.md). 

# Enabling in-transit encryption
<a name="in-transit-encryption-enable"></a>

All serverless caches have in-transit encryption enabled. On a node-based cluster, you can enable in-transit encryption using the AWS Management Console, the AWS CLI, or the ElastiCache API.

## Enabling in-transit encryption using the AWS Management Console
<a name="in-transit-encryption-enable-console"></a>

### Enabling in-transit encryption for a new node-based cluster using the AWS Management Console
<a name="in-transit-encryption-enable-con"></a>

When designing your own cluster, 'Dev/Test' and 'Production' configurations with the 'Easy create' method have in-transit encryption enabled. When choosing configuration yourself, make the following selections:
+ Click the checkbox next to **Enable** for the **Encryption in transit** option.

For the step-by-step process, see the following:
+ [Creating a Valkey (cluster mode disabled) cluster (Console)](SubnetGroups.designing-cluster-pre.valkey.md#Clusters.Create.CON.valkey-gs)
+ [Creating a Valkey or Redis OSS (cluster mode enabled) cluster (Console)](Clusters.Create.md#Clusters.Create.CON.RedisCluster)

### Enabling in-transit encryption for an existing node-based cluster using the AWS Management Console
<a name="in-transit-encryption-enable-existing"></a>

Enabling encryption in transit, is a two-step process, you must first set the transit encryption mode to `preferred`. This mode allows your Valkey or Redis OSS clients to connect using both encrypted and unencrypted connections. After you migrate all your Valkey or Redis OSS clients to use encrypted connections, you can then modify your cluster configuration to set the transit encryption mode to `required`. Setting the transit encryption mode to `required` will drop all unencrypted connections and will allow encrypted connections only.

**Set your **Transit encryption mode** to **Preferred****

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. Choose **Valkey caches** or **Redis OSS caches** from the ElastiCache **Resources** listed on the navigation pane, present on the left hand.

1. Choose the cache you want to update.

1. Choose the **Actions** dropdown, then choose **Modify**.

1. Choose **Enable** under **Encryption in transit** in the **Security** section.

1. Choose **Preferred** as the **Transit encryption mode**. 

1. Choose **Preview changes** and save your changes.

After you migrate all your Valkey or Redis OSS clients to use encrypted connections:

**Set your **Transit encryption mode** to **Required****

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. Choose **Valkey caches** or **Redis OSS caches** from the ElastiCache **Resources** listed on the navigation pane, present on the left hand.

1. Choose the cache you want to update.

1. Choose the **Actions** dropdown, then choose **Modify**.

1. Choose **Required** as the **Transit encryption mode**, in the **Security** section.

1. Choose **Preview changes** and save your changes.

## Enabling in-transit encryption using the AWS CLI
<a name="in-transit-encryption-enable-cli"></a>

To enable in-transit encryption when creating a Valkey or Redis OSS replication group using the AWS CLI, use the parameter `transit-encryption-enabled`.

### Enabling in-transit encryption on a new node-based cluster for Valkey or Redis OSS (Cluster Mode Disabled) (CLI)
<a name="in-transit-encryption-enable-cli-redis-classic-rg"></a>

Use the AWS CLI operation `create-replication-group` and the following parameters to create a Valkey or Redis OSS replication group with replicas that has in-transit encryption enabled:

**Key parameters:**
+ **--engine**—Must be `valkey` or `redis`.
+ **--transit-encryption-enabled**—Required. If you enable in-transit encryption, you must also provide a value for the `--cache-subnet-group` parameter.
+ **--num-cache-clusters**—Must be at least 1. The maximum value for this parameter is six.

For more information, see the following:
+ [Creating a Valkey or Redis OSS (Cluster Mode Disabled) replication group from scratch (AWS CLI)](Replication.CreatingReplGroup.NoExistingCluster.Classic.md#Replication.CreatingReplGroup.NoExistingCluster.Classic.CLI)
+ [create-replication-group](https://docs.aws.amazon.com/cli/latest/reference/elasticache/create-replication-group.html)

### Enabling in-transit encryption on a new node-based cluster for Valkey or Redis OSS (Cluster Mode Enabled) (CLI)
<a name="in-transit-encryption-enable-cli-redis-cluster"></a>

Use the AWS CLI operation `create-replication-group` and the following parameters to create a Valkey or Redis OSS (cluster mode enabled) replication group that has in-transit encryption enabled:

**Key parameters:**
+ **--engine**—Must be `valkey` or `redis`.
+ **--transit-encryption-enabled**—Required. If you enable in-transit encryption you must also provide a value for the `--cache-subnet-group` parameter.
+ Use one of the following parameter sets to specify the configuration of the replication group's node groups:
  + **--num-node-groups**—Specifies the number of shards (node groups) in this replication group. The maximum value of this parameter is 500.

    **--replicas-per-node-group**—Specifies the number of replica nodes in each node group. The value specified here is applied to all shards in this replication group. The maximum value of this parameter is 5.
  + **--node-group-configuration**—Specifies the configuration of each shard independently.

For more information, see the following:
+ [Creating a Valkey or Redis OSS (Cluster Mode Enabled) replication group from scratch (AWS CLI)](Replication.CreatingReplGroup.NoExistingCluster.Cluster.md#Replication.CreatingReplGroup.NoExistingCluster.Cluster.CLI)
+ [create-replication-group](https://docs.aws.amazon.com/cli/latest/reference/elasticache/create-replication-group.html)

### Enabling in-transit encryption for an existing cluster using the AWS CLI
<a name="in-transit-encryption-enable-cli-redis-cluster-existing-cli"></a>

Enabling encryption in transit, is a two-step process, you must first set the transit encryption mode to `preferred`. This mode allows your Valkey or Redis OSS clients to connect using both encrypted and unencrypted connections. After you migrate all your Valkey or Redis OSS clients to use encrypted connections, you can then modify your cluster configuration to set the transit encryption mode to `required`. Setting the transit encryption mode to `required` will drop all unencrypted connections and will allow encrypted connections only.

Use the AWS CLI operation `modify-replication-group` and the following parameters to update a Valkey or Redis OSS (cluster mode enabled) replication group that has in-transit encryption disabled.

**To enable in-transit encryption**

1. Set transit-encryption-mode to `preferred`, using the following parameters
   + **--transit-encryption-enabled**—Required.
   + **--transit-encryption-mode**—Must be set to `preferred`.

1. Set transit-encryption-mode to `required`, using the following parameters:
   + **--transit-encryption-enabled**—Required.
   + **--transit-encryption-mode**—Must be set to `required`.

# Connecting to ElastiCache (Valkey) or Amazon ElastiCache for Redis OSS with in-transit encryption using valkey-cli
<a name="connect-tls"></a>

To access data from ElastiCache for Redis OSS caches enabled with in-transit encryption, you use clients that work with Secure Socket Layer (SSL). You can also use valkey-cli with TLS/SSL on Amazon Linux and Amazon Linux 2. If your client does not support TLS, you can use the `stunnel` command on your client host to create an SSL tunnel to the Redis OSS nodes.

## Encrypted connection with Linux
<a name="connect-tls.linux"></a>

To use valkey-cli to connect to a Valkey or Redis OSS cluster enabled with in-transit encryption on Amazon Linux 2 or Amazon Linux, follow these steps.

1. Download and compile the valkey-cli utility. This utility is included in the Valkey software distribution.

1. At the command prompt of your EC2 instance, type the appropriate commands for the version of Linux you are using.

   **Amazon Linux 2**

   If using Amazon Linux 2, enter this:

   ```
   sudo yum -y install openssl-devel gcc
   wget -O valkey-7.2.6.tar.gz https://github.com/valkey-io/valkey/archive/refs/tags/7.2.6.tar.gz
   tar xvzf valkey-7.2.6.tar.gz
   cd valkey-7.2.6
   make distclean
   make valkey-cli BUILD_TLS=yes
   sudo install -m 755 src/valkey-cli /usr/local/bin/
   ```

   **Amazon Linux**

   If using Amazon Linux, enter this:

   ```
   sudo yum install gcc jemalloc-devel openssl-devel tcl tcl-devel clang wget
   wget -O valkey-8.0.0.tar.gz https://github.com/valkey-io/valkey/archive/refs/tags/8.0.0.tar.gz
   tar xvzf valkey-8.0.0.tar.gz
   cd valkey-8.0.0
   make valkey-cli CC=clang BUILD_TLS=yes
   sudo install -m 755 src/valkey-cli /usr/local/bin/
   ```

   On Amazon Linux, you may also need to run the following additional steps:

   ```
   sudo yum install clang
   CC=clang make
   sudo make install
   ```

1. After you have downloaded and installed the valkey-cli utility, it is recommended that you run the optional `make-test` command.

1. To connect to a cluster with encryption and authentication enabled, enter this command:

   ```
   valkey-cli -h Primary or Configuration Endpoint --tls -a 'your-password' -p 6379
   ```
**Note**  
If you install redis6 on Amazon Linux 2023, you can now use the command `redis6-cli` instead of `valkey-cli`:  

   ```
   redis6-cli -h Primary or Configuration Endpoint --tls -p 6379
   ```

## Encrypted connection with stunnel
<a name="connect-tls.stunnel"></a>

To use valkey-cli to connect to a Redis OSS cluster enabled with in-transit encryption using stunnel, follow these steps.

1. Use SSH to connect to your client and install `stunnel`.

   ```
   sudo yum install stunnel
   ```

1. Run the following command to create and edit file `'/etc/stunnel/valkey-cli.conf'` simultaneously to add a ElastiCache for Redis OSS cluster endpoint to one or more connection parameters, using the provided output below as template.

   ```
   vi /etc/stunnel/valkey-cli.conf
   
   				
   fips = no
   setuid = root
   setgid = root
   pid = /var/run/stunnel.pid
   debug = 7 
   delay = yes
   options = NO_SSLv2
   options = NO_SSLv3
   [valkey-cli]
      client = yes
      accept = 127.0.0.1:6379
      connect = primary.ssltest.wif01h.use1.cache.amazonaws.com:6379
   [valkey-cli-replica]
      client = yes
      accept = 127.0.0.1:6380
      connect = ssltest-02.ssltest.wif01h.use1.cache.amazonaws.com:6379
   ```

   In this example, the config file has two connections, the `valkey-cli` and the `valkey-cli-replica`. The parameters are set as follows:
   + **client** is set to yes to specify this stunnel instance is a client.
   + **accept** is set to the client IP. In this example, the primary is set to the Redis OSS default 127.0.0.1 on port 6379. The replica must call a different port and set to 6380. You can use ephemeral ports 1024–65535. For more information, see [Ephemeral ports](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html#VPC_ACLs_Ephemeral_Ports) in the *Amazon VPC User Guide.*
   + **connect** is set to the Redis OSS server endpoint. For more information, see [Finding connection endpoints in ElastiCache](Endpoints.md).

1. Start `stunnel`.

   ```
   sudo stunnel /etc/stunnel/valkey-cli.conf
   ```

   Use the `netstat` command to confirm that the tunnels started.

   ```
   sudo netstat -tulnp | grep -i stunnel
   				
   tcp        0      0 127.0.0.1:6379              0.0.0.0:*                   LISTEN      3189/stunnel        
   tcp        0      0 127.0.0.1:6380              0.0.0.0:*                   LISTEN      3189/stunnel
   ```

1. Connect to the encrypted Redis OSS node using the local endpoint of the tunnel.
   + If no AUTH password was used during ElastiCache for Redis OSS cluster creation, this example uses the valkey-cli to connect to the ElastiCache for Redis OSS server using complete path for valkey-cli, on Amazon Linux: 

     ```
     /home/ec2-user/redis-7.2.5/src/valkey-cli -h localhost -p 6379
     ```

     If AUTH password was used during Redis OSS cluster creation, this example uses valkey-cli to connect to the Redis OSS server using complete path for valkey-cli, on Amazon Linux: 

     ```
      /home/ec2-user/redis-7.2.5/src/valkey-cli -h localhost -p 6379 -a my-secret-password
     ```

   OR
   + Change directory to redis-7.2.5 and do the following:

     If no AUTH password was used during ElastiCache for Redis OSS cluster creation, this example uses the valkey-cli to connect to the ElastiCache for Redis OSS server using complete path for valkey-cli, on Amazon Linux: 

     ```
     src/valkey-cli -h localhost -p 6379
     ```

     If AUTH password was used during Redis OSS cluster creation, this example uses valkey-cli to connect to the Valkey or Redis OSS server using complete path for valkey-cli, on Amazon Linux: 

     ```
     src/valkey-cli -h localhost -p 6379 -a my-secret-password	
     ```

   This example uses Telnet to connect to the Valkey Redis OSS server.

   ```
   telnet localhost 6379
   			
   Trying 127.0.0.1...
   Connected to localhost.
   Escape character is '^]'.
   auth MySecretPassword
   +OK
   get foo
   $3
   bar
   ```

1. To stop and close the SSL tunnels, `pkill` the stunnel process.

   ```
   sudo pkill stunnel
   ```

# Enabling in-transit encryption on a node-based Redis OSS cluster using Python
<a name="in-transit-encryption-enable-python"></a>

The following guide will demonstrate how to enable in-transit encryption on a Redis OSS 7.0 cluster that was originally created with in-transit encryption disabled. TCP and TLS clients will continue communicating with the cluster during this process without downtime.

Boto3 will get the credentials it needs (`aws_access_key_id`, `aws_secret_access_key`, and `aws_session_token`) from the environment variables. Those credentials will be pasted in advance in the same bash terminal where we will run `python3` to process the Python code shown in this guide. The code in the example below was process from an EC2 instance that was launched in the same VPC that will be used to create the ElastiCache Redis OSS Cluster in it.

**Note**  
The following examples use the boto3 SDK for ElastiCache management operations (cluster or user creation) and redis-py/redis-py-cluster for data handling.
You must use at least boto3 version (=\$1) 1.26.39 to use the online TLS migration with the cluster modification API.
ElastiCache supports online TLS migration only for clusters with Valkey version 7.2 and above or Redis OSS version 7.0 or above. So if you have a cluster running a Redis OSS version earlier than 7.0, you’ll need to upgrade the Redis OSS version of your cluster. For more information on version differences, see [Major engine version behavior and compatibility differences with Redis OSS](VersionManagementConsiderations.md).

**Topics**
+ [Define the string constants that will launch the ElastiCache Valkey or Redis OSS Cluster](#enable-python-define-constants)
+ [Define the classes for the cluster configuration](#enable-python-define-classes)
+ [Define a class that will represent the cluster itself](#enable-python-define-classes-cluster)
+ [(Optional) Create a wrapper class to demo client connection to Valkey or Redis OSS cluster](#enable-python-create-wrapper)
+ [Create the main function that demos the process of changing in-transit encryption configuration](#enable-python-main-function)

## Define the string constants that will launch the ElastiCache Valkey or Redis OSS Cluster
<a name="enable-python-define-constants"></a>

First, let’s define some simple Python string constants that will hold the names of the AWS entities required to create the ElastiCache cluster such as `security-group`, `Cache Subnet group`, and a `default parameter group`. All of these AWS entities must be created in advance in your AWS account in the Region you are willing to use.

```
#Constants definitions 
SECURITY_GROUP = "sg-0492aa0a29c558427"
CLUSTER_DESCRIPTION = "This cluster has been launched as part of the online TLS migration user guide"
EC_SUBNET_GROUP = "client-testing"
DEFAULT_PARAMETER_GROUP_REDIS_7_CLUSTER_MODE_ENABLED = "default.redis7.cluster.on"
```

## Define the classes for the cluster configuration
<a name="enable-python-define-classes"></a>

Now, let’s define some simple Python classes that will represent a configuration of a cluster, which will hold metadata about the cluster such as the Valkey or Redis OSS version, the instance type, and whether in-transit encryption (TLS) is enabled or disabled.

```
#Class definitions

class Config:
    def __init__(
        self,
        instance_type: str = "cache.t4g.small",
        version: str = "7.0",
        multi_az: bool = True,
        TLS: bool = True,
        name: str = None,
    ):
        self.instance_type = instance_type
        self.version = version
        self.multi_az = multi_az
        self.TLS = TLS
        self.name = name or f"tls-test"

    def create_base_launch_request(self):
        return {
            "ReplicationGroupId": self.name,
            "TransitEncryptionEnabled": self.TLS,
            "MultiAZEnabled": self.multi_az,
            "CacheNodeType": self.instance_type,
            "Engine": "redis",
            "EngineVersion": self.version,
            "CacheSubnetGroupName": EC_SUBNET_GROUP ,
            "CacheParameterGroupName": DEFAULT_PARAMETER_GROUP_REDIS_7_CLUSTER_MODE_ENABLED ,
            "ReplicationGroupDescription": CLUSTER_DESCRIPTION,
            "SecurityGroupIds": [SECURITY_GROUP],
        }
        
class ConfigCME(Config):
    def __init__(
        self,
        instance_type: str = "cache.t4g.small",
        version: str = "7.0",
        multi_az: bool = True,
        TLS: bool = True,
        name: str = None,
        num_shards: int = 2,
        num_replicas_per_shard: int = 1,
    ):
        super().__init__(instance_type, version, multi_az, TLS, name)
        self.num_shards = num_shards
        self.num_replicas_per_shard = num_replicas_per_shard

    def create_launch_request(self) -> dict:
        launch_request = self.create_base_launch_request()
        launch_request["NumNodeGroups"] = self.num_shards
        launch_request["ReplicasPerNodeGroup"] = self.num_replicas_per_shard
        return launch_request
```

## Define a class that will represent the cluster itself
<a name="enable-python-define-classes-cluster"></a>

Now, let’s define some simple Python classes that will represent the ElastiCache Valkey or Redis OSS Cluster itself. This class will have a client field which will hold a boto3 client for ElastiCache management operations such as creating the cluster and querying the ElastiCache API.

```
import botocore.config
import boto3

# Create boto3 client
def init_client(region: str = "us-east-1"):
    config = botocore.config.Config(retries={"max_attempts": 10, "mode": "standard"})
    init_request = dict()
    init_request["config"] = config
    init_request["service_name"] = "elasticache"
    init_request["region_name"] = region
    return boto3.client(**init_request) 
 
 
class ElastiCacheClusterBase:
    def __init__(self, name: str):
        self.name = name
        self.elasticache_client = init_client()

    def get_first_replication_group(self):
        return self.elasticache_client.describe_replication_groups(
        ReplicationGroupId=self.name
        )["ReplicationGroups"][0]
 
    def get_status(self) -> str:
        return self.get_first_replication_group()["Status"]
 
    def get_transit_encryption_enabled(self) -> bool:
        return self.get_first_replication_group()["TransitEncryptionEnabled"]
 
    def is_available(self) -> bool:
        return self.get_status() == "available"
        
    def is_modifying(self) -> bool:
        return self.get_status() == "modifying"
        
    def wait_for_available(self):
        while True:
            if self.is_available():
                break
            else:
                time.sleep(5)

    def wait_for_modifying(self):
        while True:
            if self.is_modifying():
                break
            else:
                time.sleep(5)
                
    def delete_cluster(self) -> bool:
        self.elasticache_client.delete_replication_group(
            ReplicationGroupId=self.name, RetainPrimaryCluster=False
        )
        
    def modify_transit_encryption_mode(self, new_transit_encryption_mode: str):
        # generate api call to migrate the cluster to TLS preffered or to TLS required
            self.elasticache_client.modify_replication_group(
                ReplicationGroupId=self.name,
                TransitEncryptionMode=new_transit_encryption_mode,
                TransitEncryptionEnabled=True,
                ApplyImmediately=True,
            )  
        self.wait_for_modifying()
              
 class ElastiCacheClusterCME(ElastiCacheClusterBase):
    def __init__(self, name: str):
        super().__init__(name)

    @classmethod
    def launch(cls, config: ConfigCME = None) -> ElastiCacheClusterCME:
        config = config or ConfigCME()
        print(config)
        new_cluster = ElastiCacheClusterCME(config.name)
        launch_request = config.create_launch_request()
        new_cluster.elasticache_client.create_replication_group(**launch_request)
        new_cluster.wait_for_available()
        return new_cluster

    def get_configuration_endpoint(self) -> str:
        return self.get_first_replication_group()["ConfigurationEndpoint"]["Address"]
     
#Since the code can throw exceptions, we define this class to make the code more readable and 
#so we won't forget to delete the cluster    
class ElastiCacheCMEManager:
    def __init__(self, config: ConfigCME = None):
        self.config = config or ConfigCME()

    def __enter__(self) -> ElastiCacheClusterCME:
        self.cluster = ElastiCacheClusterCME.launch(self.config)
        return self.cluster 
          
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cluster.delete_cluster()
```

## (Optional) Create a wrapper class to demo client connection to Valkey or Redis OSS cluster
<a name="enable-python-create-wrapper"></a>

Now, let’s create a wrapper class for the `redis-py-cluster` client. This wrapper class will support pre-filling the cluster with some keys and then doing random repeated `get` commands.

**Note**  
This is an optional step but it simplifies the code of the main function that comes in a later step.

```
import redis
improt random
from time import perf_counter_ns, time


class DowntimeTestClient:
    def __init__(self, client):
        self.client = client

        # num of keys prefilled
        self.prefilled = 0
        # percent of get above prefilled
        self.percent_get_above_prefilled = 10 # nil result expected when get hit above prefilled
        # total downtime in nano seconds 
        self.downtime_ns = 0
        # num of success and fail operations
        self.success_ops = 0
        self.fail_ops = 0
        self.connection_errors = 0
        self.timeout_errors = 0
        

    def replace_client(self, client):
        self.client = client

    def prefill_data(self, timelimit_sec=60):
        end_time = time() + timelimit_sec
        while time() < end_time:
            self.client.set(self.prefilled, self.prefilled)
            self.prefilled += 1

    # unsuccesful operations throw exceptions
    def _exec(self, func):
        try:
            start_ns = perf_counter_ns()
            func()
            self.success_ops += 1
            elapsed_ms = (perf_counter_ns() - start_ns) // 10 ** 6
            # upon succesful execution of func
            # reset random_key to None so that the next command
            # will use a new random key
            self.random_key = None

        except Exception as e:
            elapsed_ns = perf_counter_ns() - start_ns
            self.downtime_ns += elapsed_ns
            # in case of failure- increment the relevant counters so that we will keep track 
            # of how many connection issues we had while trying to communicate with
            # the cluster.
            self.fail_ops += 1
            if e.__class__ is redis.exceptions.ConnectionError:
                self.connection_errors += 1
            if e.__class__ is redis.exceptions.TimeoutError:
                self.timeout_errors += 1

    def _repeat_exec(self, func, seconds):
        end_time = time() + seconds
        while time() < end_time:
            self._exec(func)

    def _new_random_key_if_needed(self, percent_above_prefilled):
        if self.random_key is None:
            max = int((self.prefilled * (100 + percent_above_prefilled)) / 100)
            return random.randint(0, max)
        return self.random_key

    def _random_get(self):
        key = self._new_random_key_if_needed(self.percent_get_above_prefilled)
        result = self.client.get(key)
        # we know the key was set for sure only in the case key < self.prefilled
        if key < self.prefilled:
            assert result.decode("UTF-8") == str(key)


    def repeat_get(self, seconds=60):
        self._repeat_exec(self._random_get, seconds)

    def get_downtime_ms(self) -> int:
        return self.downtime_ns // 10 ** 6


    def do_get_until(self, cond_check):
        while not cond_check():
            self.repeat_get()
        # do one more get cycle once condition is met
        self.repeat_get()
```

## Create the main function that demos the process of changing in-transit encryption configuration
<a name="enable-python-main-function"></a>

Now, let’s define the main function, which will do the following:

1. Create the cluster using boto3 ElastiCache client.

1. Initialize the `redis-py-cluster` client that will connect to the cluster with a clear TCP connection without TLS.

1. The `redis-py-cluster` client prefills the cluster with some data. 

1. The boto3 client will trigger TLS migration from no-TLS to TLS preferred.

1. While the cluster is being migrated to TLS `Preferred`, the `redis-py-cluster` TCP client will send repeated `get` operations to the cluster until the migration is finished.

1. After the migration to TLS `Preferred` is finished, we will assert that the cluster supports in-transit encryption. Afterwards, we will create a `redis-py-cluster` client that will connect to the cluster with TLS.

1. We will send some `get` commands using the new TLS client and the old TCP client.

1. The boto3 client will trigger TLS migration from TLS `Preferred` to TLS required.

1. While the cluster is being migrated to TLS required, the redis-py-cluster TLS client will send repeated `get` operations to the cluster until the migration is finished.

```
import redis

def init_cluster_client(
    cluster: ElastiCacheClusterCME, prefill_data: bool, TLS: bool = True) -> DowntimeTestClient:
    # we must use for the host name the cluster configuration endpoint. 
    redis_client = redis.RedisCluster(
        host=cluster.get_configuration_endpoint(), ssl=TLS, socket_timeout=0.25, socket_connect_timeout=0.1
    )
    test_client = DowntimeTestClient(redis_client)
    if prefill_data:
        test_client.prefill_data()
    return test_client

if __name__ == '__main__':
    config = ConfigCME(TLS=False, instance_type="cache.m5.large")

    with ElastiCacheCMEManager(config) as cluster:
        # create a client that will connect to the cluster with clear tcp connection
        test_client_tcp = init_cluster_client(cluster, prefill_data=True, TLS=False)
        
       # migrate the cluster to TLS Preferred
        cluster.modify_transit_encryption_mode(new_transit_encryption_mode="preferred")
        
        # do repeated get commands until the cluster finishes the migration to TLS Preferred
        test_client_tcp.do_get_until(cluster.is_available)
        
       # verify that in transit encryption is enabled so that clients will be able to connect to the cluster with TLS
        assert cluster.get_transit_encryption_enabled() == True
        
       # create a client that will connect to the cluster with TLS connection. 
        # we must first make sure that the cluster indeed supports TLS
        test_client_tls = init_cluster_client(cluster, prefill_data=True, TLS=True)
        
        # by doing get commands with the tcp client for 60 more seconds
       # we can verify that the existing tcp connection to the cluster still works 
        test_client_tcp.repeat_get(seconds=60)
        
        # do get commands with the new TLS client for 60 more seconds
        test_client_tcp.repeat_get(seconds=60)
        
       # migrate the cluster to TLS required
        cluster.modify_transit_encryption_mode(new_transit_encryption_mode="required")
        
       # from this point the tcp clients will be disconnected and we must not use them anymore.
       # do get commands with the TLS client until the cluster finishes migartion to TLS required mode.
        test_client_tls.do_get_until(cluster.is_available)
```

# Best practices when enabling in-transit encryption
<a name="enable-python-best-practices"></a>

## Before enabling in-transit encryption: make sure you have proper DNS records handling
<a name="enable-python-best-practices-before"></a>

**Note**  
We are changing and deleting old endpoints during this process. Incorrect usage of the endpoints can result in the Valkey or Redis OSS client using old and deleted endpoints that will prevent it from connecting to the cluster.

While the cluster is being migrated from no-TLS to TLS-preferred, the old cluster configuration endpoint DNS record is kept and the new cluster configuration endpoint DNS records are being generated in a different format. TLS-enabled clusters use a different format of DNS records than TLS-disabled clusters. ElastiCache will keep both DNS records when a cluster is configured in `encryption mode: Preferred` so that Applications and other Valkey or Redis OSS clients can switch between them. The following changes in the DNS records take place during the TLS-migration process:

### Description of the changes in the DNS records that take place when enabling in-transit encryption
<a name="enable-python-best-practices-before-desc"></a>

**For CME clusters**

When a cluster is set to ‘transit encryption mode: preferred’:
+ The original cluster configuration endpoint for no-TLS cluster will remain active. There will be no downtime when cluster is re-configured form TLS encryption mode ‘none’ to ‘preferred’.
+ New TLS Valkey or Redis OSS endpoints will be generated when cluster is set to TLS-preferred mode. These new endpoints will resolve to the same IPs as the old ones (non-TLS).
+ The new TLS Valkey or Redis OSS configuration endpoint will be exposed in the ElastiCache Console and in the response to `describe-replication-group` API.

When a cluster is set to ‘transit encryption mode: required’:
+ Old non-TLS enabled endpoints will be deleted. There will be no downtime of TLS cluster endpoints.
+ You can retrieve a new `cluster-configuration-endpoint` from ElastiCache Console or from the `describe-replication-group` API.

**For CMD clusters with Automatic Failover enabled or Automatic Failover disabled**

When replication group is set to ‘transit encryption mode: preferred’:
+ The original primary endpoint and reader endpoint for non-TLS enabled cluster will remain active.
+ New TLS primary and reader endpoints will be generated when cluster is set to TLS `Preferred` mode. This new endpoints will resolve to the same IP(s) as the old ones (non-TLS).
+ The new primary endpoint and reader endpoint will be exposed in the ElastiCache Console and in the response to the `describe-replication-group` API. 

When replication group is set to ‘transit encryption mode: required’:
+ Old non-TLS primary and reader endpoints will be deleted. There will be no downtime of TLS cluster endpoints. 
+ You can retrieve new primary and reader endpoints from ElastiCache Console or from the `describe-replication-group` API.

### The suggested usage of the DNS records
<a name="enable-python-best-practices-before-usage"></a>

**For CME clusters **
+ Use the cluster configuration endpoint instead of per-node DNS records in your application’s code. Using per-node DNS names directly is not recommended because during migration they will change and the application code will break connection to the cluster.
+ Don't hardcode a cluster configuration endpoint in your application, as it will change during this process.
+ Having the cluster configuration endpoint hardcoded in your application is a bad practice, since it can be changed during this process. After the in-transit encryption is completed, query the cluster configuration endpoint with the `describe-replication-group` API (as demonstrated above (in bold)) and use the DNS you get in response from that point on.

**For CMD clusters with Automatic Failover enabled **
+ Use the primary endpoint and reader endpoint instead of the per-node DNS names in your application’s code since the old per-node DNS names are deleted and new ones are generated when migrating the cluster from no-TLS to TLS-preferred. Using per-node DNS names directly is not recommended because you might add replicas to your cluster in the future. Also, when Automatic Failover is enabled, the roles of the primary cluster and replicas are changed automatically by the ElastiCache service, using the primary endpoint and reader endpoint is suggested to help you keep track of those changes. Lastly, using the reader endpoint will help you distribute your reads from the replicas equally between the replicas in the cluster.
+ Having the primary endpoint and reader endpoint hardcoded in your application is a bad practice since it can be changed during the TLS migration process. After the migration change to TLS-preferred is completed, query the primary endpoint and reader endpoint endpoint with the describe-replication-group API and use the DNS you get in response from this point on. This way you will be able to keep track of changes in endpoints in a dynamic way.

**For CMD cluster with Automatic Failover disabled **
+ Use the primary endpoint and reader endpoint instead of the per-node DNS names in your application’s code. When Automatic Failover is disabled, scaling, patching, failover, and other procedures that are managed automatically by the ElastiCache service when Automatic Failover is enabled are done by you instead. This makes it easier for you to manually keep track of the different endpoints. Since the old per-node DNS names are deleted and new ones are generated when migrating the cluster from no-TLS to TLS-preferred, do not use the per-node DNS names directly. This is mandatory so that clients will be able to connect to the cluster during the TLS-migration. Also, you’ll benefit from evenly spreading the reads between the replicas when using the reader endpoint and keep track of the DNS-records when adding or deleting replicas form the cluster.
+ Having the cluster configuration endpoint hardcoded in your application is a bad practice since it can be changed during the TLS migration process.

## During the in-transit encryption: pay attention to when the migration process finishes
<a name="enable-python-best-practices-during"></a>

Change of transit encryption mode is not immediate and can take some time. This is especially true for large clusters. Only when the cluster finishes the migration to TLS-preferred is it able to accept and serve both TCP and TLS connections. Therefore, you should not create clients that will try to establish TLS connections to the cluster until the in-transit encryption is completed.

There are several ways to get notified when the in-transit encryption is completed successfully or failed: (Not shown in the code example above):
+ Using the SNS service to get a notification when the encryption is completed
+ Using the `describe-events` API that will emit an event when the encryption is completed
+ Seeing a message in the ElastiCache Console that the encryption is completed

You can also implement logic in your application to know if the encryption is completed. In the example above, we saw several ways to ensure the cluster finishes the migration:
+ Waiting until the migration process starts (the cluster status changes to “modifying“), and waiting until the modification is finished (the cluster status changes back to “available“)
+ Asserting that the cluster has `transit_encryption_enabled` set to True by querying the `describe-replication-group` API.

### After enabling in-transit encryption: make sure the clients you use are configured properly
<a name="enable-python-best-practices-after"></a>

While the cluster is in TLS-preferred mode, your application should open TLS connections to the cluster and only use those connections. This way your application will not experience downtime when enabling in-transit encryption. You can make sure that there are no clearer TCP connections to the Valkey or Redis OSS engine using the info command under the SSL section.

```
# SSL
ssl_enabled:yes
ssl_current_certificate_not_before_date:Mar 20 23:27:07 2017 GMT
ssl_current_certificate_not_after_date:Feb 24 23:27:07 2117 GMT
ssl_current_certificate_serial:D8C7DEA91E684163
tls_mode_connected_tcp_clients:0   (should be zero)
tls_mode_connected_tls_clients:100
```

## Connecting to nodes enabled with in-transit encryption using Openssl (Memcached)
<a name="in-transit-encryption-connect-mc"></a>

To access data from ElastiCache for Memcached nodes enabled with in-transit encryption, you need to use clients that work with Secure Socket Layer (SSL). You can also use Openssl s\$1client on Amazon Linux and Amazon Linux 2. 

To use Openssl s\$1client to connect to a Memcached cluster enabled with in-transit encryption on Amazon Linux 2 or Amazon Linux:

```
/usr/bin/openssl s_client -connect memcached-node-endpoint:memcached-port
```

## Creating a TLS Memcached client using Java
<a name="in-transit-encryption-connect-java"></a>

To create a client in TLS mode, do the following to initialize the client with the appropriate SSLContext:

```
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.ConnectionFactoryBuilder;
import net.spy.memcached.MemcachedClient;
public class TLSDemo {
    public static void main(String[] args) throws Exception {
        ConnectionFactoryBuilder connectionFactoryBuilder = new ConnectionFactoryBuilder();
        // Build SSLContext
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init((KeyStore) null);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        // Create the client in TLS mode
        connectionFactoryBuilder.setSSLContext(sslContext);
        MemcachedClient client = new MemcachedClient(connectionFactoryBuilder.build(), AddrUtil.getAddresses("mycluster.fnjyzo.cfg.use1.cache.amazonaws.com:11211"));

        // Store a data item for an hour.
        client.set("theKey", 3600, "This is the data value");
    }
}
```

## Creating a TLS Memcached client using PHP
<a name="in-transit-encryption-connect-php-mc"></a>

To create a client in TLS mode, do the following to initialize the client with the appropriate SSLContext:

```
<?php

/**
 * Sample PHP code to show how to create a TLS Memcached client. In this example we
 * will use the Amazon ElastiCache Auto Descovery feature, but TLS can also be
 * used with a Static mode client. 
 * See Using the ElastiCache Cluster Client for PHP (https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/AutoDiscovery.Using.ModifyApp.PHP.html) for more information 
 * about Auto Discovery and persistent-id.
 */

/* Configuration endpoint to use to initialize memcached client.
 * this is only an example */
$server_endpoint = "mycluster.fnjyzo.cfg.use1.cache.amazonaws.com";

/* Port for connecting to the cluster. 
 * This is only an example     */
$server_port = 11211;

/* Initialize a persistent Memcached client and configure it with the Dynamic client mode  */
$tls_client =  new Memcached('persistent-id');
$tls_client->setOption(Memcached::OPT_CLIENT_MODE, Memcached::DYNAMIC_CLIENT_MODE);

/* Add the memcached's cluster server/s */
$tls_client->addServer($server_endpoint, $server_port);

/* Configure the client to use TLS */
if(!$tls_client->setOption(Memcached::OPT_USE_TLS, 1)) {
    echo $tls_client->getLastErrorMessage(), "\n";
    exit(1);
}

/* Set your TLS context configurations values.
 * See MemcachedTLSContextConfig in memcached-api.php for all configurations */
$tls_config = new MemcachedTLSContextConfig();
$tls_config->hostname = '*.mycluster.fnjyzo.use1.cache.amazonaws.com';
$tls_config->skip_cert_verify = false;
$tls_config->skip_hostname_verify = false;

/* Use the created TLS context configuration object to create OpenSSL's SSL_CTX and set it to your client.
 * Note:  These TLS context configurations will be applied to all the servers connected to this client. */
$tls_client->createAndSetTLSContext((array)$tls_config);

/* test the TLS connection with set-get scenario: */

 /* store the data for 60 seconds in the cluster.
 * The client will decide which cache host will store this item.
 */
if($tls_client->set('key', 'value', 60)) {
    print "Successfully stored key\n";
} else {
    echo "Failed to set key: ", $tls_client->getLastErrorMessage(), "\n";
    exit(1);
}

/* retrieve the key */
if ($tls_client->get('key') === 'value') {
    print "Successfully retrieved key\n";
} else {
    echo "Failed to get key: ", $tls_client->getLastErrorMessage(), "\n";
    exit(1);
}
```

For more information on using the PHP client, see [Installing the ElastiCache cluster client for PHP](Appendix.PHPAutoDiscoverySetup.md).

# At-Rest Encryption in ElastiCache
<a name="at-rest-encryption"></a>

To help keep your data secure, Amazon ElastiCache and Amazon S3 provide different ways to restrict access to data in your cache. For more information, see [Amazon VPCs and ElastiCache security](VPCs.md) and [Identity and Access Management for Amazon ElastiCache](IAM.md).

ElastiCache at-rest encryption is a feature to increase data security by encrypting on-disk data. It is always enabled on a serverless cache. When enabled, it encrypts the following aspects:
+ Disk during sync, backup and swap operations
+ Backups stored in Amazon S3 

Data stored on SSDs (solid-state drives) in data tiering enabled clusters is always encrypted.

 ElastiCache offers default (service managed) encryption at rest, as well as ability to use your own symmetric customer managed AWS KMS keys in [AWS Key Management Service (KMS)](https://docs.aws.amazon.com/kms/latest/developerguide/overview.html). When the cache is backed up, under encryption options, choose whether to use the default encryption key or a customer-managed key. For more information, see [Enabling At-Rest Encryption](#at-rest-encryption-enable).

**Important**  
Enabling At-Rest Encryption on an existing node-based Valkey or Redis OSS cluster involves deleting your existing replication group, **after** running backup and restore on the replication group.

At-rest encryption can be enabled on a cache only when it is created. Because there is some processing needed to encrypt and decrypt the data, enabling at-rest encryption can have a performance impact during these operations. You should benchmark your data with and without at-rest encryption to determine the performance impact for your use cases. 

**Topics**
+ [At-Rest Encryption Conditions](#at-rest-encryption-constraints)
+ [Using customer managed keys from AWS KMS](#using-customer-managed-keys-for-elasticache-security)
+ [Enabling At-Rest Encryption](#at-rest-encryption-enable)
+ [See Also](#at-rest-encryption-see-also)

## At-Rest Encryption Conditions
<a name="at-rest-encryption-constraints"></a>

The following constraints on ElastiCache at-rest encryption should be kept in mind when you plan your implementation of ElastiCache encryption at-rest:
+ At-rest encryption is supported on replication groups running Valkey 7.2 and later, and Redis OSS versions (3.2.6 scheduled for EOL, see [Redis OSS versions end of life schedule](engine-versions.md#deprecated-engine-versions)), 4.0.10 or later.
+ At-rest encryption is supported only for replication groups running in an Amazon VPC.
+ At-rest encryption is only supported for replication groups running the following node types.
  + R7g, R6gd, R6g, R5, R4, R3
  + M7g, M6g, M5, M4, M3
  + T4g, T3, T2
  + C7gn

  For more information, see [Supported node types](CacheNodes.SupportedTypes.md)
+ At-rest encryption is enabled by setting the parameter `AtRestEncryptionEnabled` to `true`. For Valkey, this parameter defaults to `true` if not specified.
+ You can enable at-rest encryption on a replication group only when creating the replication group. You cannot toggle at-rest encryption on and off by modifying a replication group. For information on implementing at-rest encryption on an existing replication group, see [Enabling At-Rest Encryption](#at-rest-encryption-enable).
+ If a cluster is using a node type from the r6gd family, data stored on SSD is encrypted whether at-rest encryption is enabled or not.
+ The option to use customer managed key for encryption at rest is not available in AWS GovCloud (us-gov-east-1 and us-gov-west-1) regions. 
+ If a cluster is using a node type from the r6gd family, data stored on SSD is encrypted with the chosen customer managed AWS KMS key (or service-managed encryption in AWS GovCloud Regions).
+ With Memcached, at-rest encryption is supported only on serverless caches.
+ When using Memcached, the option to use customer managed key for encryption at rest is not available in AWS GovCloud (us-gov-east-1 and us-gov-west-1) regions. 

Implementing at-rest encryption can reduce performance during backup and node sync operations. Benchmark at-rest encryption compared to no encryption on your own data to determine its impact on performance for your implementation.

## Using customer managed keys from AWS KMS
<a name="using-customer-managed-keys-for-elasticache-security"></a>

ElastiCache supports symmetric customer managed AWS KMS keys (KMS key) for encryption at rest. Customer-managed KMS keys are encryption keys that you create, own and manage in your AWS account. For more information, see [AWS KMS keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#root_keys) in the *AWS Key Management Service Developer Guide*. The keys must be created in AWS KMS before they can be used with ElastiCache.

To learn how to create AWS KMS root keys, see [Creating Keys](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html) in the *AWS Key Management Service Developer Guide*. 

ElastiCache allows you to integrate with AWS KMS. For more information, see [Using Grants](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html) in the *AWS Key Management Service Developer Guide*. No customer action is needed to enable Amazon ElastiCache integration with AWS KMS. 

The `kms:ViaService` condition key limits use of an AWS KMS key (KMS key) to requests from specified AWS services. To use `kms:ViaService` with ElastiCache, include both ViaService names in the condition key value: `elasticache.AWS_region.amazonaws.com` and `dax.AWS_region.amazonaws.com`. For more information, see [kms:ViaService](https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-kms-via-service).

You can use [AWS CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html) to track the requests that Amazon ElastiCache sends to AWS Key Management Service on your behalf. All API calls to AWS Key Management Service related to customer managed keys have corresponding CloudTrail logs. You can also see the grants that ElastiCache creates by calling the [ListGrants](https://docs.aws.amazon.com/kms/latest/APIReference/API_ListGrants.html) KMS API call. 

Once a replication group is encrypted using customer managed key, all backups for the replication group are encrypted as follows:
+ Automatic daily backups are encrypted using the customer managed key associated with the cluster.
+ Final backup created when replication group is deleted, is also encrypted using the customer managed key associated with the replication group.
+ Manually created backups are encrypted by default to use the KMS key associated with the replication group. You may override this by choosing another customer managed key.
+ Copying a backup defaults to using a customer managed key associated with the source backup. You may override this by choosing another customer managed key.

**Note**  
Customer managed keys cannot be used when exporting backups to your selected Amazon S3 bucket. However, all backups exported to Amazon S3 are encrypted using [Server side encryption.](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html) You may choose to copy the backup file to a new S3 object and encrypt using a customer managed KMS key, copy the file to another S3 bucket that is set up with default encryption using a KMS key or change an encryption option in the file itself.
You can also use customer managed keys to encrypt manually-created backups for replication groups that do not use customer managed keys for encryption. With this option, the backup file stored in Amazon S3 is encrypted using a KMS key, even though the data is not encrypted on the original replication group. 
Restoring from a backup allows you to choose from available encryption options, similar to encryption choices available when creating a new replication group.
+ If you delete the key or [disable](https://docs.aws.amazon.com/kms/latest/developerguide/enabling-keys.html) the key and [revoke grants](https://docs.aws.amazon.com/kms/latest/APIReference/API_RevokeGrant.html) for the key that you used to encrypt a cache, the cache becomes irrecoverable. In other words, it cannot be modified or recovered after a hardware failure. AWS KMS deletes root keys only after a waiting period of at least seven days. After the key is deleted, you can use a different customer managed key to create a backup for archival purposes. 
+ Automatic key rotation preserves the properties of your AWS KMS root keys, so the rotation has no effect on your ability to access your ElastiCache data. Encrypted Amazon ElastiCache caches don't support manual key rotation, which involves creating a new root key and updating any references to the old key. To learn more, see [Rotating AWS KMS keys](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html) in the *AWS Key Management Service Developer Guide*. 
+ Encrypting an ElastiCache cache using KMS key requires one grant per cache. This grant is used throughout the lifespan of the cache. Additionally, one grant per backup is used during backup creation. This grant is retired once the backup is created. 
+ For more information on AWS KMS grants and limits, see [Limits](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html) in the *AWS Key Management Service Developer Guide*.

## Enabling At-Rest Encryption
<a name="at-rest-encryption-enable"></a>

All serverless caches have at-rest encryption enabled.

When creating a node-based cluster, you can enable at-rest encryption by setting the parameter `AtRestEncryptionEnabled` to `true`. You can't enable at-rest encryption on existing replication groups.

 You can enable at-rest encryption when you create an ElastiCache cache. You can do so using the AWS Management Console, the AWS CLI, or the ElastiCache API.

When creating a cache, you can pick one of the following options:
+ **Default** – This option uses service managed encryption at rest. 
+ **Customer managed key ** – This option allows you to provide the Key ID/ARN from AWS KMS for encryption at rest. 

To learn how to create AWS KMS root keys, see [Create Keys](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html) in the *AWS Key Management Service Developer Guide* 

**Contents**
+ [Enabling At-Rest Encryption Using the AWS Management Console](#at-rest-encryption-enable-con)
+ [Enabling At-Rest Encryption Using the AWS CLI](#at-rest-encryption-enable-cli)

### Enabling At-Rest Encryption on an existing node-based Valkey or Redis OSS Cluster
<a name="at-reset-encryption-enable-existing-cluster"></a>

You can only enable at-rest encryption when you create a Valkey or Redis OSS replication group. If you have an existing replication group on which you want to enable at-rest encryption, do the following.

**To enable at-rest encryption on an existing replication group**

1. Create a manual backup of your existing replication group. For more information, see [Taking manual backups](backups-manual.md).

1. Create a new replication group by restoring from the backup. On the new replication group, enable at-rest encryption. For more information, see [Restoring from a backup into a new cache](backups-restoring.md).

1. Update the endpoints in your application to point to the new replication group.

1. Delete the old replication group. For more information, see [Deleting a cluster in ElastiCache](Clusters.Delete.md) or [Deleting a replication group](Replication.DeletingRepGroup.md).

### Enabling At-Rest Encryption Using the AWS Management Console
<a name="at-rest-encryption-enable-con"></a>

#### Enabling At-Rest Encryption on a Serverless Cache (Console)
<a name="at-rest-encryption-enable-con-serverless"></a>

All serverless caches have at-rest encryption enabled. By default, an AWS-owned KMS key is used to encrypt data. To choose your own AWS KMS key, make the following selections:
+ Expand the **Default settings** section.
+ Choose **Customize default settings** under **Default settings** section.
+ Choose **Customize your security settings** under **Security** section.
+ Choose **Customer managed CMK** under **Encryption key** setting.
+ Select a key under **AWS KMS key** setting.

#### Enabling At-Rest Encryption on a Node-Based Cluster (Console)
<a name="at-rest-encryption-enable-con-self-designed"></a>

When designing your own cache, 'Dev/Test' and 'Production' configurations with the 'Easy create' method have at-rest encryption enabled using the **Default** key. When choosing configuration yourself, make the following selections:
+ Choose version 3.2.6, 4.0.10 or later as your engine version.
+ Click the checkbox next to **Enable** for the **Encryption at rest** option.
+ Choose either a **Default key** or **Customer managed CMK**.

For the step-by-step procedure, see the following:
+ [Creating a Valkey (cluster mode disabled) cluster (Console)](SubnetGroups.designing-cluster-pre.valkey.md#Clusters.Create.CON.valkey-gs)
+ [Creating a Valkey or Redis OSS (cluster mode enabled) cluster (Console)](Clusters.Create.md#Clusters.Create.CON.RedisCluster)

### Enabling At-Rest Encryption Using the AWS CLI
<a name="at-rest-encryption-enable-cli"></a>

To enable at-rest encryption when creating a Valkey or Redis OSS cluster using the AWS CLI, use the *--at-rest-encryption-enabled* parameter when creating a replication group.

#### Enabling At-Rest Encryption on a Valkey or Redis OSS (Cluster Mode Disabled) Cluster (CLI)
<a name="at-rest-encryption-enable-cli-redis-classic-rg"></a>

The following operation creates the Valkey or Redis OSS (cluster mode disabled) replication group `my-classic-rg` with three nodes (*--num-cache-clusters*), a primary and two read replicas. At-rest encryption is enabled for this replication group (*--at-rest-encryption-enabled*).

The following parameters and their values are necessary to enable encryption on this replication group:

**Key Parameters**
+ **--engine**—Must be `valkey` or `redis`.
+ **--engine-version**—If the engine is Redis OSS, this must be 3.2.6, 4.0.10 or later.
+ **--at-rest-encryption-enabled**—Required to enable at-rest encryption.

**Example 1: Valkey or Redis OSS (Cluster Mode Disabled) Cluster with Replicas**  
For Linux, macOS, or Unix:  

```
aws elasticache create-replication-group \
    --replication-group-id my-classic-rg \
    --replication-group-description "3 node replication group" \
    --cache-node-type cache.m4.large \
    --engine redis \    
    --at-rest-encryption-enabled \  
    --num-cache-clusters 3
```
For Windows:  

```
aws elasticache create-replication-group ^
    --replication-group-id my-classic-rg ^
    --replication-group-description "3 node replication group" ^
    --cache-node-type cache.m4.large ^
    --engine redis ^    
    --at-rest-encryption-enabled ^  
    --num-cache-clusters 3 ^
```

For additional information, see the following:
+ [Creating a Valkey or Redis OSS (Cluster Mode Disabled) replication group from scratch (AWS CLI)](Replication.CreatingReplGroup.NoExistingCluster.Classic.md#Replication.CreatingReplGroup.NoExistingCluster.Classic.CLI)
+ [create-replication-group](https://docs.aws.amazon.com/cli/latest/reference/elasticache/create-replication-group.html)

 

#### Enabling At-Rest Encryption on a Cluster for Valkey or Redis OSS (Cluster Mode Enabled) (CLI)
<a name="at-rest-encryption-enable-cli-clustered-redis"></a>

The following operation creates the Valkey or Redis OSS (cluster mode enabled) replication group `my-clustered-rg` with three node groups or shards (*--num-node-groups*). Each has three nodes, a primary and two read replicas (*--replicas-per-node-group*). At-rest encryption is enabled for this replication group (*--at-rest-encryption-enabled*).

The following parameters and their values are necessary to enable encryption on this replication group:

**Key Parameters**
+ **--engine**—Must be `valkey` or `redis`.
+ **--engine-version**—If the engine is Redis OSS, this must be 4.0.10 or later.
+ **--at-rest-encryption-enabled**—Required to enable at-rest encryption.
+ **--cache-parameter-group**—Must be `default-redis4.0.cluster.on` or one derived from it to make this a cluster mode enabled replication group.

**Example 2: A Valkey or Redis OSS (Cluster Mode Enabled) Cluster**  
For Linux, macOS, or Unix:  

```
aws elasticache create-replication-group \
   --replication-group-id my-clustered-rg \
   --replication-group-description "redis clustered cluster" \
   --cache-node-type cache.m3.large \
   --num-node-groups 3 \
   --replicas-per-node-group 2 \
   --engine redis \
   --engine-version 6.2 \
   --at-rest-encryption-enabled \
   --cache-parameter-group default.redis6.x.cluster.on
```
For Windows:  

```
aws elasticache create-replication-group ^
   --replication-group-id my-clustered-rg ^
   --replication-group-description "redis clustered cluster" ^
   --cache-node-type cache.m3.large ^
   --num-node-groups 3 ^
   --replicas-per-node-group 2 ^
   --engine redis ^
   --engine-version 6.2 ^
   --at-rest-encryption-enabled ^
   --cache-parameter-group default.redis6.x.cluster.on
```

For additional information, see the following:
+ [Creating a Valkey or Redis OSS (Cluster Mode Enabled) replication group from scratch (AWS CLI)](Replication.CreatingReplGroup.NoExistingCluster.Cluster.md#Replication.CreatingReplGroup.NoExistingCluster.Cluster.CLI)
+ [create-replication-group](https://docs.aws.amazon.com/cli/latest/reference/elasticache/create-replication-group.html)

## See Also
<a name="at-rest-encryption-see-also"></a>
+ [Amazon VPCs and ElastiCache security](VPCs.md)
+ [Identity and Access Management for Amazon ElastiCache](IAM.md)

# Authentication and Authorization
<a name="auth-redis"></a>

AWS Identity and Access Management (IAM) is a web service that helps you securely control access to AWS resources. ElastiCache supports authenticating users using IAM and the Valkey and Redis OSS AUTH command, and authorizing user operations using Role-Based Access Control (RBAC).

**Topics**
+ [Role-Based Access Control (RBAC)](Clusters.RBAC.md)
+ [Authenticating with the Valkey and Redis OSS AUTH command](auth.md)
+ [Migrating from password-based authentication (AUTH) to IAM authentication](auth-to-iam-migration.md)
+ [Disabling access control on an ElastiCache Valkey or Redis OSS cache](in-transit-encryption-disable.md)

# Role-Based Access Control (RBAC)
<a name="Clusters.RBAC"></a>

With the Valkey and Redis OSS AUTH command as described in [Authenticating with the Valkey and Redis OSS AUTH command](auth.md) you can use Role-Based Access Control (RBAC). RBAC is also the only way to control access to serverless caches. This is available for Valkey 7.2 and onward, and Redis OSS 6.0 to 7.2. 

RBAC enables you to:
+ Control cache access through user groups. These user groups are designed as a way to organize access to caches.
+ With *authN*, have per user passwords as opposed to per cluster auth tokens.
+ With *authZ*, have fine-grained user permissions.
+ Base your cluster access on ACLs.

Unlike Valkey and Redis OSS AUTH, where all authenticated clients have full cache access if their token is authenticated, RBAC enables you to assign users to sets depending on the users' desired roles. These sets are designed as a way to organize access to caches.

With RBAC, you create users and assign them specific permissions by using an access string, as described following. You assign the users to sets aligned with a specific role (administrators, human resources) that are then deployed to one or more ElastiCache caches. By doing this, you can establish security boundaries between clients using the same Valkey or Redis OSS cache or caches, and prevent clients from accessing each other’s data. 

RBAC is designed to support the introduction of [ACL](https://valkey.io/topics/acl/) in Redis OSS 6. When you use RBAC with your ElastiCache Valkey or Redis OSS cache, there are some limitations: 
+ A user group configured for the "VALKEY" engine can only contain users who are using an authentication mechanism (either password or IAM). This means all users with the engine "VALKEY", and any other users with the engine "Redis" who have their setup configured to authenticate with password or IAM, can be in this user group.
+ When using RBAC with Valkey clusters, both user groups with engine "VALKEY" and with engine "REDIS" can be used.
+ When using RBAC with Redis OSS clusters, only user groups with the engine "REDIS" can be used.
+ You can't specify passwords in an access string. You set passwords with [CreateUser](https://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_CreateUser.html) or [ModifyUser](https://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_ModifyUser.html) calls.
+ For user rights, you enable or disable users with the `on` and `off` as a part of the access string. If neither is specified in the access string, the user is assigned `off` and doesn't have access rights to the cache.
+ You can't use forbidden and renamed commands as part of the access string. If you specify a forbidden or a renamed command, an exception will be thrown. If you want to use access control lists (ACLs) for a renamed command, specify the original name of the command, in other words the name of the command before it was renamed.
+ You can't use the `reset` command as a part of an access string. You specify passwords with API parameters, and ElastiCache for Valkey and Redis OSS manages passwords. Thus, you can't use `reset` because it would remove all passwords for a user.
+ Redis OSS 6 introduces the [ACL LIST](https://valkey.io/commands/acl-list) command. This command returns a list of users along with the ACL rules applied to each user. ElastiCache supports the `ACL LIST` command, but does not include support for password hashes as Redis OSS does. With ElastiCache, you can use the [DescribeUsers](https://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_DescribeUsers.html) operation to get similar information, including the rules contained within the access string. However, [DescribeUsers](https://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_DescribeUsers.html) doesn't retrieve a user password. 
+ Other read-only commands supported by ElastiCache for Valkey and Redis OSS include [ACL WHOAMI](https://valkey.io/commands/acl-whoami), [ACL USERS](https://valkey.io/commands/acl-users), and [ACL CAT](https://valkey.io/commands/acl-cat). ElastiCache for Valkey and Redis OSS doesn't support any other write-based ACL commands.
+ The following limits apply:    
<a name="quotas-table"></a>[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonElastiCache/latest/dg/Clusters.RBAC.html)

**RBAC with Valkey**

When using Role Based Access Control with Valkey, users and user groups are made with the "VALKEY" engine type. This is recommended, as by default Valkey with RBAC provides increased security compared to Redis OSS. Both provisioned and serverless Valkey clusters support VALKEY user and user group associations. 

Key features of Valkey Access Control include:
+ Valkey users are restricted to Valkey user group associations only.
+ Valkey user groups can contain Valkey users, and Redis OSS users who are either password protected or IAM auth enabled.
+ Valkey users must use either password protection or IAM authentication.
+ VALKEY user groups can only be associated to VALKEY clusters
+ There is no default user requirement. When the Valkey user group is attached to clusters, the default user requirement is automatically disabled. Customers will see that default user is turned off when using the ACL LIST command.

More information on using RBAC with ElastiCache for Valkey and Redis OSS follows.

**Topics**
+ [Specifying Permissions Using an Access String](#Access-string)
+ [Applying RBAC to a Cache for ElastiCache for Valkey or Redis OSS](#rbac-using)
+ [Migrating from AUTH to RBAC](#Migrate-From-RBAC-to-Auth)
+ [Migrating from RBAC to AUTH](#Migrate-From-RBAC-to-AUTH-1)
+ [Automatically rotating passwords for users](User-Secrets-Manager.md)
+ [Authenticating with IAM](auth-iam.md)

## Specifying Permissions Using an Access String
<a name="Access-string"></a>

To specify permissions to an ElastiCache Valkey or Redis OSS cache, you create an access string and assign it to a user through either the AWS CLI or AWS Management Console. 

Access strings are defined as a list of space-delimited rules which are applied on the user. They define which commands a user can execute and which keys a user can operate on. In order to execute a command, a user must have access to the command being executed and all keys being accessed by the command. Rules are applied from left to right cumulatively, and a simpler string may be used instead of the one provided if there are redundancies in the string provided.

For information about the syntax of the ACL rules, see [ACL](https://valkey.io/topics/acl/). 

In the following example, the access string represents an active user with access to all available keys and commands.

 `on ~* +@all`

The access string syntax is broken down as follows:
+ `on` – The user is an active user.
+ `~*` – Access is given to all available keys.
+ `+@all` – Access is given to all available commands.

The preceding settings are the least restrictive. You can modify these settings to make them more secure.

In the following example, the access string represents a user with access restricted to read access on keys that start with “app::” keyspace

`on ~app::* -@all +@read`

You can refine these permissions further by listing commands the user has access to:

`+command1` – The user's access to commands is limited to *`command1`*.

 `+@category` – The user's access is limited to a category of commands.

For information on assigning an access string to a user, see [Creating Users and User Groups with the Console and CLI](#Users-management).

If you are migrating an existing workload to ElastiCache, you can retrieve the access string by calling `ACL LIST`, excluding the user and any password hashes.

For Redis OSS version 6.2 and above the following access string syntax is also supported:
+ `&*` – Access is given to all available channels.

For Redis OSS version 7.0 and above the following access string syntax is also supported:
+ `|` – Can be used for blocking subcommands (e.g "-config\$1set").
+ `%R~<pattern>` – Add the specified read key pattern. This behaves similar to the regular key pattern but only grants permission to read from keys that match the given pattern. See [key permissions](https://valkey.io/topics/acl/) for more information.
+ `%W~<pattern>` – Add the specified write key pattern. This behaves similar to the regular key pattern but only grants permission to write to keys that match the given pattern. See [ACL key permissions](https://valkey.io/topics/acl/) for more information.
+ `%RW~<pattern>` – Alia for `~<pattern>`.
+ `(<rule list>)` – Create a new selector to match rules against. Selectors are evaluated after the user permissions, and are evaluated according to the order they are defined. If a command matches either the user permissions or any selector, it is allowed. See [ACL selectors](https://valkey.io/topics/acl/) more information.
+ `clearselectors` – Delete all of the selectors attached to the user.

## Applying RBAC to a Cache for ElastiCache for Valkey or Redis OSS
<a name="rbac-using"></a>

To use ElastiCache for Valkey or Redis OSS RBAC, you take the following steps: 

1. Create one or more users.

1. Create a user group and add users to the group.

1. Assign the user group to a cache that has in-transit encryption enabled.

These steps are described in detail as follows.

**Topics**
+ [Creating Users and User Groups with the Console and CLI](#Users-management)
+ [Managing User Groups with the Console and CLI](#User-Groups)
+ [Assigning User Groups to Serverless Caches](#Users-groups-to-serverless-caches)
+ [Assigning User Groups to Replication Groups](#Users-groups-to-RGs)

### Creating Users and User Groups with the Console and CLI
<a name="Users-management"></a>

The user information for RBAC users is a user ID, user name, and optionally a password and an access string. The access string provides the permission level on keys and commands. The user ID is unique to the user, and the user name is what is passed to the engine. 

Make sure that the user permissions you provide make sense with the intended purpose of the user group. For example, if you create a user group called `Administrators`, any user you add to that group should have its access string set to full access to keys and commands. For users in an `e-commerce` user group, you might set their access strings to read-only access.

ElastiCache automatically configures a default user with user ID and user name `"default"` and adds it to all user groups. You can't modify or delete this user. This user is intended for compatibility with the default behavior of previous Redis OSS versions and has an access string that permits it to call all commands and access all keys. 

To add proper access control to a cache, replace this default user with a new one that isn't enabled or uses a strong password. To change the default user, create a new user with the user name set to `default`. You can then swap it with the original default user.

The following procedures shows how to swap the original `default` user with another `default` user that has a modified access string.

**To modify the default user on the console**

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. Choose **User group management** from the navigation pane.

1. For **User group ID**, choose the ID that you want to modify. Make sure that you choose the link and not the check box.

1. Choose **Modify**.

1. In the **Modify** window, choose **Manage**. For "select the user that you want", select the user with the **User name** as default.

1. Choose **Choose**.

1. Choose **Modify**. When you do this, any existing connections to a cache that the original default user has are terminated.

**To modify the default user with the AWS CLI**

1. Create a new user with the user name `default` by using the following commands.

   For Linux, macOS, or Unix:

   ```
   aws elasticache create-user \
    --user-id "new-default-user" \
    --user-name "default" \
    --engine "VALKEY" \
    --passwords "a-str0ng-pa))word" \
    --access-string "off +get ~keys*"
   ```

   For Windows:

   ```
   aws elasticache create-user ^
    --user-id "new-default-user" ^
    --user-name "default" ^
    --engine "VALKEY" ^
    --passwords "a-str0ng-pa))word" ^
    --access-string "off +get ~keys*"
   ```

1. Create a user group and add the user that you created previously.

   For Linux, macOS, or Unix:

   ```
   aws elasticache create-user-group \
     --user-group-id "new-group-2" \
     --engine "VALKEY" \
     --user-ids "new-default-user"
   ```

   For Windows:

   ```
   aws elasticache create-user-group ^
     --user-group-id "new-group-2" ^
     --engine "VALKEY" ^
     --user-ids "new-default-user"
   ```

When creating a user, you can set up to two passwords. When you modify a password, any existing connections to caches are maintained.

In particular, be aware of these user password constraints when using RBAC for ElastiCache for Valkey and Redis OSS:
+ Passwords must be 16–128 printable characters.
+ The following nonalphanumeric characters are not allowed: `,` `""` `/` `@`. 

#### Managing Users with the Console and CLI
<a name="Users-console"></a>

Use the following procedure to manage users on the console.

**To manage users on the console**

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. On the Amazon ElastiCache dashboard, choose **User management**. The following options are available:
   + **Create user** – When creating a user, you enter a user ID, user name, authentication mode, and access string. The access string sets the permission level for what keys and commands the user is allowed. 

     When creating a user, you can set up to two passwords. When you modify a password, any existing connections to caches are maintained.
   + **Modify user** – Enables you to update a user's authentication settings or change its access string.
   + **Delete user** – The account will be removed from any User Groups to which it belongs.

Use the following procedures to manage users with the AWS CLI.

**To modify a user by using the CLI**
+  Use the `modify-user` command to update a user's password or passwords or change a user's access permissions. 

  When a user is modified, the user groups associated with the user are updated, along with any caches associated with the user group. All existing connections are maintained. The following are examples.

  For Linux, macOS, or Unix:

  ```
  aws elasticache modify-user \
    --user-id user-id-1 \
    --access-string "~objects:* ~items:* ~public:*" \
    --authentication-mode Type=iam
  ```

  For Windows:

  ```
  aws elasticache modify-user ^
    --user-id user-id-1 ^
    --access-string "~objects:* ~items:* ~public:*" ^
    --authentication-mode Type=iam
  ```

**Note**  
We don't recommend using the `nopass` option. If you do, we recommend setting the user's permissions to read-only with access to a limited set of keys.

**To delete a user by using the CLI**
+ Use the `delete-user` command to delete a user. The account is deleted and removed from any user groups to which it belongs. The following is an example.

  For Linux, macOS, or Unix:

  ```
  aws elasticache delete-user \
    --user-id user-id-2
  ```

  For Windows:

  ```
  aws elasticache delete-user ^
    --user-id user-id-2
  ```

To see a list of users, call the [describe-users](https://docs.aws.amazon.com/cli/latest/reference/elasticache/describe-users.html) operation. 

```
aws elasticache describe-users
```

### Managing User Groups with the Console and CLI
<a name="User-Groups"></a>

You can create user groups to organize and control access of users to one or more caches, as shown following.

Use the following procedure to manage user groups using the console.

**To manage user groups using the console**

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. On the Amazon ElastiCache dashboard, choose **User group management**. 

   The following operations are available to create new user groups:
   + **Create** – When you create a user group, you add users and then assign the user groups to caches. For example, you can create an `Admin` user group for users who have administrative roles on a cache.
**Important**  
If you are not using a Valkey or Redis OSS user group then you must include a default user when creating a user group.
   + **Add Users** – Add users to the user group.
   + **Remove Users** – Remove users from the user group. When users are removed from a user group, any existing connections they have to a cache are terminated.
   + **Delete** – Use this to delete a user group. Note that the user group itself, not the users belonging to the group, will be deleted.

   For existing user groups, you can do the following:
   + **Add Users** – Add existing users to the user group.
   + **Delete Users** – Removes existing users from the user group.
**Note**  
Users are removed from the user group, but not deleted from the system.

Use the following procedures to manage user groups using the CLI.

**To create a new user group and add a user by using the CLI**
+ Use the `create-user-group` command as shown following.

  For Linux, macOS, or Unix:

  ```
  aws elasticache create-user-group \
    --user-group-id "new-group-1" \
    --engine "VALKEY" \
    --user-ids user-id-1, user-id-2
  ```

  For Windows:

  ```
  aws elasticache create-user-group ^
    --user-group-id "new-group-1" ^
    --engine "VALKEY" ^
    --user-ids user-id-1, user-id-2
  ```

**To modify a user group by adding new users or removing current members by using the CLI**
+ Use the `modify-user-group` command as shown following.

  For Linux, macOS, or Unix:

  ```
  aws elasticache modify-user-group --user-group-id new-group-1 \
  --user-ids-to-add user-id-3 \
  --user-ids-to-remove user-id-2
  ```

  For Windows:

  ```
  aws elasticache modify-user-group --user-group-id new-group-1 ^
  --user-ids-to-add user-id-3 ^
  --user-ids-to-removere user-id-2
  ```

**Note**  
Any open connections belonging to a user removed from a user group are ended by this command.

**To delete a user group by using the CLI**
+ Use the `delete-user-group` command as shown following. The user group itself, not the users belonging to the group, is deleted.

  For Linux, macOS, or Unix:

  ```
  aws elasticache delete-user-group /
     --user-group-id
  ```

  For Windows:

  ```
  aws elasticache delete-user-group ^
     --user-group-id
  ```

To see a list of user groups, you can call the [describe-user-groups](https://docs.aws.amazon.com/cli/latest/reference/elasticache/describe-user-groups.html) operation.

```
aws elasticache describe-user-groups \
  --user-group-id test-group
```

### Assigning User Groups to Serverless Caches
<a name="Users-groups-to-serverless-caches"></a>

After you have created a user group and added users, the final step in implementing RBAC is assigning the user group to a serverless cache.

#### Assigning User Groups to Serverless Caches Using the Console
<a name="Users-groups-to-SCs-CON"></a>

To add a user group to a serverless cache using the AWS Management Console, do the following:
+ For cluster mode disabled, see [Creating a Valkey (cluster mode disabled) cluster (Console)](SubnetGroups.designing-cluster-pre.valkey.md#Clusters.Create.CON.valkey-gs)
+ For cluster mode enabled, see [Creating a Valkey or Redis OSS (cluster mode enabled) cluster (Console)](Clusters.Create.md#Clusters.Create.CON.RedisCluster)

#### Assigning User Groups to Serverless Caches Using the AWS CLI
<a name="Users-groups-to-SCs-CLI"></a>

 The following AWS CLI operation creates a serverless cache using the **user-group-id** parameter with the value `my-user-group-id`. Replace the subnet group `sng-test` with a subnet group that exists.

**Key Parameters**
+ **--engine** – Must be `VALKEY` or `REDIS`.
+ **--user-group-id** – This value provides the ID of the user group, comprised of users with specified access permissions for the cache.

For Linux, macOS, or Unix:

```
aws elasticache create-serverless-cache \
    --serverless-cache-name "new-serverless-cache" \
    --description "new-serverless-cache" \
    --engine "VALKEY" \
    --user-group-id "new-group-1"
```

For Windows:

```
aws elasticache create-serverless-cache ^
    --serverless-cache-name "new-serverless-cache" ^
    --description "new-serverless-cache" ^
    --engine "VALKEY" ^
    --user-group-id "new-group-1"
```

The following AWS CLI operation modifies a serverless cache with the **user-group-id** parameter with the value `my-user-group-id`. 

For Linux, macOS, or Unix:

```
aws elasticache modify-serverless-cache \
    --serverless-cache-name serverless-cache-1 \
    --user-group-id "new-group-2"
```

For Windows:

```
aws elasticache modify-serverless-cache ^
    --serverless-cache-name serverless-cache-1 ^
    --user-group-id "new-group-2"
```

Note that any modifications made to a cache are updated asynchronously. You can monitor this progress by viewing the events. For more information, see [Viewing ElastiCache events](ECEvents.Viewing.md).

### Assigning User Groups to Replication Groups
<a name="Users-groups-to-RGs"></a>

After you have created a user group and added users, the final step in implementing RBAC is assigning the user group to a replication group.

#### Assigning User Groups to Replication Groups Using the Console
<a name="Users-groups-to-RGs-CON"></a>

To add a user group to a replication using the AWS Management Console, do the following:
+ For cluster mode disabled, see [Creating a Valkey (cluster mode disabled) cluster (Console)](SubnetGroups.designing-cluster-pre.valkey.md#Clusters.Create.CON.valkey-gs)
+ For cluster mode enabled, see [Creating a Valkey or Redis OSS (cluster mode enabled) cluster (Console)](Clusters.Create.md#Clusters.Create.CON.RedisCluster)

#### Assigning User Groups to Replication Groups Using the AWS CLI
<a name="Users-groups-to-RGs-CLI"></a>

 The following AWS CLI operation creates a replication group with encryption in transit (TLS) enabled and the **user-group-ids** parameter with the value `my-user-group-id`. Replace the subnet group `sng-test` with a subnet group that exists.

**Key Parameters**
+ **--engine** – Must be `valkey` or `redis`.
+ **--engine-version** – Must be 6.0 or later.
+ **--transit-encryption-enabled** – Required for authentication and for associating a user group.
+ **--user-group-ids** – This value provides the ID of the user group, comprised of users with specified access permissions for the cache.
+ **--cache-subnet-group** – Required for associating a user group.

For Linux, macOS, or Unix:

```
aws elasticache create-replication-group \
    --replication-group-id "new-replication-group" \
    --replication-group-description "new-replication-group" \
    --engine "VALKEY" \
    --cache-node-type cache.m5.large \
    --transit-encryption-enabled \
    --user-group-ids "new-group-1" \
    --cache-subnet-group "cache-subnet-group"
```

For Windows:

```
aws elasticache create-replication-group ^
    --replication-group-id "new-replication-group" ^
    --replication-group-description "new-replication-group" ^
    --engine "VALKEY" ^
    --cache-node-type cache.m5.large ^
    --transit-encryption-enabled ^
    --user-group-ids "new-group-1" ^
    --cache-subnet-group "cache-subnet-group"
```

The following AWS CLI operation modifies a replication group with encryption in transit (TLS) enabled and the **user-group-ids** parameter with the value `my-user-group-id`. 

For Linux, macOS, or Unix:

```
aws elasticache modify-replication-group \
    --replication-group-id replication-group-1 \
    --user-group-ids-to-remove "new-group-1" \
    --user-group-ids-to-add "new-group-2"
```

For Windows:

```
aws elasticache modify-replication-group ^
    --replication-group-id replication-group-1 ^
    --user-group-ids-to-remove "new-group-1" ^
    --user-group-ids-to-add "new-group-2"
```

Note the `PendingChanges` in the response. Any modifications made to a cache are updated asynchronously. You can monitor this progress by viewing the events. For more information, see [Viewing ElastiCache events](ECEvents.Viewing.md).

## Migrating from AUTH to RBAC
<a name="Migrate-From-RBAC-to-Auth"></a>

If you are using AUTH as described in [Authenticating with the Valkey and Redis OSS AUTH command](auth.md) and want to migrate to using RBAC, use the following procedures.

Use the following procedure to migrate from AUTH to RBAC using the console.

**To migrate from Valkey or Redis OSS AUTH to RBAC using the console**

1. Sign in to the AWS Management Console and open the ElastiCache console at [ https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. From the list in the upper-right corner, choose the AWS Region where the cache that you want to modify is located.

1. In the navigation pane, choose the engine that runs on the cache that you want to modify.

   A list of the chosen engine's caches appears.

1. In the list of caches, for the cache that you want to modify, choose its name. 

1. For **Actions**, choose **Modify**. 

   The **Modify** window appears.

1. For **Access control**, choose **User group access control list**.

1.  For **User group access control list**, choose a user group. 

1. Choose **Preview changes** and then on the next screen, **Modify**.

Use the following procedure to migrate from Valkey or Redis OSS AUTH to RBAC using the CLI.

**To migrate from AUTH to RBAC using the CLI**
+  Use the `modify-replication-group` command as shown following. 

  For Linux, macOS, or Unix:

  ```
  aws elasticache modify-replication-group --replication-group-id test \
      --auth-token-update-strategy DELETE \
      --user-group-ids-to-add user-group-1
  ```

  For Windows:

  ```
  aws elasticache modify-replication-group --replication-group-id test ^
      --auth-token-update-strategy DELETE ^
      --user-group-ids-to-add user-group-1
  ```

## Migrating from RBAC to AUTH
<a name="Migrate-From-RBAC-to-AUTH-1"></a>

If you are using RBAC and want to migrate to Redis OSS AUTH, see [Migrating from RBAC to AUTH](auth.md#Migrate-From-RBAC-to-AUTH).

**Note**  
If you need to disable access control on an ElastiCache cache, you'll need to do it through the AWS CLI. For more information, see [Disabling access control on an ElastiCache Valkey or Redis OSS cache](in-transit-encryption-disable.md). 

# Automatically rotating passwords for users
<a name="User-Secrets-Manager"></a>

With AWS Secrets Manager, you can replace hardcoded credentials in your code (including passwords) with an API call to Secrets Manager to retrieve the secret programmatically. This helps ensure that the secret can't be compromised by someone examining your code, because the secret simply isn't there. Also, you can configure Secrets Manager to automatically rotate the secret for you according to a schedule that you specify. This enables you to replace long-term secrets with short-term ones, which helps to significantly reduce the risk of compromise.

Using Secrets Manager, you can automatically rotate your ElastiCache for Redis OSS passwords (that is, secrets) using an AWS Lambda function that Secrets Manager provides.

For more information about AWS Secrets Manager, see [What is AWS Secrets Manager?](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html)

## How ElastiCache uses secrets
<a name="how-elasticache-uses-secrets"></a>

Valkey 7.2 and above have an equivalent feature set as Redis OSS 7.0. In Redis OSS 6, ElastiCache introduced [Role-Based Access Control (RBAC)](Clusters.RBAC.md) to secure the Valkey or Redis OSS cluster. This feature allows certain connections to be limited in terms of the commands that can be executed and the keys that can be accessed. With RBAC, while the customer creates a user with passwords, the password values need to be manually entered in plaintext and is visible to the operator. 

With Secrets Manager, applications fetch the password from Secrets Manager rather than entering them manually and storing them in the application's configuration. For information on how to do this, see [How ElastiCache users are associated with the secret](#How-User-Secrets-Manager-Associate).

There is a cost incurred for using secrets. For pricing information, see [AWS Secrets Manager Pricing](https://aws.amazon.com/secrets-manager/pricing/).

## How ElastiCache users are associated with the secret
<a name="How-User-Secrets-Manager-Associate"></a>

Secrets Manager will keep a reference for the associated user in the secret’s `SecretString` field. There will be no reference to the secret from ElastiCache side.

```
{
    "password": "strongpassword",
    "username": "user1",
    "user_arn": "arn:aws:elasticache:us-east-1:xxxxxxxxxx918:user:user1" //this is the bond between the secret and the user
}
```

## Lambda rotation function
<a name="lambda-rotation-function"></a>

To enable Secrets Manager automatic password rotation, you will create a Lambda function that will interact with the [modify-user](https://docs.aws.amazon.com/cli/latest/reference/elasticache/modify-user.html) API to update the user’s passwords. 

For information on how this works, see [How rotation works](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html#rotate-secrets_how).

**Note**  
For some AWS services, to avoid the confused deputy scenario, AWS recommends that you use both the `aws:SourceArn` and `aws:SourceAccount` global condition keys. However, if you include the `aws:SourceArn` condition in your rotation function policy, the rotation function can only be used to rotate the secret specified by that ARN. We recommend that you include only the context key `aws:SourceAccount` so that you can use the rotation function for multiple secrets.

For any issues you may encounter, see [Troubleshoot AWS Secrets Manager rotation](https://docs.aws.amazon.com/secretsmanager/latest/userguide/troubleshoot_rotation.html).

## How to create an ElastiCache user and associate it with Secrets Manager
<a name="User-Secrets-Manager-Associate"></a>

The following steps illustrate how to create a user and associate it with Secrets Manager:

1. **Create an inactive user**

   For Linux, macOS, or Unix:

   ```
   aws elasticache create-user \
    --user-id user1 \
    --user-name user1 \
    --engine "REDIS" \
    --no-password \ // no authentication is required
    --access-string "*off* +get ~keys*" // this disables the user
   ```

   For Windows:

   ```
   aws elasticache create-user ^
    --user-id user1 ^
    --user-name user1 ^
    --engine "REDIS" ^
    --no-password ^ // no authentication is required
    --access-string "*off* +get ~keys*" // this disables the user
   ```

   You will see a response similar to the following:

   ```
   {
       "UserId": "user1",
       "UserName": "user1",
       "Status": "active",
       "Engine": "redis",
       "AccessString": "off ~keys* -@all +get",
       "UserGroupIds": [],
       "Authentication": {
           "Type": "no_password"
       },
       "ARN": "arn:aws:elasticache:us-east-1:xxxxxxxxxx918:user:user1"
   }
   ```

1. **Create a Secret**

   For Linux, macOS, or Unix:

   ```
   aws secretsmanager create-secret \
   --name production/ec/user1 \
   --secret-string \
   '{
      "user_arn": "arn:aws:elasticache:us-east-1:123456xxxx:user:user1", 
       "username":"user1"
    }'
   ```

   For Windows:

   ```
   aws secretsmanager create-secret ^
   --name production/ec/user1 ^
   --secret-string ^
   '{
      "user_arn": "arn:aws:elasticache:us-east-1:123456xxxx:user:user1", 
       "username":"user1"
    }'
   ```

   You will see a response similar to the following:

   ```
   {
    "ARN": "arn:aws:secretsmanager:us-east-1:123456xxxx:secret:production/ec/user1-eaFois",
    "Name": "production/ec/user1",
    "VersionId": "aae5b963-1e6b-4250-91c6-ebd6c47d0d95"
   }
   ```

1. **Configure a Lambda function to rotate your password **

   1. Sign in to the AWS Management Console and open the Lambda console at [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/elasticache/)

   1. Choose **Functions** on the navigation pane and then choose the function you created. Choose the function name, not the checkbox to its left.

   1. Choose the **Configuration** tab.

   1. In **General configuration**, choose **Edit** and then set **Timeout** to at least 12 minutes.

   1. Choose **Save**.

   1. Choose **Environment variables** and then set the following:

      1. SECRETS\$1MANAGER\$1ENDPOINT – https://secretsmanager.**REGION**.amazonaws.com

      1. SECRET\$1ARN – The Amazon Resource Name (ARN) of the secret you created in Step 2.

      1. USER\$1NAME – Username of the ElastiCache user,

      1. Choose **Save**.

   1. Choose **Permissions**

   1. Under **Execution role**, choose the name of the Lambda function role to view on the IAM console.

   1. The Lambda function will need the following permission to modify the users and set the password: 

      ElastiCache

------
#### [ JSON ]

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "elasticache:DescribeUsers",
                      "elasticache:ModifyUser"
                  ],
                  "Resource": "arn:aws:elasticache:us-east-1:123456789012:user:user1"
              }
          ]
      }
      ```

------

      Secrets Manager

------
#### [ JSON ]

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "secretsmanager:GetSecretValue",
                      "secretsmanager:DescribeSecret",
                      "secretsmanager:PutSecretValue",
                      "secretsmanager:UpdateSecretVersionStage"
                  ],
                  "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:XXXX"
              },
              {
                  "Effect": "Allow",
                  "Action": "secretsmanager:GetRandomPassword",
                  "Resource": "*"
              }
          ]
      }
      ```

------

1. Set up Secrets Manager secret rotation

   1. **Using the AWS Management Console, see [Set up automatic rotation for AWS Secrets Manager secrets using the console](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_turn-on-for-other.html)**

      For more information on setting up a rotation schedule, see [Schedule expressions in Secrets Manager rotation](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_schedule.html).

   1. **Using the AWS CLI, see [ Set up automatic rotation for AWS Secrets Manager using the AWS Command Line Interface](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets-cli.html)**

# Authenticating with IAM
<a name="auth-iam"></a>

**Topics**
+ [Overview](#auth-iam-overview)
+ [Limitations](#auth-iam-limits)
+ [Setup](#auth-iam-setup)
+ [Connecting](#auth-iam-Connecting)

## Overview
<a name="auth-iam-overview"></a>

With IAM Authentication you can authenticate a connection to ElastiCache for Valkey or Redis OSS using AWS IAM identities, when your cache is configured to use Valkey or Redis OSS version 7 or above. This allows you to strengthen your security model and simplify many administrative security tasks. You can also use IAM Authentication to configure fine-grained access control for each individual ElastiCache cache and ElastiCache user, following least-privilege permissions principles. IAM Authentication for ElastiCache works by providing a short-lived IAM authentication token instead of a long-lived ElastiCache user password in the Valkey or Redis OSS `AUTH` or `HELLO` command. For more information about the IAM authentication token, refer to the [Signature Version 4 signing process](https://docs.aws.amazon.com//general/latest/gr/signature-version-4.html) in the the AWS General Reference Guide and the code example below. 

You can use IAM identities and their associated policies to further restrict Valkey or Redis OSS access. You can also grant access to users from their federated Identity providers directly to Valkey or Redis OSS caches.

To use AWS IAM with ElastiCache, you first need to create an ElastiCache user with authentication mode set to IAM. Then you can create or reuse an IAM identity. The IAM identity needs an associated policy to grant the `elasticache:Connect` action to the ElastiCache cache and ElastiCache user. Once configured, you can create an IAM authentication token using the AWS credentials of the IAM user or role. Finally you need to provide the short-lived IAM authentication token as a password in your Valkey or Redis OSS Client when connecting to your cache. A Valkey or Redis OSS client with support for credentials provider can auto-generate the temporary credentials automatically for each new connection. ElastiCache will perform IAM authentication for connection requests of IAM-enabled ElastiCache users and will validate the connection requests with IAM. 

## Limitations
<a name="auth-iam-limits"></a>

When using IAM authentication, the following limitations apply:
+ IAM authentication is available when using ElastiCache for Valkey 7.2 and above or Redis OSS version 7.0 and above.
+ For IAM-enabled ElastiCache users the username and user id properties must be identical.
+ The IAM authentication token is valid for 15 minutes. For long-lived connections, we recommend using a Valkey or Redis OSS client that supports a credentials provider interface.
+ An IAM authenticated connection to ElastiCache for Valkey or Redis OSS will automatically be disconnected after 12 hours. The connection can be prolonged for 12 hours by sending an `AUTH` or `HELLO` command with a new IAM authentication token.
+ IAM authentication is not supported inside `MULTI`/`EXEC` blocks.
+ Currently, IAM authentication supports the following global condition context keys:
  + When using IAM authentication with serverless caches, `aws:VpcSourceIp`, `aws:SourceVpc`, `aws:SourceVpce`, `aws:CurrentTime`, `aws:EpochTime`, and `aws:ResourceTag/%s` (from associated serverless caches and users) are supported.
  + When using IAM authentication with replication groups, `aws:SourceIp` and `aws:ResourceTag/%s` (from associated replication groups and users) are supported.

  For more information about global condition context keys, see [AWS global condition context keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html) in the IAM User Guide.

**Note**  
Cache names are converted to lowercase at cache creation time. Ensure authenticating code supplies the cache name in lowercase to avoid authentication errors.

## Setup
<a name="auth-iam-setup"></a>

To setup IAM authentication:

1. Create a cache

   ```
   aws elasticache create-serverless-cache \
     --serverless-cache-name cache-01  \
     --description "ElastiCache IAM auth application" \
     --engine redis
   ```

1. Create an IAM trust policy document, as shown below, for your role that allows your account to assume the new role. Save the policy to a file named *trust-policy.json*.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": {
           "Effect": "Allow",
           "Principal": { "AWS": "arn:aws:iam::123456789012:root" },
           "Action": "sts:AssumeRole"
       }
   }
   ```

------

1. Create an IAM policy document, as shown below. Save the policy to a file named *policy.json*.

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect" : "Allow",
         "Action" : [
           "elasticache:Connect"
         ],
         "Resource" : [
           "arn:aws:elasticache:us-east-1:123456789012:serverlesscache:cache-01",
           "arn:aws:elasticache:us-east-1:123456789012:user:iam-user-01"
         ]
       }
     ]
   }
   ```

------

1. Create an IAM role.

   ```
   aws iam create-role \
   --role-name "elasticache-iam-auth-app" \
   --assume-role-policy-document file://trust-policy.json
   ```

1. Create the IAM policy.

   ```
   aws iam create-policy \
     --policy-name "elasticache-allow-all" \
     --policy-document file://policy.json
   ```

1. Attach the IAM policy to the role.

   ```
   aws iam attach-role-policy \
    --role-name "elasticache-iam-auth-app" \
    --policy-arn "arn:aws:iam::123456789012:policy/elasticache-allow-all"
   ```

1. Create a new IAM-enabled user.

   ```
   aws elasticache create-user \
     --user-name iam-user-01 \
     --user-id iam-user-01 \
     --authentication-mode Type=iam \
     --engine redis \
     --access-string "on ~* +@all"
   ```

1. Create a user group and attach the user.

   ```
   aws elasticache create-user-group \
     --user-group-id iam-user-group-01 \
     --engine redis \
     --user-ids default iam-user-01
   
   aws elasticache modify-serverless-cache \
     --serverless-cache-name cache-01  \
     --user-group-id iam-user-group-01
   ```

## Connecting
<a name="auth-iam-Connecting"></a>

**Connect with token as password**

You first need to generate the short-lived IAM authentication token using an [AWS SigV4 pre-signed request](https://docs.aws.amazon.com//general/latest/gr/sigv4-signed-request-examples.html). After that you provide the IAM authentication token as a password when connecting to a Valkey or Redis OSS cache, as shown in the example below. 

```
String userId = "insert user id";
String cacheName = "insert cache name";
boolean isServerless = true;
String region = "insert region";

// Create a default AWS Credentials provider.
// This will look for AWS credentials defined in environment variables or system properties.
AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain();

// Create an IAM authentication token request and signed it using the AWS credentials.
// The pre-signed request URL is used as an IAM authentication token for ElastiCache with Redis OSS.
IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userId, cacheName, region, isServerless);
String iamAuthToken = iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials());

// Construct Redis OSS URL with IAM Auth credentials provider
RedisURI redisURI = RedisURI.builder()
    .withHost(host)
    .withPort(port)
    .withSsl(ssl)
    .withAuthentication(userId, iamAuthToken)
    .build();

// Create a new Lettuce Redis OSS client
RedisClient client = RedisClient.create(redisURI);
client.connect();
```

Below is the definition for `IAMAuthTokenRequest`.

```
public class IAMAuthTokenRequest {
    private static final HttpMethodName REQUEST_METHOD = HttpMethodName.GET;
    private static final String REQUEST_PROTOCOL = "http://";
    private static final String PARAM_ACTION = "Action";
    private static final String PARAM_USER = "User";
    private static final String PARAM_RESOURCE_TYPE = "ResourceType";
    private static final String RESOURCE_TYPE_SERVERLESS_CACHE = "ServerlessCache";
    private static final String ACTION_NAME = "connect";
    private static final String SERVICE_NAME = "elasticache";
    private static final long TOKEN_EXPIRY_SECONDS = 900;

    private final String userId;
    private final String cacheName;
    private final String region;
    private final boolean isServerless;

    public IAMAuthTokenRequest(String userId, String cacheName, String region, boolean isServerless) {
        this.userId = userId;
        this.cacheName = cacheName;
        this.region = region;
        this.isServerless = isServerless;
    }

    public String toSignedRequestUri(AWSCredentials credentials) throws URISyntaxException {
        Request<Void> request = getSignableRequest();
        sign(request, credentials);
        return new URIBuilder(request.getEndpoint())
            .addParameters(toNamedValuePair(request.getParameters()))
            .build()
            .toString()
            .replace(REQUEST_PROTOCOL, "");
    }

    private <T> Request<T> getSignableRequest() {
        Request<T> request  = new DefaultRequest<>(SERVICE_NAME);
        request.setHttpMethod(REQUEST_METHOD);
        request.setEndpoint(getRequestUri());
        request.addParameters(PARAM_ACTION, Collections.singletonList(ACTION_NAME));
        request.addParameters(PARAM_USER, Collections.singletonList(userId));
        if (isServerless) {
            request.addParameters(PARAM_RESOURCE_TYPE, Collections.singletonList(RESOURCE_TYPE_SERVERLESS_CACHE));
        }
        return request;
    }

    private URI getRequestUri() {
        return URI.create(String.format("%s%s/", REQUEST_PROTOCOL, cacheName));
    }

    private <T> void sign(SignableRequest<T> request, AWSCredentials credentials) {
        AWS4Signer signer = new AWS4Signer();
        signer.setRegionName(region);
        signer.setServiceName(SERVICE_NAME);

        DateTime dateTime = DateTime.now();
        dateTime = dateTime.plus(Duration.standardSeconds(TOKEN_EXPIRY_SECONDS));

        signer.presignRequest(request, credentials, dateTime.toDate());
    }

    private static List<NameValuePair> toNamedValuePair(Map<String, List<String>> in) {
        return in.entrySet().stream()
            .map(e -> new BasicNameValuePair(e.getKey(), e.getValue().get(0)))
            .collect(Collectors.toList());
    }
}
```

**Connect with credentials provider**

The code below shows how to authenticate with ElastiCache using the IAM authentication credentials provider.

```
String userId = "insert user id";
String cacheName = "insert cache name";
boolean isServerless = true;
String region = "insert region";

// Create a default AWS Credentials provider.
// This will look for AWS credentials defined in environment variables or system properties.
AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain();

// Create an IAM authentication token request. Once this request is signed it can be used as an
// IAM authentication token for ElastiCache with Redis OSS.
IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userId, cacheName, region, isServerless);

// Create a Redis OSS credentials provider using IAM credentials.
RedisCredentialsProvider redisCredentialsProvider = new RedisIAMAuthCredentialsProvider(
    userId, iamAuthTokenRequest, awsCredentialsProvider);
    
// Construct Redis OSS URL with IAM Auth credentials provider
RedisURI redisURI = RedisURI.builder()
    .withHost(host)
    .withPort(port)
    .withSsl(ssl)
    .withAuthentication(redisCredentialsProvider)
    .build();

// Create a new Lettuce Redis OSS client
RedisClient client = RedisClient.create(redisURI);
client.connect();
```

Below is an example of a Lettuce Redis OSS client that wraps the IAMAuthTokenRequest in a credentials provider to auto-generate temporary credentials when needed.

```
public class RedisIAMAuthCredentialsProvider implements RedisCredentialsProvider {
    private static final long TOKEN_EXPIRY_SECONDS = 900;

    private final AWSCredentialsProvider awsCredentialsProvider;
    private final String userId;
    private final IAMAuthTokenRequest iamAuthTokenRequest;
    private final Supplier<String> iamAuthTokenSupplier;

    public RedisIAMAuthCredentialsProvider(String userId,
        IAMAuthTokenRequest iamAuthTokenRequest,
        AWSCredentialsProvider awsCredentialsProvider) {
        this.userName = userName;
        this.awsCredentialsProvider = awsCredentialsProvider;
        this.iamAuthTokenRequest = iamAuthTokenRequest;      
        this.iamAuthTokenSupplier = Suppliers.memoizeWithExpiration(this::getIamAuthToken, TOKEN_EXPIRY_SECONDS, TimeUnit.SECONDS);
    }

    @Override
    public Mono<RedisCredentials> resolveCredentials() {
        return Mono.just(RedisCredentials.just(userId, iamAuthTokenSupplier.get()));
    }

    private String getIamAuthToken() {
        return iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials());
    }
}
```

# Authenticating with the Valkey and Redis OSS AUTH command
<a name="auth"></a>

**Note**  
The **AUTH** has been superseded by [Role-Based Access Control (RBAC)](Clusters.RBAC.md). All serverless caches must use RBAC for authentication.

Valkey and Redis OSS authentication tokens or passwords enable Valkey and Redis OSS to require a password before allowing clients to run commands, thereby improving data security. The **AUTH** is available for node-based clusters only.

**Topics**
+ [Overview of AUTH in ElastiCache for Valkey and Redis OSS](#auth-overview)
+ [Applying authentication to an ElastiCache for Valkey and Redis OSS cluster](#auth-using)
+ [Modifying the AUTH token on an existing cluster](#auth-modifyng-token)
+ [Migrating from RBAC to AUTH](#Migrate-From-RBAC-to-AUTH)

## Overview of AUTH in ElastiCache for Valkey and Redis OSS
<a name="auth-overview"></a>

When you use the **AUTH** with your ElastiCache for Valkey and Redis OSS cluster, there are some refinements. 

In particular, be aware of these AUTH token or password constraints when using AUTH:
+ Tokens, or passwords, must be 16–128 printable characters.
+ Nonalphanumeric characters are restricted to (\$1, &, \$1, \$1, ^, <, >, -). 
+ AUTH can only be enabled for encryption in-transit enabled Valkey or Redis OSS clusters.

To set up a strong token, we recommend that you follow a strict password policy, such as requiring the following:
+ Tokens or passwords must include at least three of the following character types:
  + Uppercase characters
  + Lowercase characters
  + Digits 
  + Nonalphanumeric characters (`!`, `&`, `#`, `$`, `^`, `<`, `>`, `-`)
+ Tokens or passwords must not contain a dictionary word or a slightly modified dictionary word.
+ Tokens or passwords must not be the same as or similar to a recently used token.

## Applying authentication to an ElastiCache for Valkey and Redis OSS cluster
<a name="auth-using"></a>

You can require that users enter a token (password) on a token-protected Valkey or Redis OSS server. To do this, include the parameter `--auth-token` (API: `AuthToken`) with the correct token when you create your replication group or cluster. Also include it in all subsequent commands to the replication group or cluster.

The following AWS CLI operation creates a replication group with encryption in transit (TLS) enabled and the **AUTH** token `This-is-a-sample-token`. Replace the subnet group `sng-test` with a subnet group that exists.

**Key parameters**
+ **--engine** – Must be `valkey` or `redis`.
+ **--engine-version** – If engine is Redis OSS, must be 3.2.6, 4.0.10, or later.
+ **--transit-encryption-enabled** – Required for authentication and HIPAA eligibility.
+ **--auth-token** – Required for HIPAA eligibility. This value must be the correct token for this token-protected Valkey or Redis OSS server.
+ **--cache-subnet-group** – Required for HIPAA eligibility.

For Linux, macOS, or Unix:

```
aws elasticache create-replication-group \
    --replication-group-id authtestgroup \
    --replication-group-description authtest \
    --engine redis \ 
    --cache-node-type cache.m4.large \
    --num-node-groups 1 \
    --replicas-per-node-group 2 \    
    --transit-encryption-enabled \
    --auth-token This-is-a-sample-token \
    --cache-subnet-group sng-test
```

For Windows:

```
aws elasticache create-replication-group ^
    --replication-group-id authtestgroup ^
    --replication-group-description authtest ^
    --engine redis ^ 
    --cache-node-type cache.m4.large ^
    --num-node-groups 1 ^
    --replicas-per-node-group 2 ^    
    --transit-encryption-enabled ^
    --auth-token This-is-a-sample-token ^
    --cache-subnet-group sng-test
```

## Modifying the AUTH token on an existing cluster
<a name="auth-modifyng-token"></a>

To make it easier to update your authentication, you can modify the **AUTH** token used on a cluster. You can make this modification if the engine version is Valkey 7.2 or higher or Redis 5.0.6 or higher. ElastiCache must also have encryption in transit enabled. For more information, see [ElastiCache in-transit encryption (TLS)](in-transit-encryption.md).

Modifying the auth token supports two strategies: ROTATE and SET. The ROTATE strategy adds an additional AUTH token to the server while retaining the previous token. The SET strategy updates the server to support just a single AUTH token. Make these modification calls with the `--apply-immediately` parameter to apply changes immediately.

### Rotating the AUTH token
<a name="auth-modifyng-rotate"></a>

To update a Valkey or Redis OSS server with a new **AUTH token**, call the `ModifyReplicationGroup` API with the `--auth-token` parameter as the new **AUTH** token and the `--auth-token-update-strategy` with the value ROTATE. After the ROTATE modification is complete, the cluster will support the previous AUTH token in addition to the one specified in the `auth-token` parameter. If no AUTH token was configured on the replication group before the AUTH token rotation, the cluster supports the AUTH token specified in the `--auth-token` parameter in addition to supporting connecting without authentication. See [Setting the AUTH token](#auth-modifying-set) to update the AUTH token to be required using update strategy SET.

**Note**  
If you do not configure the AUTH token before, then once the modification is complete, the cluster will support no AUTH token in addition to the one specified in the auth-token parameter. 

If this modification is performed on a server that already supports two AUTH tokens, the oldest AUTH token will also be removed during this operation. This allows a server to support up to two most recent AUTH tokens at a given time.

At this point, you can proceed by updating the client to use the latest AUTH token. After the clients are updated, you can use the SET strategy for **AUTH** token rotation (explained in the following section) to exclusively start using the new token. 

The following AWS CLI operation modifies a replication group to rotate the **AUTH** token `This-is-the-rotated-token`.

For Linux, macOS, or Unix: 

```
aws elasticache modify-replication-group \
--replication-group-id authtestgroup \
--auth-token This-is-the-rotated-token \
--auth-token-update-strategy ROTATE \
--apply-immediately
```

For Windows:

```
aws elasticache modify-replication-group ^
--replication-group-id authtestgroup ^
--auth-token This-is-the-rotated-token ^
--auth-token-update-strategy ROTATE ^
--apply-immediately
```

### Setting the AUTH token
<a name="auth-modifying-set"></a>

To update a Valkey or Redis OSS server to support a single required **AUTH** token, call the `ModifyReplicationGroup` API operation with the `--auth-token` parameter with same value as the last AUTH token and the `--auth-token-update-strategy` parameter with the value `SET`. The SET strategy can only be used with a cluster that has 2 AUTH tokens or 1 optional AUTH token from using a ROTATE strategy before. After the modification is complete, the server supports only the AUTH token specified in the auth-token parameter. 

The following AWS CLI operation modifies a replication group to set the AUTH token to `This-is-the-set-token`.

For Linux, macOS, or Unix: 

```
aws elasticache modify-replication-group \
--replication-group-id authtestgroup \
--auth-token This-is-the-set-token \
--auth-token-update-strategy SET \
--apply-immediately
```

For Windows:

```
aws elasticache modify-replication-group ^
--replication-group-id authtestgroup ^
--auth-token This-is-the-set-token ^
--auth-token-update-strategy SET ^
--apply-immediately
```

### Enabling authentication on an existing cluster
<a name="auth-enabling"></a>

To enable authentication on an existing Valkey or Redis OSS server, call the `ModifyReplicationGroup` API operation. Call `ModifyReplicationGroup` with the `--auth-token` parameter as the new token and the `--auth-token-update-strategy` with the value ROTATE. 

After the ROTATE modification is complete, the cluster supports the **AUTH** token specified in the `--auth-token` parameter in addition to supporting connecting without authentication. Once all client applications are updated to authenticate to Valkey or Redis OSS with the AUTH token, use the SET strategy to mark the AUTH token as required. Enabling authentication is only supported on Valkey and Redis OSS servers with encryption in transit (TLS) enabled. 

## Migrating from RBAC to AUTH
<a name="Migrate-From-RBAC-to-AUTH"></a>

If you are authenticating users with Valkey or Redis OSS Role-Based Access Control (RBAC) as described in [Role-Based Access Control (RBAC)](Clusters.RBAC.md), and you want to migrate to AUTH, use the following procedures. You can migrate using either console or CLI. 

**To migrate from RBAC to AUTH using the console**

1. Sign in to the AWS Management Console and open the ElastiCache console at [ https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. From the list in the upper-right corner, choose the AWS Region where the cluster that you want to modify is located.

1. In the navigation pane, choose the engine running on the cluster that you want to modify.

   A list of the chosen engine's clusters appears.

1. In the list of clusters, for the cluster that you want to modify, choose its name. 

1. For **Actions**, choose **Modify**. 

   The **Modify** window appears.

1. For **Access control**, choose **Valkey AUTH default user access** or **Redis OSS AUTH default user access**.

1. Under **Valkey AUTH token** or **Redis OSS AUTH token**, set a new token. 

1. Choose **Preview changes** and then on the next screen, **Modify**.

**To migrate from RBAC to AUTH using the AWS CLI**

Use one of the following commands to configure a new optional **AUTH** token for your Valkey or Redis OSS replication group. Note that an optional Auth token will allow unauthenticated access to the replication group until the Auth token is marked as required, using the update strategy `SET` in the following step.

For Linux, macOS, or Unix:

```
aws elasticache modify-replication-group \
    --replication-group-id test \
    --remove-user-groups \
    --auth-token This-is-a-sample-token \
    --auth-token-update-strategy ROTATE \ 
    --apply-immediately
```

For Windows:

```
aws elasticache modify-replication-group ^
    --replication-group-id test ^
    --remove-user-groups ^
    --auth-token This-is-a-sample-token ^
    --auth-token-update-strategy ROTATE ^ 
    --apply-immediately
```

After executing the above command, you can update your Valkey or Redis OSS applications to authenticate to the ElastiCache replication group using the newly configured optional AUTH token. To complete the Auth token rotation, use the the update strategy `SET` in the subsequent command below. This will mark to the optional AUTH token as required. When the Auth token update completes, the replication group status will show as `ACTIVE` and all connections to this replication group will require authentication.

For Linux, macOS, or Unix:

```
aws elasticache modify-replication-group \
			--replication-group-id test \
			--auth-token This-is-a-sample-token \
			--auth-token-update-strategy SET \ 
			--apply-immediately
```

For Windows:

```
aws elasticache modify-replication-group ^
			--replication-group-id test ^
			--remove-user-groups ^
			--auth-token This-is-a-sample-token ^
			--auth-token-update-strategy SET ^ 
			--apply-immediately
```

For more information, see [Authenticating with the Valkey and Redis OSS AUTH command](#auth).

**Note**  
If you need to disable access control on an ElastiCache Cluster, see [Disabling access control on an ElastiCache Valkey or Redis OSS cache](in-transit-encryption-disable.md). 

# Migrating from password-based authentication (AUTH) to IAM authentication
<a name="auth-to-iam-migration"></a>

This guide describes how to migrate your Amazon ElastiCache node-based cluster or serverless cache from password-based authentication (AUTH) to AWS Identity and Access Management (IAM) authentication without service interruption.

**Note**  
We recommend testing this migration in a non-production environment before applying changes to your production environment.

## Overview
<a name="auth-to-iam-overview"></a>

IAM authentication provides enhanced security by eliminating the need for long-lived passwords. Instead, applications generate short-lived authentication tokens (valid for up to 15 minutes) using the [AWS Signature Version 4 signing process](https://docs.aws.amazon.com//general/latest/gr/signature-version-4.html).

## Prerequisites
<a name="auth-to-iam-prereqs"></a>

Before you begin, verify the following:
+ Your cache is running Redis OSS 7.0 or later, or Valkey. IAM authentication is not supported on earlier engine versions.
+ In-transit encryption (TLS) is enabled on your cache. IAM authentication requires TLS. For more information, see [ElastiCache in-transit encryption (TLS)](in-transit-encryption.md).
+ You have the necessary IAM permissions to create users and modify user groups. For more information, see [How Amazon ElastiCache works with IAM](security_iam_service-with-iam.md).
+ The IAM role or user that your application uses has an IAM policy that allows the `elasticache:Connect` action for the target cache and IAM user. For more information, see [Authenticating with IAM](auth-iam.md).
+ No additional IAM authentication limitations apply to your application. For the full list of limitations, see [Authenticating with IAM](auth-iam.md).

## Migration process
<a name="auth-to-iam-process"></a>

The migration process involves creating both a password-based and an IAM-authenticated user, verifying connectivity, and then transitioning your applications to IAM authentication.

### Step 1: Create users
<a name="auth-to-iam-create-users"></a>

Create two ElastiCache users so that your cache supports both password-based and IAM authentication during the migration period.

**Create a password-based authentication user**

**Note**  
If you already have a password-based user configured, you can skip creating a new one and use your existing user.

Use the following AWS CLI command to create a password-based user.

For Linux, macOS, or Unix:

```
aws elasticache create-user \
  --user-id <user-id> \
  --user-name default \
  --engine <engine> \
  --passwords "<your-existing-auth-password>" \
  --access-string "on ~* +@all"
```

For Windows:

```
aws elasticache create-user ^
  --user-id <user-id> ^
  --user-name default ^
  --engine <engine> ^
  --passwords "<your-existing-auth-password>" ^
  --access-string "on ~* +@all"
```

Replace:
+ *<user-id>* – A unique ID for this user.
+ *<engine>* – The engine your cache uses: `valkey` or `redis`.
+ *<your-existing-auth-password>* – The AUTH token currently configured on your cache.

**Create an IAM-authenticated user**

Use the following AWS CLI command to create an IAM-authenticated user.

For Linux, macOS, or Unix:

```
aws elasticache create-user \
  --user-id <iam-user-id> \
  --user-name <iam-user-name> \
  --authentication-mode Type=iam \
  --engine <engine> \
  --access-string "on ~* +@all"
```

For Windows:

```
aws elasticache create-user ^
  --user-id <iam-user-id> ^
  --user-name <iam-user-name> ^
  --authentication-mode Type=iam ^
  --engine <engine> ^
  --access-string "on ~* +@all"
```

Replace:
+ *<iam-user-id>* – A unique ID for the IAM user.
+ *<iam-user-name>* – The username for the IAM user.
+ *<engine>* – The engine your cache uses: `valkey` or `redis`.

### Step 2: Create and attach user group
<a name="auth-to-iam-user-group"></a>

If you already have a user group containing your password-based user, add the IAM-authenticated user to that existing group:

For Linux, macOS, or Unix:

```
aws elasticache modify-user-group \
  --user-group-id <user-group-id> \
  --user-ids-to-add <iam-user-id>
```

For Windows:

```
aws elasticache modify-user-group ^
  --user-group-id <user-group-id> ^
  --user-ids-to-add <iam-user-id>
```

Replace:
+ *<user-group-id>* – The ID of your existing user group.
+ *<iam-user-id>* – The user ID of the IAM-authenticated user created in Step 1.

Then skip to [Step 3: Verify both authentication methods](#auth-to-iam-verify-dual).

Otherwise, create a new user group, add both users, and attach the group to your cache.

Use the following AWS CLI commands to create a user group with both users:

For Linux, macOS, or Unix:

```
aws elasticache create-user-group \
  --user-group-id <user-group-id> \
  --engine <engine> \
  --user-ids <user-id> <iam-user-id>
```

For Windows:

```
aws elasticache create-user-group ^
  --user-group-id <user-group-id> ^
  --engine <engine> ^
  --user-ids <user-id> <iam-user-id>
```

Replace:
+ *<user-group-id>* – A unique ID for the user group.
+ *<engine>* – The engine your cache uses: `valkey` or `redis`.
+ *<user-id>*, *<iam-user-id>* – The user IDs created in Step 1.

Then modify your cache to use the new user group.

For node-based clusters:

For Linux, macOS, or Unix:

```
aws elasticache modify-replication-group \
  --replication-group-id <replication-group-id> \
  --auth-token-update-strategy DELETE \
  --user-group-ids-to-add <user-group-id>
```

For Windows:

```
aws elasticache modify-replication-group ^
  --replication-group-id <replication-group-id> ^
  --auth-token-update-strategy DELETE ^
  --user-group-ids-to-add <user-group-id>
```

Replace:
+ *<replication-group-id>* – The ID of your replication group.
+ *<user-group-id>* – The user group ID you created above.

For serverless caches:

For Linux, macOS, or Unix:

```
aws elasticache modify-serverless-cache \
  --serverless-cache-name <serverless-cache-name> \
  --user-group-id <user-group-id>
```

For Windows:

```
aws elasticache modify-serverless-cache ^
  --serverless-cache-name <serverless-cache-name> ^
  --user-group-id <user-group-id>
```

Replace:
+ *<serverless-cache-name>* – The name of your serverless cache.
+ *<user-group-id>* – The user group ID you created above.

### Step 3: Verify both authentication methods
<a name="auth-to-iam-verify-dual"></a>

After completing Step 2, your cache supports both authentication methods. Verify that applications can connect using both methods before proceeding.
+ Applications using password-based authentication can continue connecting with the password.
+ Applications configured for IAM authentication can connect using IAM tokens.

### Step 4: Connect with IAM
<a name="auth-to-iam-connect"></a>

**Generate an IAM authentication token**

Generate a short-lived IAM authentication token using an [AWS SigV4 pre-signed request](https://docs.aws.amazon.com//general/latest/gr/sigv4-signed-request-examples.html). The following Python example demonstrates token generation.

```
import boto3
from botocore.auth import SigV4QueryAuth
from botocore.awsrequest import AWSRequest

cache_name = "<cache-name>"
user = "<username>"
region = "<region>"
expires = 900

session = boto3.Session()
credentials = session.get_credentials().get_frozen_credentials()

req = AWSRequest(
    method="GET",
    url=f"http://{cache_name}/",
    params={"Action": "connect", "User": user}
)
SigV4QueryAuth(credentials, "elasticache", region, expires=expires).add_auth(req)

token = req.url.replace("http://", "")
print(token)
```

**Note**  
The generated token is valid for up to 15 minutes from creation.

**Connect using valkey-cli**

Connect to your ElastiCache cache using the generated token. You can use either **valkey-cli** or **redis-cli** to connect to Valkey clusters. For Redis OSS clusters, use **redis-cli**.

```
valkey-cli -h <host> -p 6379 --tls
```

For cluster mode enabled clusters, add the `--cluster` flag:

```
valkey-cli -h <host> -p 6379 --tls --cluster
```

Then authenticate with the following command:

```
AUTH <username> <token>
```

Replace:
+ *<host>* – The endpoint of your cache.
+ *<username>* – The username of the IAM-authenticated user.
+ *<token>* – The IAM authentication token you generated.

Expected output:

```
OK
```

Run the following command to validate the username:

```
ACL WHOAMI
```

### Step 5: Application integration
<a name="auth-to-iam-app-integration"></a>

For Java applications, use the default AWS Credentials provider chain to generate temporary security credentials. For more information, see [Authenticating with IAM](auth-iam.md). For other languages, generate the IAM authentication token using the [AWS Signature Version 4 signing process](https://docs.aws.amazon.com//general/latest/gr/signature-version-4.html) and pass it as the password in your client's `AUTH` command.

## Completing the migration
<a name="auth-to-iam-completing"></a>

After your applications can connect using IAM authentication, complete the following steps to finalize the migration.

### Step 1: Configure IAM authentication with fallback
<a name="auth-to-iam-fallback"></a>

Before removing the password-based user, update your application code to use IAM authentication as the primary method while keeping the password-based user as a fallback.

In your application code:
+ Configure your client to authenticate using IAM-generated tokens as the primary method.
+ Add a fallback mechanism so that if IAM authentication fails (for example, due to token expiry or a generation error), the client retries using the password-based AUTH credential.
+ Log all authentication attempts, including fallbacks and retries, so you can monitor whether any connections are falling back to password-based auth.

### Step 2: Monitor and verify
<a name="auth-to-iam-monitor"></a>

Review your application logs and the `IamAuthenticationExpirations` and `IamAuthenticationThrottling` Amazon CloudWatch metrics over at least 24–48 hours to confirm all connections are through IAM.

A non-zero value for either metric warrants investigation:
+ `IamAuthenticationExpirations` – An IAM authenticated connection is automatically disconnected after 12 hours. The connection can be prolonged by sending an `AUTH` or `HELLO` command with a new IAM authentication token.
+ `IamAuthenticationThrottling` – Indicates too many authentication requests, which might mean your application is generating tokens too aggressively or has connection pooling issues.

For node-based clusters, you can perform additional engine-level checks:
+ `ACL LOG` – Check for failed authentication attempts. Look for entries with `reason=auth`.
+ `CLIENT LIST` – Verify connected users. Check the `user=` field to confirm clients are using the IAM user.

`ACL LOG` and `CLIENT LIST` are available on node-based clusters only. For ElastiCache Serverless deployments, rely on application-side logging and Amazon CloudWatch metrics.

### Step 3: Remove the password-based user
<a name="auth-to-iam-remove-user"></a>

Once you confirm that all applications use IAM authentication, remove the password-based user from the user group.

**Valkey caches**

Remove the password-based user directly:

For Linux, macOS, or Unix:

```
aws elasticache modify-user-group \
   --user-group-id <user-group-id> \
   --user-ids-to-remove <password-user-id>
```

For Windows:

```
aws elasticache modify-user-group ^
   --user-group-id <user-group-id> ^
   --user-ids-to-remove <password-user-id>
```

**Redis OSS caches**

For Redis OSS caches, the user group must always contain a user with the username `default`. If the password-based user you created in Step 1 has the username `default`, you must create a disabled placeholder user to replace it before removing it:

For Linux, macOS, or Unix:

```
aws elasticache create-user \
   --user-id <disabled-default-id> \
   --user-name default \
   --engine redis \
   --no-password-required \
   --access-string "off ~* -@all"
```

For Windows:

```
aws elasticache create-user ^
   --user-id <disabled-default-id> ^
   --user-name default ^
   --engine redis ^
   --no-password-required ^
   --access-string "off ~* -@all"
```

Then add the disabled user to the group and remove the password-based user:

For Linux, macOS, or Unix:

```
aws elasticache modify-user-group \
   --user-group-id <user-group-id> \
   --user-ids-to-add <disabled-default-id> \
   --user-ids-to-remove <password-user-id>
```

For Windows:

```
aws elasticache modify-user-group ^
   --user-group-id <user-group-id> ^
   --user-ids-to-add <disabled-default-id> ^
   --user-ids-to-remove <password-user-id>
```

If the password-based user you created in Step 1 does not have the username `default`, you can remove it directly using the same command shown for Valkey caches above.

Replace:
+ *<disabled-default-id>* – A unique ID for the disabled placeholder user (Redis OSS only).
+ *<user-group-id>* – The ID of the user group associated with your cache.
+ *<password-user-id>* – The user ID of the password-based user to remove.

**Note**  
Do not delete the password-based user after removing it from the user group. Keep it available in case you need to roll back to password-based authentication.

### Step 4: Confirm post-removal
<a name="auth-to-iam-confirm"></a>

After removing the password-based user from the user group, monitor the `AuthenticationFailures` Amazon CloudWatch metric. A sustained value of zero confirms no authentication failures occurring, including any residual password-based attempts. Set a CloudWatch alarm on this metric to detect unexpected attempts.

For node-based clusters, you can also verify using `ACL LOG` and `CLIENT LIST`. For serverless caches, rely on application-side logging and CloudWatch metrics.

## Rollback procedure
<a name="auth-to-iam-rollback"></a>

Re-add the password-based user to the user group, then restore password-based authentication in your application while you investigate.

For Valkey caches:

For Linux, macOS, or Unix:

```
aws elasticache modify-user-group \
   --user-group-id <user-group-id> \
   --user-ids-to-add <password-user-id>
```

For Windows:

```
aws elasticache modify-user-group ^
   --user-group-id <user-group-id> ^
   --user-ids-to-add <password-user-id>
```

For Redis OSS caches where the password-based user does not have the username `default`, use the same command above.

For Redis OSS caches where you created a disabled placeholder user in [Step 3: Remove the password-based user](#auth-to-iam-remove-user), add the password-based user and remove the disabled placeholder user in a single operation:

For Linux, macOS, or Unix:

```
aws elasticache modify-user-group \
   --user-group-id <user-group-id> \
   --user-ids-to-add <password-user-id> \
   --user-ids-to-remove <disabled-default-id>
```

For Windows:

```
aws elasticache modify-user-group ^
   --user-group-id <user-group-id> ^
   --user-ids-to-add <password-user-id> ^
   --user-ids-to-remove <disabled-default-id>
```

Replace:
+ *<user-group-id>* – The ID of the user group associated with your cache.
+ *<password-user-id>* – The user ID of the password-based user to re-add.
+ *<disabled-default-id>* – The user ID of the disabled placeholder user (Redis OSS only).

# Disabling access control on an ElastiCache Valkey or Redis OSS cache
<a name="in-transit-encryption-disable"></a>

Follow the instructions below to disable access control on a Valkey or Redis OSS TLS-enabled cache. Your cache will have one of two different types of configurations: AUTH default user access or User group access control list (RBAC). If your cache was created with the AUTH configuration, you have to change it to the RBAC configuration before you can disable the cache by removing the user groups. If your cache was created with the RBAC configuration, you can go straight into disabling it.

**To disable a Valkey or Redis OSS serverless cache configured with RBAC**

1. Remove the user groups to disable the access control.

   ```
   aws elasticache modify-serverless-cache --serverless-cache-name <serverless-cache> --remove-user-group
   ```

1. (Optional) Verify that no user groups are associated with the serverless cache.

   ```
   aws elasticache describe-serverless-caches --serverless-cache-name <serverless-cache>    
   {
       "..."
       "UserGroupId": ""
       "..."
   }
   ```

**To disable a Valkey or Redis OSS cache with configured with an AUTH token**

1. Change the AUTH token to RBAC and specify a user group to add.

   ```
   aws elasticache modify-replication-group --replication-group-id <replication-group-id-value> --auth-token-update-strategy DELETE --user-group-ids-to-add <user-group-value>
   ```

1. Verify that the AUTH token got disabled and that a user group was added.

   ```
   aws elasticache describe-replication-groups --replication-group-id <replication-group-id-value>
   {
       "..."
       "AuthTokenEnabled": false,
       "UserGroupIds": [
           "<user-group-value>"
       ]
       "..."
   }
   ```

1. Remove the user groups to disable the access control.

   ```
   aws elasticache modify-replication-group --replication-group-id <replication-group-value> --user-group-ids-to-remove <user-group-value>
   {
       "..."
       "PendingModifiedValues": {
       "UserGroups": {
         "UserGroupIdsToAdd": [],
         "UserGroupIdsToRemove": [
           "<user-group-value>"
         ]
       }
       "..."
   }
   ```

1. (Optional) Verify that no user groups are associated with the cluster. The `AuthTokenEnabled` field should also read false.

   ```
   aws elasticache describe-replication-groups --replication-group-id <replication-group-value>    
   "AuthTokenEnabled": false
   ```

**To disable a Valkey or Redis OSS cluster configured with RBAC**

1. Remove the user groups to disable the access control.

   ```
   aws elasticache modify-replication-group --replication-group-id <replication-group-value> --user-group-ids-to-remove <user-group-value>
   {
       "..."
       "PendingModifiedValues": {
       "UserGroups": {
         "UserGroupIdsToAdd": [],
         "UserGroupIdsToRemove": [
           "<user-group-value>"
         ]
       }
       "..."
   }
   ```

1. (Optional) Verify that no user groups are associated with the cluster. The `AuthTokenEnabled` field should also read false.

   ```
   aws elasticache describe-replication-groups --replication-group-id <replication-group-value>    
   "AuthTokenEnabled": false
   ```