-
Notifications
You must be signed in to change notification settings - Fork 81
fix(redis): decouple TLS from auth so on-prem can require a password #875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
fdbb393
089c0e0
f4010fb
738c85e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -513,7 +513,7 @@ data: | |
| listName: "launch-endpoint-autoscaling:${ENDPOINT_ID}" | ||
| listLength: "100" # something absurdly high so we don't scale past 1 pod | ||
| activationListLength: "0" | ||
| enableTLS: "{{ .Values.redis.enableTLS }}" | ||
| enableTLS: "{{ include "modelEngine.redisEnableTLS" . }}" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you double check whether this regresses AWS? Specifically The concern is that the scaler and the app connect to two different Redis instances. This trigger's The app connects to the cache using whatever scheme
Rendered with |
||
| unsafeSsl: "{{ .Values.redis.unsafeSsl }}" | ||
| databaseIndex: "${REDIS_DB_INDEX}" | ||
| {{- if .Values.redis.enableAuth }} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |
| from dataclasses import dataclass | ||
| from pathlib import Path | ||
| from typing import Optional, Sequence | ||
| from urllib.parse import quote | ||
|
|
||
| import yaml | ||
| from azure.identity import DefaultAzureCredential | ||
|
|
@@ -47,6 +48,24 @@ def get_model_cache_directory_name(model_name: str): | |
| return name | ||
|
|
||
|
|
||
| def _apply_redis_auth_token(url: str) -> str: | ||
| """Add REDIS_AUTH_TOKEN to a Redis URL that carries no credential of its own. | ||
|
|
||
| Keeps the password out of Helm values: the chart names the host and db | ||
| index, the app supplies the credential from its secret-backed env var. A | ||
| URL that already has userinfo is left alone so an explicit override wins. | ||
| """ | ||
| auth_token = os.getenv("REDIS_AUTH_TOKEN") | ||
| if not auth_token: | ||
| return url | ||
| scheme, sep, remainder = url.partition("://") | ||
| if not sep or "@" in remainder.split("/")[0]: | ||
| return url | ||
| # redis-py unquotes the userinfo, so percent-encoding here is what lets a | ||
| # password containing @, / or # survive URL parsing. | ||
| return f"{scheme}://:{quote(auth_token, safe='')}@{remainder}" | ||
|
|
||
|
|
||
| @dataclass | ||
| class HostedModelInferenceServiceConfig: | ||
| gateway_namespace: str | ||
|
|
@@ -104,18 +123,18 @@ def from_yaml(cls, yaml_path): | |
| def cache_redis_url(self) -> str: | ||
| # On-prem Redis support (explicit URL, no cloud provider dependency) | ||
| if self.cache_redis_onprem_url: | ||
| return self.cache_redis_onprem_url | ||
| return _apply_redis_auth_token(self.cache_redis_onprem_url) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you check if Injecting the credential into
|
||
|
|
||
| cloud_provider = infra_config().cloud_provider | ||
|
|
||
| # On-prem: support REDIS_HOST env var fallback | ||
| if cloud_provider == "onprem": | ||
| if self.cache_redis_aws_url: | ||
| logger.info("On-prem deployment using cache_redis_aws_url") | ||
| return self.cache_redis_aws_url | ||
| return _apply_redis_auth_token(self.cache_redis_aws_url) | ||
| redis_host = os.getenv("REDIS_HOST", "redis") | ||
| redis_port = getattr(infra_config(), "redis_port", 6379) | ||
| return f"redis://{redis_host}:{redis_port}/0" | ||
| return _apply_redis_auth_token(f"redis://{redis_host}:{redis_port}/0") | ||
|
|
||
| if cloud_provider == "gcp": | ||
| assert self.cache_redis_gcp_url, "cache_redis_gcp_url required for GCP" | ||
|
|
@@ -148,11 +167,13 @@ def cache_redis_url_expiration_timestamp(self) -> Optional[int]: | |
|
|
||
| @property | ||
| def cache_redis_host_port(self) -> str: | ||
| # redis://redis.url:6379/<db_index> | ||
| # redis://:password@redis.url:6379/<db_index> | ||
| # -> redis.url:6379 | ||
| if "rediss://" in self.cache_redis_url: | ||
| return self.cache_redis_url.split("rediss://")[1].split("@")[-1].split("/")[0] | ||
| return self.cache_redis_url.split("redis://")[1].split("/")[0] | ||
| # Credentials must be stripped for every scheme: this value is rendered | ||
| # into the KEDA scaler's `address` metadata, so a password left in here | ||
| # both breaks the address and leaks into the ScaledObject. | ||
| authority = self.cache_redis_url.split("://", 1)[-1] | ||
| return authority.split("@")[-1].split("/")[0] | ||
|
|
||
| @property | ||
| def cache_redis_db_index(self) -> int: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.