The aws:elasticache/user:User resource, part of the Pulumi AWS provider, defines ElastiCache users with authentication methods and access permissions for Redis or Valkey clusters. This guide focuses on three capabilities: password and IAM authentication, access string permissions, and dual-password rotation.
ElastiCache users don’t operate independently; they must be attached to user groups, which are then associated with clusters. The examples are intentionally small. Combine them with ElastiCache user groups and cluster configuration.
Create a user with password authentication and scoped access
Most deployments create users with password-based authentication and access strings that limit which commands and keys they can use.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.elasticache.User("test", {
userId: "testUserId",
userName: "testUserName",
accessString: "on ~app::* -@all +@read +@hash +@bitmap +@geo -setbit -bitfield -hset -hsetnx -hmset -hincrby -hincrbyfloat -hdel -bitop -geoadd -georadius -georadiusbymember",
engine: "redis",
passwords: ["password123456789"],
});
import pulumi
import pulumi_aws as aws
test = aws.elasticache.User("test",
user_id="testUserId",
user_name="testUserName",
access_string="on ~app::* -@all +@read +@hash +@bitmap +@geo -setbit -bitfield -hset -hsetnx -hmset -hincrby -hincrbyfloat -hdel -bitop -geoadd -georadius -georadiusbymember",
engine="redis",
passwords=["password123456789"])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/elasticache"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := elasticache.NewUser(ctx, "test", &elasticache.UserArgs{
UserId: pulumi.String("testUserId"),
UserName: pulumi.String("testUserName"),
AccessString: pulumi.String("on ~app::* -@all +@read +@hash +@bitmap +@geo -setbit -bitfield -hset -hsetnx -hmset -hincrby -hincrbyfloat -hdel -bitop -geoadd -georadius -georadiusbymember"),
Engine: pulumi.String("redis"),
Passwords: pulumi.StringArray{
pulumi.String("password123456789"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = new Aws.ElastiCache.User("test", new()
{
UserId = "testUserId",
UserName = "testUserName",
AccessString = "on ~app::* -@all +@read +@hash +@bitmap +@geo -setbit -bitfield -hset -hsetnx -hmset -hincrby -hincrbyfloat -hdel -bitop -geoadd -georadius -georadiusbymember",
Engine = "redis",
Passwords = new[]
{
"password123456789",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.elasticache.User;
import com.pulumi.aws.elasticache.UserArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var test = new User("test", UserArgs.builder()
.userId("testUserId")
.userName("testUserName")
.accessString("on ~app::* -@all +@read +@hash +@bitmap +@geo -setbit -bitfield -hset -hsetnx -hmset -hincrby -hincrbyfloat -hdel -bitop -geoadd -georadius -georadiusbymember")
.engine("redis")
.passwords("password123456789")
.build());
}
}
resources:
test:
type: aws:elasticache:User
properties:
userId: testUserId
userName: testUserName
accessString: on ~app::* -@all +@read +@hash +@bitmap +@geo -setbit -bitfield -hset -hsetnx -hmset -hincrby -hincrbyfloat -hdel -bitop -geoadd -georadius -georadiusbymember
engine: redis
passwords:
- password123456789
The accessString property defines what the user can do. The syntax follows the pattern: on (user is active), ~app::* (key pattern), -@all (deny all commands), then +@read +@hash (allow specific command categories). The passwords array holds one or two passwords for authentication. All credentials are stored in plain-text in Pulumi state.
Authenticate users with IAM instead of passwords
Teams using AWS IAM for centralized identity can authenticate through IAM policies rather than managing passwords.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.elasticache.User("test", {
userId: "testUserId",
userName: "testUserName",
accessString: "on ~* +@all",
engine: "redis",
authenticationMode: {
type: "iam",
},
});
import pulumi
import pulumi_aws as aws
test = aws.elasticache.User("test",
user_id="testUserId",
user_name="testUserName",
access_string="on ~* +@all",
engine="redis",
authentication_mode={
"type": "iam",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/elasticache"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := elasticache.NewUser(ctx, "test", &elasticache.UserArgs{
UserId: pulumi.String("testUserId"),
UserName: pulumi.String("testUserName"),
AccessString: pulumi.String("on ~* +@all"),
Engine: pulumi.String("redis"),
AuthenticationMode: &elasticache.UserAuthenticationModeArgs{
Type: pulumi.String("iam"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = new Aws.ElastiCache.User("test", new()
{
UserId = "testUserId",
UserName = "testUserName",
AccessString = "on ~* +@all",
Engine = "redis",
AuthenticationMode = new Aws.ElastiCache.Inputs.UserAuthenticationModeArgs
{
Type = "iam",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.elasticache.User;
import com.pulumi.aws.elasticache.UserArgs;
import com.pulumi.aws.elasticache.inputs.UserAuthenticationModeArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var test = new User("test", UserArgs.builder()
.userId("testUserId")
.userName("testUserName")
.accessString("on ~* +@all")
.engine("redis")
.authenticationMode(UserAuthenticationModeArgs.builder()
.type("iam")
.build())
.build());
}
}
resources:
test:
type: aws:elasticache:User
properties:
userId: testUserId
userName: testUserName
accessString: on ~* +@all
engine: redis
authenticationMode:
type: iam
The authenticationMode property switches from password to IAM authentication. When type is set to iam, ElastiCache validates requests using AWS IAM credentials instead of passwords. The accessString still controls command and key permissions.
Configure password rotation with dual passwords
ElastiCache supports up to two passwords per user, enabling zero-downtime rotation.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.elasticache.User("test", {
userId: "testUserId",
userName: "testUserName",
accessString: "on ~* +@all",
engine: "redis",
authenticationMode: {
type: "password",
passwords: [
"password1",
"password2",
],
},
});
import pulumi
import pulumi_aws as aws
test = aws.elasticache.User("test",
user_id="testUserId",
user_name="testUserName",
access_string="on ~* +@all",
engine="redis",
authentication_mode={
"type": "password",
"passwords": [
"password1",
"password2",
],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/elasticache"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := elasticache.NewUser(ctx, "test", &elasticache.UserArgs{
UserId: pulumi.String("testUserId"),
UserName: pulumi.String("testUserName"),
AccessString: pulumi.String("on ~* +@all"),
Engine: pulumi.String("redis"),
AuthenticationMode: &elasticache.UserAuthenticationModeArgs{
Type: pulumi.String("password"),
Passwords: pulumi.StringArray{
pulumi.String("password1"),
pulumi.String("password2"),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = new Aws.ElastiCache.User("test", new()
{
UserId = "testUserId",
UserName = "testUserName",
AccessString = "on ~* +@all",
Engine = "redis",
AuthenticationMode = new Aws.ElastiCache.Inputs.UserAuthenticationModeArgs
{
Type = "password",
Passwords = new[]
{
"password1",
"password2",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.elasticache.User;
import com.pulumi.aws.elasticache.UserArgs;
import com.pulumi.aws.elasticache.inputs.UserAuthenticationModeArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var test = new User("test", UserArgs.builder()
.userId("testUserId")
.userName("testUserName")
.accessString("on ~* +@all")
.engine("redis")
.authenticationMode(UserAuthenticationModeArgs.builder()
.type("password")
.passwords(
"password1",
"password2")
.build())
.build());
}
}
resources:
test:
type: aws:elasticache:User
properties:
userId: testUserId
userName: testUserName
accessString: on ~* +@all
engine: redis
authenticationMode:
type: password
passwords:
- password1
- password2
The authenticationMode property with type password accepts a passwords array with up to two entries. During rotation, add the new password while keeping the old one, update clients, then remove the old password. Both passwords work simultaneously during the transition.
Beyond these examples
These snippets focus on specific user-level features: password and IAM authentication, access string permissions, and dual-password rotation. They’re intentionally minimal rather than full cluster access control configurations.
The examples assume pre-existing infrastructure such as ElastiCache Redis or Valkey clusters. Users must be attached to user groups separately. They focus on user configuration rather than provisioning clusters or groups.
To keep things focused, common user patterns are omitted, including:
- User group attachment (users must be added to groups separately)
- Tag-based organization (tags property)
- Passwordless access (noPasswordRequired)
- Access string syntax and command categories
These omissions are intentional: the goal is to illustrate how each user feature is wired, not provide drop-in access control modules. See the ElastiCache User resource reference for all available configuration options.
Let's create AWS ElastiCache Users
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Security & State Management
Authentication & Passwords
authenticationMode property with type set to either iam or password.authenticationMode.type to iam and don’t specify the passwords field. This avoids storing credentials in state.passwords array.noPasswordRequired to true to indicate no password is needed for the user.Access Control & Permissions
accessString property with Redis ACL syntax to control permissions. For example, you can allow specific commands like +@read +@hash while denying others like -setbit -bitfield. See the AWS documentation on Access Strings for detailed syntax.Configuration & Immutability
userId and userName are immutable. Changing either requires replacing the resource, so plan these values carefully during initial creation.redis and valkey engines (case insensitive).