[Security][Remote Connector]: Add env var auth config for RESP#2949
[Security][Remote Connector]: Add env var auth config for RESP#2949sammshen merged 2 commits intoLMCache:devfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the ability to configure Redis/RESP connection details and credentials via environment variables, ensuring sensitive information is kept out of configuration files and logs. Documentation and examples have been updated to promote this practice. Feedback was provided regarding the logic used for environment variable overrides; specifically, using the "or" operator prevents overriding a non-empty configuration value with an empty string. It is recommended to use "os.environ.get(key, default)" to correctly handle cases where an empty string is an intended value.
| host = os.environ.get("LMCACHE_RESP_HOST", "") or config.host | ||
| port_str = os.environ.get("LMCACHE_RESP_PORT", "") | ||
| port = int(port_str) if port_str else config.port | ||
| username = os.environ.get("LMCACHE_RESP_USERNAME", "") or config.username | ||
| password = os.environ.get("LMCACHE_RESP_PASSWORD", "") or config.password |
There was a problem hiding this comment.
The use of the or operator for environment variable overrides prevents setting a value to an empty string if a default exists in the configuration. This is particularly problematic for username and password, where an empty string is a valid value indicating no authentication. Using os.environ.get(key, default) is a more robust pattern for these overrides.
| host = os.environ.get("LMCACHE_RESP_HOST", "") or config.host | |
| port_str = os.environ.get("LMCACHE_RESP_PORT", "") | |
| port = int(port_str) if port_str else config.port | |
| username = os.environ.get("LMCACHE_RESP_USERNAME", "") or config.username | |
| password = os.environ.get("LMCACHE_RESP_PASSWORD", "") or config.password | |
| host = os.environ.get("LMCACHE_RESP_HOST", config.host) | |
| port_env = os.environ.get("LMCACHE_RESP_PORT") | |
| port = int(port_env) if port_env else config.port | |
| username = os.environ.get("LMCACHE_RESP_USERNAME", config.username) | |
| password = os.environ.get("LMCACHE_RESP_PASSWORD", config.password) |
| username = os.environ.get("LMCACHE_RESP_USERNAME", "") or str( | ||
| extra_config.get("username", "") | ||
| ) | ||
| password = os.environ.get("LMCACHE_RESP_PASSWORD", "") or str( | ||
| extra_config.get("password", "") | ||
| ) |
There was a problem hiding this comment.
Similar to the L2 adapter, using or for environment variable overrides prevents overriding a non-empty configuration value with an empty string (e.g., to disable authentication). It is better to use os.environ.get(key, default) to correctly handle cases where the environment variable is explicitly set to an empty string.
username = os.environ.get("LMCACHE_RESP_USERNAME", str(extra_config.get("username", "")))
password = os.environ.get("LMCACHE_RESP_PASSWORD", str(extra_config.get("password", "")))| host = os.environ.get("LMCACHE_RESP_HOST", "") or parsed_url.host | ||
| port_str = os.environ.get("LMCACHE_RESP_PORT", "") | ||
| port = int(port_str) if port_str else parsed_url.port |
There was a problem hiding this comment.
Using os.environ.get(key, default) is cleaner and more consistent for handling environment variable overrides compared to the or pattern, which can have unexpected behavior with empty strings.
| host = os.environ.get("LMCACHE_RESP_HOST", "") or parsed_url.host | |
| port_str = os.environ.get("LMCACHE_RESP_PORT", "") | |
| port = int(port_str) if port_str else parsed_url.port | |
| host = os.environ.get("LMCACHE_RESP_HOST", parsed_url.host) | |
| port_env = os.environ.get("LMCACHE_RESP_PORT") | |
| port = int(port_env) if port_env else parsed_url.port |
| * - Variable | ||
| - Description | ||
| * - ``LMCACHE_RESP_USERNAME`` | ||
| - Redis ACL username. Overrides ``username`` in config/JSON. |
There was a problem hiding this comment.
Typically, env var are set for long term usage, like a default value. I would recommend have the command line args override env var instead of the other way around.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 22a083a. Configure here.
| # which serve as defaults. This keeps secrets out of logged | ||
| # config while allowing explicit CLI overrides. | ||
| host = config.host or os.environ.get("LMCACHE_RESP_HOST", "") | ||
| port = config.port if config.port else int(os.environ.get("LMCACHE_RESP_PORT", "0")) |
There was a problem hiding this comment.
Env var host/port fallback unreachable in MP mode
High Severity
The env var fallback for LMCACHE_RESP_HOST and LMCACHE_RESP_PORT in _create_resp_l2_adapter is dead code. from_dict() validates that host is a non-empty string and port is a positive integer, raising ValueError before the adapter factory ever runs. A user who omits host/port from the JSON and relies solely on env vars will get a crash at config parsing time, not a graceful fallback. The documentation, help() text, and tests all advertise this feature, but it cannot work.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 22a083a. Configure here.
| else int(os.environ.get("LMCACHE_RESP_PORT", "0")) | ||
| ) | ||
| username = config.username or os.environ.get("LMCACHE_RESP_USERNAME", "") | ||
| password = config.password or os.environ.get("LMCACHE_RESP_PASSWORD", "") |
There was a problem hiding this comment.
Tests duplicate logic instead of exercising production code
Medium Severity
Every test in this file copy-pastes the env var resolution logic inline (e.g. config.host or os.environ.get(...)) instead of calling _create_resp_l2_adapter or RESPConnectorAdapter.create_connector. The tests verify their own inlined logic, not the production code. They will always pass even if the real adapters break — and in fact they mask the from_dict validation bug that makes host/port env var fallback unreachable in MP mode.
Additional Locations (1)
Triggered by project rule: LMCache Code Review Style Guide
Reviewed by Cursor Bugbot for commit 22a083a. Configure here.
| parsed_url.port | ||
| if parsed_url.port | ||
| else int(os.environ.get("LMCACHE_RESP_PORT", "0")) | ||
| ) |
There was a problem hiding this comment.
Env var host/port fallback unreachable in non-MP mode
High Severity
The env var fallback for LMCACHE_RESP_HOST and LMCACHE_RESP_PORT at lines 57–62 is dead code in non-MP mode. The parse_remote_url function (called just above on line 54) contains assert host is not None and assert port is not None, which will crash with an AssertionError for any URL missing a host or port — before the fallback logic ever runs. A user who omits host/port from remote_url expecting the env vars to fill them in will get an assertion crash instead.
Reviewed by Cursor Bugbot for commit 22a083a. Configure here.
Support LMCACHE_RESP_USERNAME, LMCACHE_RESP_PASSWORD, LMCACHE_RESP_HOST, and LMCACHE_RESP_PORT environment variables in both MP and non-MP modes. Env vars are read inside the adapter at creation time so credentials are never stored in the config object or printed in startup logs. Signed-off-by: Samuel Shen <slshen@tensormesh.ai>
Change precedence so config/CLI args override env vars (env vars serve as defaults). Add unit tests for the precedence logic in both MP and non-MP modes. Signed-off-by: Samuel Shen <slshen@tensormesh.ai>
22a083a to
a044120
Compare


Support LMCACHE_RESP_USERNAME, LMCACHE_RESP_PASSWORD, LMCACHE_RESP_HOST, and LMCACHE_RESP_PORT environment variables in both MP and non-MP modes. Env vars are read inside the adapter at creation time so credentials are never stored in the config object or printed in startup logs.
What this PR does / why we need it:
Special notes for your reviewers:
If applicable:
Note
Medium Risk
Touches connection/auth configuration for Redis/Valkey in both MP and non-MP code paths; precedence and fallback logic changes could cause misconfiguration or unexpected connection targets if env vars are set incorrectly.
Overview
Adds environment-variable defaults for RESP credentials and endpoint (
LMCACHE_RESP_USERNAME,LMCACHE_RESP_PASSWORD,LMCACHE_RESP_HOST,LMCACHE_RESP_PORT) in both MP mode (resp_l2_adapter) and non-MP mode (RESPConnectorAdapter), with config/URL values taking precedence to keep secrets out of logged configs.Updates RESP documentation and example config to recommend env vars for auth, and adjusts the non-MP sample URL scheme to
resp://. Adds unit tests covering precedence (config > env > default) for host/port and credentials.Reviewed by Cursor Bugbot for commit a044120. Bugbot is set up for automated code reviews on this repo. Configure here.