Guide · AWS ElastiCache
MCP Server ElastiCache AUTH and Encryption — AUTH token, TLS, RBAC, at-rest encryption
ElastiCache Redis AUTH and encryption must be configured at cluster creation — they cannot be added to an existing cluster without replacement. Two details catch teams when adding security: in-transit encryption is required to use AUTH — attempting to enable the AUTH token without transitEncryptionEnabled: true is rejected by the API; and AUTH token rotation is a two-step process — you can hold both an old and a new AUTH token simultaneously during the transition window. If you rotate by deleting the old token and setting a new one atomically, any in-flight ioredis connections authenticated with the old token will be disconnected. ElastiCache Redis 7+ with cluster mode supports RBAC via user groups — create separate Redis users with ACL rules restricting which commands and key prefixes are accessible, then assign user groups to the replication group to isolate multi-tenant MCP tool access.
TL;DR
Enable transitEncryptionEnabled: true and atRestEncryptionEnabled: true at cluster creation. Set an authToken of 16–128 alphanumeric characters. Store the token in Secrets Manager and inject it into your MCP server via environment variable — never hardcode it. To rotate: add the new token (ElastiCache accepts both old and new simultaneously for up to one hour), deploy the new application, then remove the old token.
AUTH token requirements
The ElastiCache AUTH token is a password that Redis checks on every connection via the AUTH command. Requirements:
- Length: 16 to 128 characters.
- Allowed characters: uppercase and lowercase letters, digits, and the following special characters:
!&#$^<>-. Spaces and most other special characters are not allowed. - In-transit encryption must be enabled — ElastiCache rejects the
authTokenparameter iftransitEncryptionEnabledis false. - The token is stored encrypted in AWS — it is not retrievable via the ElastiCache API after creation. Store it in Secrets Manager at creation time.
// CDK: create a random AUTH token and store in Secrets Manager
import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
import * as elasticache from "aws-cdk-lib/aws-elasticache";
const authTokenSecret = new secretsmanager.Secret(this, "RedisAuthToken", {
secretName: "prod/mcp-server/redis-auth-token",
generateSecretString: {
// Generate a 32-char alphanumeric token (no special chars for simplicity)
excludePunctuation: true,
passwordLength: 32,
generateStringKey: "token",
secretStringTemplate: JSON.stringify({ description: "ElastiCache auth token" }),
},
});
const redis = new elasticache.CfnReplicationGroup(this, "McpRedis", {
replicationGroupDescription: "MCP server session cache",
cacheNodeType: "cache.t4g.small",
engine: "redis",
engineVersion: "7.1",
// Auth token — must match the secret value at creation time
authToken: authTokenSecret.secretValueFromJson("token").unsafeUnwrap(),
// In-transit encryption required for authToken
transitEncryptionEnabled: true,
// At-rest encryption — enable at creation, cannot change later
atRestEncryptionEnabled: true,
// ... subnet group, security groups, parameter group
});
In your MCP server Lambda or ECS task, retrieve the token from Secrets Manager at startup:
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
import Redis from "ioredis";
const smClient = new SecretsManagerClient({ region: process.env.AWS_REGION });
let redis: Redis | null = null;
async function getRedis(): Promise {
if (redis) return redis;
const secret = await smClient.send(
new GetSecretValueCommand({ SecretId: "prod/mcp-server/redis-auth-token" })
);
const { token } = JSON.parse(secret.SecretString!);
redis = new Redis({
host: process.env.ELASTICACHE_PRIMARY_ENDPOINT,
port: 6379,
password: token,
tls: {},
connectTimeout: 5000,
});
return redis;
}
In-transit TLS configuration
When transitEncryptionEnabled: true, all connections to the cluster must use TLS. Configure ioredis with tls: {}:
// Minimal TLS config — uses Node's default CA bundle which includes AWS's root CA
const redis = new Redis({
host: process.env.ELASTICACHE_PRIMARY_ENDPOINT,
port: 6379,
password: process.env.REDIS_AUTH_TOKEN,
tls: {},
});
// If you see certificate verification errors, check the ElastiCache TLS mode:
// - "required" (default since Redis 6 on newer ElastiCache): TLS enforced
// - "preferred": TLS optional
//
// On older ElastiCache versions with self-signed or private CA certificates,
// you may need to explicitly set rejectUnauthorized:
const redisWithCustomCa = new Redis({
host: process.env.ELASTICACHE_PRIMARY_ENDPOINT,
port: 6379,
password: process.env.REDIS_AUTH_TOKEN,
tls: {
// Set to false ONLY if you are using an older ElastiCache configuration
// with a private CA that is not in Node's default bundle.
// Leaving rejectUnauthorized:true is always preferred.
rejectUnauthorized: true,
},
});
Modern ElastiCache clusters (Redis 6+) use AWS Certificate Manager certificates signed by the Amazon Root CA — trusted by Node.js 18+ out of the box. If you see DEPTH_ZERO_SELF_SIGNED_CERT errors, you are likely connecting to an older cluster generation; check the ElastiCache documentation for the correct CA bundle for your region.
Zero-downtime AUTH token rotation
ElastiCache supports a two-token transition window for AUTH token rotation. During the window, the cluster accepts both the old and new AUTH token simultaneously, allowing a rolling deployment.
Rotation steps:
- Add the new token — update the replication group via the AWS Console, CLI, or CDK with the new token; set
AuthTokenUpdateStrategy: ROTATE. ElastiCache begins accepting both old and new tokens. - Deploy the new application version — update the secret in Secrets Manager with the new token value; redeploy the MCP server so new instances pick up the new token. Old instances continue to work with the old token.
- Remove the old token — after all instances are running the new version, update the replication group again with
AuthTokenUpdateStrategy: SETto finalize the new token and stop accepting the old one. The transition window is up to one hour.
# Step 1: Add new token (ROTATE strategy — accepts both old and new)
aws elasticache modify-replication-group \
--replication-group-id mcp-redis \
--auth-token "NEW_TOKEN_HERE" \
--auth-token-update-strategy ROTATE \
--apply-immediately
# Step 3: After deploying new app version, finalize (SET strategy — only new token)
aws elasticache modify-replication-group \
--replication-group-id mcp-redis \
--auth-token "NEW_TOKEN_HERE" \
--auth-token-update-strategy SET \
--apply-immediately
RBAC user groups (Redis 7+)
ElastiCache for Redis 7 supports Access Control Lists (ACL) through managed users and user groups. This enables multi-tenant MCP servers to give different tenants different Redis access levels without maintaining separate clusters.
# Create a read-only user for MCP tools that only need to read session state
aws elasticache create-user \
--user-id mcp-reader \
--user-name mcp-reader \
--engine redis \
--passwords "ReadOnlyPassword123!" \
--access-string "on ~session:* &* -@all +@read +@connection"
# Create a read-write user for MCP tools that modify session state
aws elasticache create-user \
--user-id mcp-writer \
--user-name mcp-writer \
--engine redis \
--passwords "ReadWritePassword456!" \
--access-string "on ~session:* &* -@all +@read +@write +@connection +expire +del"
# Create a user group and attach both users
aws elasticache create-user-group \
--user-group-id mcp-user-group \
--engine redis \
--user-ids default mcp-reader mcp-writer
# Associate the user group with your replication group
aws elasticache modify-replication-group \
--replication-group-id mcp-redis \
--user-group-ids-to-add mcp-user-group \
--apply-immediately
The ACL access string format follows the Redis ACL specification: on enables the user; ~session:* restricts the user to keys starting with session:; -@all +@read denies all commands then re-grants the read command category. When using user groups, the authToken on the replication group must be cleared — authentication is done via individual user passwords.
At-rest encryption
At-rest encryption encrypts all data stored on disk (RDB snapshots, AOF logs, swap files). Enable it at cluster creation — it cannot be enabled on an existing cluster; you must create a new cluster and migrate data.
- Default: AWS managed key (no additional configuration required; uses the
aws/elasticachemanaged key). - Customer managed key (CMK): specify a KMS key ARN via
kmsKeyIdin the CDK construct or--kms-key-idin the CLI. CMKs allow you to control key rotation policy and grant/revoke access independently. - At-rest encryption has no measurable performance impact for MCP session state workloads — ElastiCache uses AES-256 hardware acceleration on all modern instance types.
Common failure modes
| Symptom | Cause | Fix |
|---|---|---|
WRONGPASS invalid username-password pair or user is disabled | AUTH token is incorrect, expired, or rotated without updating the application | Verify the token in Secrets Manager matches the current ElastiCache AUTH token; check that the application retrieved the latest secret version |
ERR Client sent AUTH, but no password is set | ioredis is sending a password (password option set) but the cluster has no AUTH token enabled | Remove the password option from the ioredis constructor, or enable AUTH on the cluster |
API error: AuthToken is not allowed for non-encrypted clusters | Attempting to set authToken without transitEncryptionEnabled: true | Enable transitEncryptionEnabled: true alongside authToken — both must be set at cluster creation |
TLS handshake failure: SELF_SIGNED_CERT_IN_CHAIN | Connecting to an older ElastiCache cluster with a private CA not in Node's default bundle | Download the ElastiCache TLS CA certificate from the AWS documentation for your region and pass it via tls: { ca: fs.readFileSync('amazon-root-ca.pem') } |
| Connections dropped after AUTH token rotation | Using single-step rotation (SET strategy immediately) instead of two-step ROTATE → SET | Use ROTATE strategy first to accept both tokens, deploy new app, then SET strategy to finalize; allows zero-downtime rotation |
ACL error: NOPERM this user has no permissions to run the 'set' command | RBAC user does not have write permissions; connected with wrong user | Check the ACL access string for the user; add +@write or the specific command needed; verify the ioredis connection is using the correct user credentials |