Repository navigation
security(redis): every Ansible-rendered client pairs its Redis password with a username; deploy scripts drop the hardcoded password (#16678, #16686) - #16700
Conversation
|
Warning Review limit reachedNext included review available in 12 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (11)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ SSOT Configuration Compliance: Passing🎉 No new hardcoded values of either class — Known backlog in |
…not line numbers (#16686)
|
Delta review at 3c002f8 (from 55fce7c): approve. Commit 15d0c69 (pipefail-survival + Ansible quoting):
Commit 3c002f8 (guard-citation fix for #15877):
CI at head |
…e now always travels with the password (#16678)
|
Delta review at 59a0f92 (from 3c002f8): approve. Verified the regex fix and the new assertions directly against the current template (`autobot-slm-backend/ansible/roles/ai-stack/templates/ai-stack.env.j2`, lines 37-42): ``` Confirms #16678 left exactly one `{% endif %}` in this block (the old test's two-`endif` regex would indeed match `None`) — the new single-`{% endif %}` regex is correct. The three new assertions match the template's actual Jinja logic exactly: `ai_redis_username="svc"` → `default('', true)` passes it through unchanged (non-empty, non-undefined) → `REDIS_USERNAME=svc`; `ai_redis_username=""` → `default('', true)` treats the empty string as needing the default (the `true` flag), yielding `''`, then `'' or 'default'` → `REDIS_USERNAME=default`; no password → the whole block doesn't render. Also an improvement over the old test: using `"svc"` instead of `"default"` for the with-username case actually distinguishes "the template passes a real username through" from "the template always falls back to default" — the old test's use of `"default"` for both configured and fallback cases couldn't tell those apart. CI: no FAILURE/ERROR/TIMED_OUT at this head; rest still in progress (expected, this is CI's first run of the fixed test per your note). |
…ong the glob-declared reads (#16686)
|
Root cause of the python-suite shard 8 red at
The fix registers it under the record's The pre-push hook didn't catch this because the record test isn't selected by this PR's changeset. That's the selection gap tracked in #16711. |
|
Re-stamped at 2073807 (from 59a0f92): approve. Verified the delta: one line, adding `repo_tests/redis_password_literal_guard_test.py` to the `".sh"` entry in `GLOB_DECLARED_UNCOVERED` — correctly alphabetically placed between `one_git_enumeration_15926_test.py` and `shell_lib_test.py`. Confirmed it belongs there, not just guard-silencing: the guard's own scope does `scripts = tracked_paths(REPO_ROOT, ".sh")`, a genuine root-relative `*.sh` sweep matching this key's stated reason exactly ("the matching files live outside the python filter's trees"). No code change, no other lines touched. CI: no FAILURE/ERROR/TIMED_OUT checks. Mergeable. |
Closes #16678, closes #16686
Refs #16657, #13568, #16627, #16628
One Redis-credentials PR, batched per a7: the remaining clients' username pairing (#16678), the deploy scripts' hardcoded password (#16686), and #16657 AC1's endpoint-calling test.
Thinking Path
AUTH <password>while thedefaultuser isnopass. It acceptsAUTH default <password>, which also works against a server enforcing that password. security(redis): backend.env renders a password-only AUTOBOT_REDIS_URL when a password is set without a username #16668 fixed this forbackend.env.j2. The same defect was in the other Ansible-rendered clients: they sent--userorREDIS_USERNAMEonly when a username was configured, but always sent the password. P1b's own adoption path is safe, because the SLM generates the username beside the password. An operator who sets only a password is not.deploy-native.shanddeploy-hybrid.shwroteAUTOBOT_REDIS_PASSWORD=autobot123into their generated env files, a literal that dates from 2026-02. They are still referenced:NATIVE_DEPLOYMENT_READY.mdand two security-validation utilities point at them. So they're fixed, not retired, because retiring needs proof they're unused.ast. Its closure audit asked for a test that actually calls the endpoint.What Changed
roles/ai-stack/templates/ai-stack.env.j2:REDIS_USERNAMEis always rendered alongsideREDIS_PASSWORD, asai_redis_usernameor elsedefault. With no password, nothing is rendered.playbooks/deploy-native-services.ymlandplaybooks/deploy-hybrid-docker.yml:redis-clichecks and the container healthcheck always pass--user <configured or default>with-a;REDIS_USERNAMEisdefaultalongside a password, and empty when there is none, so the no-password output is unchanged.requirepasslines are untouched.ansible/deploy-native.shandansible/deploy-hybrid.sh:/etc/autobot/slm-secrets.env. That is the file_shared/tasks/read_redis_password.ymlreads, and the path mirrors that task.AUTOBOT_REDIS_USERNAMEwith it,defaultwhen a password exists.repo_tests/redis_password_literal_guard_test.py(new): fails if any tracked*.sh, heredoc bodies included, assigns a literal toAUTOBOT_REDIS_PASSWORD. The measured population is 2 onmain(deploy-hybrid.sh:151,deploy-native.sh:175) and 0 after this PR. It has a known-positive test covering the security(redis): deploy-hybrid.sh and deploy-native.sh write a hardcoded Redis password into the generated env file #16686 shape, and contrast cases for expansions, empty values and comments. Its blind spots are declared in the docstring.tests/test_redis_username_plumbing_16626.py: the deploy-playbook test pinned the defect ("no--userwithout a username"). It now assertsdefaultis sent, and that a configured name is honoured. New tests cover the units'REDIS_USERNAME(defaultwith a password, empty without) and the ai-stack env (password alone, custom username, no password).autobot-backend/tests/test_npu_bootstrap_credential_16657.py:test_calling_the_bootstrap_endpoint_returns_no_redis_passwordPOSTs to/npu/workers/bootstrapthrough the real router, with a sample password set on the config, and asserts the response has nopasswordkey and never contains the sample.changelog/unreleased/16678-redis-client-usernames.md.Acceptance criteria
defaultunless configuredredis-cli, the hybrid healthcheck andredis-cli, and 4 unitREDIS_USERNAMElines, as described abovetest_deploy_playbook_redis_cli_sends_the_user_first,test_deploy_playbook_units_get_default_with_a_password_and_nothing_without,test_ai_stack_env_sends_a_username_whenever_it_sends_a_passworddefaultAUTOBOT_REDIS_USERNAME=${redis_username}in both scriptsAUTOBOT_REDIS_PASSWORDin any tracked shell scriptrepo_tests/redis_password_literal_guard_test.pytest_calling_the_bootstrap_endpoint_returns_no_redis_password. AC2 (an authenticated channel that survives a worker restart) and AC3 (a guard for credential fields under exempt paths) stay open, so this PR only references #16657.Verification
Pre-push hook at
55fce7cef:all relevant tests pass. My output filter didn't capture the hook's file list, so I can't show which files ran. CI's python-suite is the first run I can cite for the new endpoint test. It is also the first test in the repo to import theapi.npu_workersrouter.Lint: ruff and black are clean on the three Python test files. Both playbooks parse as YAML, and both shell scripts pass
bash -n. That is parse-only; no repo code was run.CI on
3c002f8a3: red onpython-suiteshard 12/12 again, and the cause was mine. P1b'stest_redis_password_provisioned_16627.py::test_the_ai_stack_env_renders_the_username_only_with_the_passwordsliced the ai-stack Redis block with a regex that expects the old nested{% endif %}. My security(redis): the ai-stack env and deploy playbooks send a Redis password without a username #16678 template change removed the innerif, so the slice found nothing, and the test also pinned the old username-only-if-configured rule. It is renamedtest_the_ai_stack_env_renders_a_username_whenever_it_renders_the_password: it slices up to the block's first{% endif %}and adds the password-alone case, which rendersdefault. The pre-push hook didn't catch it, because it selects tests by the files a change touches, and this test file wasn't among them.Code review of
55fce7cef: REQUEST CHANGES; ledgered as blocked. Resolved in the follow-up commits:set -euo pipefail. A missing key inslm-secrets.envmakesgrepexit 1 and aborts the deploy.|| trueadded to all fourgrep | headreads, the same guardread_redis_password.ymluses.main:-a {{ password }} pingwith an empty password renders as-a ping, which swallowsping, so the check silently becomes a no-op--userand-ago through Ansible'squotefilter, so an empty password stays an explicit''argument andpingstays the command. The test's plain Jinja environment registersshlex.quoteasquoteto render them.config.redis.password, so the sample is a forward guard.The review also checked:
AUTH default ''against a nopass server is safe;CI on
55fce7cef: red onpython-suiteshard 12/12. The cause was mine: my guard's docstring citedfile:linereferences, whichrepo_tests/comment_line_number_citations_test.py(tech-debt(guards): audit comments that assert a mechanism exists elsewhere — three were false today, one preceded an outage #15877) rejects. It now names the scripts'update_backend_configheredoc instead. My other open branches were checked for the same pattern and have none.Model Used
Claude Opus 5 (
claude-opus-5).🤖 Generated with Claude Code