fix: persist provisioned Redis ACL users
This commit is contained in:
parent
4f48a20670
commit
e1772917ea
@ -13,4 +13,4 @@
|
|||||||
|
|
||||||
SSH 隧道账号只接受由注册服务 CA 签发的短期证书,只允许转发到服务器 `127.0.0.1:3307`,并关闭终端、TTY、代理转发和密码认证。生产主机的 SSH 管理账号使用独立密钥,关闭密码登录。
|
SSH 隧道账号只接受由注册服务 CA 签发的短期证书,只允许转发到服务器 `127.0.0.1:3307`,并关闭终端、TTY、代理转发和密码认证。生产主机的 SSH 管理账号使用独立密钥,关闭密码登录。
|
||||||
|
|
||||||
Redis 原始端口不映射到宿主机。公网 `6380` 只接受 TLS,注册服务为每台设备创建独立 ACL 账号;停用安装会删除该账号。证书文件应归属 HAProxy 容器的 `99:99` 并保持 `0600`,续期后需重新生成 `/opt/cangku/shared/redis-tls.pem`、恢复该属主并重启 TLS 网关。
|
Redis 原始端口不映射到宿主机。公网 `6380` 只接受 TLS,注册服务为每台设备创建独立 ACL 账号;停用安装会删除该账号。ACL 保存在 Redis 数据卷的 `users.acl`,注册与撤销后立即执行 `ACL SAVE`,容器重启不会丢失设备账号。证书文件应归属 HAProxy 容器的 `99:99` 并保持 `0600`,续期后需重新生成 `/opt/cangku/shared/redis-tls.pem`、恢复该属主并重启 TLS 网关。
|
||||||
|
|||||||
@ -31,7 +31,7 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file:
|
env_file:
|
||||||
- /opt/cangku/shared/redis.env
|
- /opt/cangku/shared/redis.env
|
||||||
command: ["sh", "-c", "exec redis-server --appendonly yes --save 60 1000 --requirepass \"$$REDIS_PASSWORD\""]
|
command: ["sh", "-c", "if [ ! -s /data/users.acl ]; then printf 'user default on >%s ~* +@all\\n' \"$$REDIS_PASSWORD\" > /data/users.acl; fi; exec redis-server --appendonly yes --save 60 1000 --aclfile /data/users.acl"]
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/cangku/data/redis:/data
|
- /opt/cangku/data/redis:/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|||||||
@ -188,18 +188,22 @@ class Broker:
|
|||||||
def _create_redis_user(self, username, password):
|
def _create_redis_user(self, username, password):
|
||||||
if not re.fullmatch(r'cangku_[a-f0-9]{16}', username):
|
if not re.fullmatch(r'cangku_[a-f0-9]{16}', username):
|
||||||
raise ValueError('Refusing to create an unexpected Redis username')
|
raise ValueError('Refusing to create an unexpected Redis username')
|
||||||
self._redis_connection().execute_command(
|
client = self._redis_connection()
|
||||||
|
client.execute_command(
|
||||||
'ACL', 'SETUSER', username,
|
'ACL', 'SETUSER', username,
|
||||||
'reset', 'on', f'>{password}', '~*',
|
'reset', 'on', f'>{password}', '~*',
|
||||||
'+ping', '+get', '+set', '+setex', '+del', '+unlink', '+exists',
|
'+ping', '+get', '+set', '+setex', '+del', '+unlink', '+exists',
|
||||||
'+expire', '+ttl', '+scan', '+eval', '+quit',
|
'+expire', '+ttl', '+scan', '+eval', '+quit',
|
||||||
'+client|setname', '+client|setinfo',
|
'+client|setname', '+client|setinfo',
|
||||||
)
|
)
|
||||||
|
client.execute_command('ACL', 'SAVE')
|
||||||
|
|
||||||
def _drop_redis_user(self, username):
|
def _drop_redis_user(self, username):
|
||||||
if not username or not re.fullmatch(r'cangku_[a-f0-9]{16}', username):
|
if not username or not re.fullmatch(r'cangku_[a-f0-9]{16}', username):
|
||||||
return
|
return
|
||||||
self._redis_connection().execute_command('ACL', 'DELUSER', username)
|
client = self._redis_connection()
|
||||||
|
client.execute_command('ACL', 'DELUSER', username)
|
||||||
|
client.execute_command('ACL', 'SAVE')
|
||||||
|
|
||||||
def _create_application_admin(self, username, password, label):
|
def _create_application_admin(self, username, password, label):
|
||||||
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12)).decode()
|
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12)).decode()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user