

# 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());
    }
}
```