| name | redis-security |
| description | Master Redis security - authentication, ACL, TLS encryption, network hardening, and production security best practices |
| sasmp_version | 1.3.0 |
| bonded_agent | 07-redis-security |
| bond_type | PRIMARY_BOND |
| version | 2.1.0 |
| last_updated | 2025-01 |
| parameters | [object Object] |
| retry_config | [object Object] |
| observability | [object Object] |
Redis Security Skill
Security Maturity Levels
| Level | Features | Use Case |
|---|---|---|
| Basic | Password only | Development |
| Standard | ACL + Network | Internal apps |
| High | ACL + TLS + Network | Production |
| Paranoid | All + Audit + WAF | Financial/Healthcare |
Authentication
Legacy Password (Pre-6.0)
# redis.conf
requirepass your_strong_password_here_min_32_chars
AUTH password
ACL Authentication (Redis 6.0+)
AUTH username password
Access Control Lists (ACL)
User Management
# Create user with specific permissions
ACL SETUSER app_user on >secure_password ~app:* +@read +@write -@dangerous
# Create read-only user
ACL SETUSER readonly_user on >password ~* +@read -@write -@admin
# Create admin user
ACL SETUSER admin_user on >strong_password ~* +@all
# Disable user
ACL SETUSER app_user off
# Delete user
ACL DELUSER app_user
# List all users
ACL LIST
# Show current user
ACL WHOAMI
ACL Rule Syntax
ACL SETUSER username [on|off] [>password|#hash] [~pattern] [+command|-command] [+@category|-@category]
Key Patterns:
~*- All keys~app:*- Keys starting with "app:"~user:${USER}:*- Variable pattern (Redis 7+)
Command Categories:
ACL CAT # List all categories
# Common categories:
# @read - Read commands (GET, MGET, etc.)
# @write - Write commands (SET, DEL, etc.)
# @admin - Admin commands (CONFIG, DEBUG, etc.)
# @dangerous - Potentially harmful (KEYS, FLUSHALL, etc.)
# @slow - Commands that may block
# @fast - O(1) commands
# @pubsub - Pub/Sub commands
# @scripting - Lua scripting
ACL File
# acl-users.conf
user default off
user admin on >admin_password ~* +@all
user app on >app_password ~app:* +@read +@write -@dangerous
user readonly on >ro_password ~* +@read -@write -@admin
user replication on >repl_password +psync +replconf +ping
# redis.conf
aclfile /etc/redis/acl-users.conf
ACL Audit Log
# View ACL violations
ACL LOG [count]
# Reset log
ACL LOG RESET
TLS Configuration
Generate Certificates
#!/bin/bash
# generate-certs.sh
# CA
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -sha256 -days 3650 \
-key ca.key -out ca.crt \
-subj "/CN=Redis-CA"
# Server
openssl genrsa -out redis.key 2048
openssl req -new -key redis.key -out redis.csr \
-subj "/CN=redis-server"
openssl x509 -req -in redis.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out redis.crt -days 365 -sha256
# Client (optional for mTLS)
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr \
-subj "/CN=redis-client"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out client.crt -days 365 -sha256
# Set permissions
chmod 600 *.key
chmod 644 *.crt
Server Configuration
# redis.conf
# TLS port (disable plain port)
tls-port 6379
port 0
# Certificates
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
# Require client certificates (mTLS)
tls-auth-clients yes # or 'optional' or 'no'
# TLS versions (disable old versions)
tls-protocols "TLSv1.2 TLSv1.3"
# Cipher suites
tls-ciphersuites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
tls-ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256"
# Replication over TLS
tls-replication yes
# Cluster over TLS
tls-cluster yes
Client Connection
# redis-cli with TLS
redis-cli --tls \
--cert /path/to/client.crt \
--key /path/to/client.key \
--cacert /path/to/ca.crt \
-h redis.example.com
# Python with TLS
import redis
r = redis.Redis(
host='redis.example.com',
port=6379,
ssl=True,
ssl_certfile='/path/to/client.crt',
ssl_keyfile='/path/to/client.key',
ssl_ca_certs='/path/to/ca.crt'
)
Network Security
Bind Configuration
# redis.conf
# Bind to specific interfaces
bind 127.0.0.1 -::1 # Localhost only
bind 10.0.0.1 127.0.0.1 # Internal + localhost
# Protected mode (blocks external when no password)
protected-mode yes
Firewall Rules
# UFW
ufw allow from 10.0.0.0/8 to any port 6379
# iptables
iptables -A INPUT -p tcp -s 10.0.0.0/8 --dport 6379 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
# Kubernetes NetworkPolicy
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: redis-policy
spec:
podSelector:
matchLabels:
app: redis
ingress:
- from:
- podSelector:
matchLabels:
access: redis
ports:
- port: 6379
Command Restrictions
Rename Dangerous Commands
# redis.conf
rename-command FLUSHALL "" # Disable completely
rename-command FLUSHDB ""
rename-command DEBUG ""
rename-command SHUTDOWN SHUTDOWN_b840fc02 # Rename
rename-command CONFIG CONFIG_b840fc02
rename-command KEYS "" # Disable (use SCAN)
rename-command BGSAVE "" # Control via ACL instead
ACL-Based Restrictions (Preferred)
# Better than rename-command
ACL SETUSER app_user on >password ~app:* +@all -@dangerous -CONFIG -DEBUG -SHUTDOWN
Security Checklist
Development
□ Set requirepass
□ Bind to localhost only
□ Enable protected-mode
Staging
□ Configure ACL users
□ Disable default user
□ Enable TLS
□ Restrict network access
□ Disable dangerous commands
Production
□ Strong unique passwords (32+ chars)
□ Per-application ACL users
□ mTLS with client certificates
□ Firewall/NetworkPolicy
□ No public internet exposure
□ Regular credential rotation
□ ACL audit logging enabled
□ Rename/disable admin commands
□ Regular security updates
□ Backup encryption
Security Headers Check Script
#!/bin/bash
# security-audit.sh
REDIS_HOST=${1:-localhost}
REDIS_PORT=${2:-6379}
echo "=== Redis Security Audit ==="
# Check authentication
echo -n "Authentication required: "
if redis-cli -h $REDIS_HOST -p $REDIS_PORT PING 2>&1 | grep -q "NOAUTH"; then
echo "YES ✓"
else
echo "NO ✗ (WARNING)"
fi
# Check protected mode
echo -n "Protected mode: "
redis-cli -h $REDIS_HOST -p $REDIS_PORT CONFIG GET protected-mode | grep -q "yes" && echo "YES ✓" || echo "NO ✗"
# Check TLS
echo -n "TLS enabled: "
redis-cli -h $REDIS_HOST -p $REDIS_PORT --tls INFO server 2>/dev/null && echo "YES ✓" || echo "NO ✗"
# Check dangerous commands
echo "Dangerous commands:"
for cmd in FLUSHALL FLUSHDB DEBUG KEYS CONFIG; do
echo -n " $cmd: "
if redis-cli -h $REDIS_HOST -p $REDIS_PORT ACL CAT 2>/dev/null | grep -q "^$cmd$"; then
echo "AVAILABLE ✗"
else
echo "RESTRICTED ✓"
fi
done
Assets
acl-users.conf- ACL user definitionssecurity-checklist.md- Security audit checklistgenerate-certs.sh- TLS certificate generation
References
SECURITY_GUIDE.md- Complete security guide
Troubleshooting Guide
Common Issues & Solutions
1. Authentication Failures
NOAUTH Authentication required
Fix:
AUTH password
# or
AUTH username password
2. ACL Permission Denied
NOPERM this user has no permissions to run the 'CONFIG' command
Diagnosis:
ACL WHOAMI
ACL LIST
Fix: Update user permissions
ACL SETUSER myuser +CONFIG
3. TLS Connection Failed
SSL_connect: certificate verify failed
Fixes:
# Check certificate dates
openssl x509 -in redis.crt -noout -dates
# Verify certificate chain
openssl verify -CAfile ca.crt redis.crt
# Check hostname matches
openssl x509 -in redis.crt -noout -text | grep DNS
4. Protected Mode Blocking
DENIED Redis is running in protected mode
Fix options:
- Bind to specific IP (not 0.0.0.0)
- Set password with requirepass
- Disable protected-mode (NOT recommended)
5. Client Certificate Required
SSL: certificate required
Fix: Provide client certificate
redis-cli --tls --cert client.crt --key client.key --cacert ca.crt
Debug Checklist
□ Password set? (CONFIG GET requirepass)
□ User exists? (ACL LIST)
□ User enabled? (ACL GETUSER username)
□ Correct permissions? (ACL GETUSER username)
□ TLS certs valid? (openssl verify)
□ Firewall allows connection?
□ Bind includes client IP? (CONFIG GET bind)
□ Protected mode appropriate? (CONFIG GET protected-mode)
Security Incident Response
1. Immediate Actions:
□ Block compromised credentials (ACL SETUSER user off)
□ Enable ACL LOG monitoring
□ Check for unauthorized commands (MONITOR briefly)
2. Investigation:
□ Review ACL LOG
□ Check client list (CLIENT LIST)
□ Audit data integrity (DBSIZE, SCAN)
3. Remediation:
□ Rotate all credentials
□ Update firewall rules
□ Enable/strengthen TLS
□ Review and restrict ACLs
Error Codes Reference
| Code | Name | Description | Recovery |
|---|---|---|---|
| SEC001 | NOAUTH | Not authenticated | AUTH command |
| SEC002 | WRONGPASS | Invalid password | Check credentials |
| SEC003 | NOPERM | ACL permission denied | Update ACL |
| SEC004 | TLS_CERT | Certificate error | Fix certificate |
| SEC005 | PROTECTED | Protected mode block | Configure properly |
Test Template
# test_redis_security.py
import redis
import pytest
import ssl
@pytest.fixture
def r_auth():
return redis.Redis(
host='localhost',
port=6379,
password='test_password',
decode_responses=True
)
class TestAuthentication:
def test_auth_required(self):
r = redis.Redis(decode_responses=True)
with pytest.raises(redis.AuthenticationError):
r.ping()
def test_auth_success(self, r_auth):
assert r_auth.ping() == True
def test_wrong_password(self):
r = redis.Redis(password='wrong_password')
with pytest.raises(redis.AuthenticationError):
r.ping()
class TestACL:
def test_acl_whoami(self, r_auth):
result = r_auth.acl_whoami()
assert result is not None
def test_acl_list(self, r_auth):
users = r_auth.acl_list()
assert len(users) > 0
def test_permission_denied(self, r_auth):
# Create limited user
r_auth.acl_setuser(
"limited_user",
enabled=True,
passwords=["+limited_pass"],
keys=["allowed:*"],
commands=["+get", "-set"]
)
# Connect as limited user
r_limited = redis.Redis(
username="limited_user",
password="limited_pass",
decode_responses=True
)
# Should fail
with pytest.raises(redis.ResponseError, match="NOPERM"):
r_limited.set("forbidden:key", "value")
# Cleanup
r_auth.acl_deluser("limited_user")
class TestTLS:
def test_tls_connection(self):
"""Test TLS connection (requires TLS-enabled Redis)"""
try:
r = redis.Redis(
host='localhost',
port=6379,
ssl=True,
ssl_cert_reqs=ssl.CERT_REQUIRED,
ssl_ca_certs='/path/to/ca.crt'
)
assert r.ping() == True
except redis.ConnectionError:
pytest.skip("TLS not configured")