fix(security): keep redis, flowise, discourse and nextcloud LDAP secrets off argv

Four credentials still reached a process command line that host `ps`
shows, in forms the exec lints do not catch:

- svc-db-redis passed the admin password as `redis-cli -a` and the
  per-consumer ACL password as an `ACL SETUSER` argument. `REDIS_CLI`
  now authenticates through `REDISCLI_AUTH`, and the ACL password is
  read from stdin with `redis-cli -x`.
- web-app-flowise rendered every MCP server token into
  `-e FLOWISE_MCP_DESIRED=<json>`; the value now comes from the task's
  `environment:`, like `FLOWISE_API_KEY` in the same task.
- web-app-discourse rendered the LiteLLM API key into the `rails r`
  code argument; the script now goes to `rails r -` on stdin.
- web-app-nextcloud set the LDAP agent password through the occ
  wrapper's argv; it now reaches occ through `-e NC_LDAP_AGENT_PASSWORD`
  plus `environment:`, and the task carries the stack-host gate the
  wrapper used to hide from the lint.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5.5 committed 2026-10-25 08:04:16 +01:00
1 parent 485b52ca5a
commit 54dde281a0
5 files changed
+14 -7

No files matched your search

+1 -2
View File
@@ -49,9 +49,8 @@
container exec
-e REDIS_ACL_PASSWORD
{{ REDIS_CONTAINER_ADDRESS }} sh -lc
'{{ REDIS_CLI }} ACL SETUSER {{ redis_acl_username }}
'printf "%s" ">$REDIS_ACL_PASSWORD" | {{ REDIS_CLI }} -x ACL SETUSER {{ redis_acl_username }}
on resetkeys resetchannels
">$REDIS_ACL_PASSWORD"
allkeys allchannels
+@all'
environment:
+1 -1
View File
@@ -11,4 +11,4 @@ REDIS_EXPOSE_LOCAL: true
REDIS_RETRIES: 5
REDIS_DELAY: 5
REDIS_EXEC_SHELL: "container exec {{ REDIS_CONTAINER_ADDRESS }} sh -lc"
REDIS_CLI: 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning'
REDIS_CLI: 'REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli'
@@ -7,10 +7,12 @@
argv:
- container
- exec
- -i
- "{{ DISCOURSE_CONTAINER }}" # nocheck: container-exec-resolver the launcher names the container itself, so the bare name resolves in both modes
- rails
- r
- "{{ lookup('template', 'ai_gateway/register.rb.j2') }}"
- "-"
stdin: "{{ lookup('template', 'ai_gateway/register.rb.j2') }}"
changed_when: false
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
+2 -1
View File
@@ -50,7 +50,7 @@
- -e
- "FLOWISE_WORKSPACE={{ (flowise_mcp_identity.stdout_lines | last | from_json).workspace_id }}"
- -e
- "FLOWISE_MCP_DESIRED={{ FLOWISE_MCP_DESIRED | to_json }}"
- FLOWISE_MCP_DESIRED
- -e
- "FLOWISE_MCP_TRANSPORT={{ FLOWISE_MCP_TRANSPORT }}"
- -e
@@ -61,6 +61,7 @@
stdin: "{{ lookup('file', 'python/reconcile/mcp_servers.py') }}"
environment:
FLOWISE_API_KEY: "{{ (flowise_mcp_identity.stdout_lines | last | from_json).api_key }}"
FLOWISE_MCP_DESIRED: "{{ FLOWISE_MCP_DESIRED | to_json }}"
register: flowise_mcp_registry
retries: "{{ 30 if MCP_RECONCILE_STRICT | bool else 0 }}"
delay: 10
@@ -46,8 +46,13 @@
create_stdout='{{ nextcloud_ldap_config_create.stdout | default('') }}'
create_stderr='{{ nextcloud_ldap_config_create.stderr | default('') }}'
- name: 🔧 Set Nextcloud LDAP bind password
shell: >
{{ NEXTCLOUD_DOCKER_EXEC_OCC }} ldap:set-config {{ nextcloud_ldap_config_id }} ldapAgentPassword '{{ LDAP.BIND_CREDENTIAL }}'
shell: >- # nocheck: container-exec-resolver NEXTCLOUD_LOCAL_CID resolved at delegate_to runtime; container_address would return a manager-only subshell
container exec -u {{ NEXTCLOUD_DOCKER_USER }} -e NC_LDAP_AGENT_PASSWORD {{ NEXTCLOUD_LOCAL_CID | quote }}
sh -c 'exec "$1" ldap:set-config "$2" ldapAgentPassword "$NC_LDAP_AGENT_PASSWORD"'
_ {{ NEXTCLOUD_INTERNAL_OCC_COMMAND | quote }} {{ nextcloud_ldap_config_id | quote }}
environment:
NC_LDAP_AGENT_PASSWORD: "{{ LDAP.BIND_CREDENTIAL }}"
when: IS_STACK_HOST | bool
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: 🟢 Activate Nextcloud LDAP configuration
shell: >