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:

// 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:

  1. 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.
  2. 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.
  3. Remove the old token — after all instances are running the new version, update the replication group again with AuthTokenUpdateStrategy: SET to 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.

Common failure modes

SymptomCauseFix
WRONGPASS invalid username-password pair or user is disabledAUTH token is incorrect, expired, or rotated without updating the applicationVerify 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 setioredis is sending a password (password option set) but the cluster has no AUTH token enabledRemove the password option from the ioredis constructor, or enable AUTH on the cluster
API error: AuthToken is not allowed for non-encrypted clustersAttempting to set authToken without transitEncryptionEnabled: trueEnable transitEncryptionEnabled: true alongside authToken — both must be set at cluster creation
TLS handshake failure: SELF_SIGNED_CERT_IN_CHAINConnecting to an older ElastiCache cluster with a private CA not in Node's default bundleDownload 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 rotationUsing single-step rotation (SET strategy immediately) instead of two-step ROTATE → SETUse 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' commandRBAC user does not have write permissions; connected with wrong userCheck the ACL access string for the user; add +@write or the specific command needed; verify the ioredis connection is using the correct user credentials