Skip to content

Honor INFRAHUB_CACHE_TLS_* in Prefect result storage block#9218

Merged
minitriga merged 1 commit into
stablefrom
fix/9217-prefect-redis-tls
Jun 2, 2026
Merged

Honor INFRAHUB_CACHE_TLS_* in Prefect result storage block#9218
minitriga merged 1 commit into
stablefrom
fix/9217-prefect-redis-tls

Conversation

@PhillSimonds

@PhillSimonds PhillSimonds commented May 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Background flows hung in RUNNING against TLS-only Redis because setup_blocks() built the Prefect RedisStorageContainer via from_host(), whose internal client path constructs redis.Redis(...) with no ssl= argument. INFRAHUB_CACHE_TLS_ENABLED / INFRAHUB_CACHE_TLS_INSECURE / INFRAHUB_CACHE_TLS_CA_FILE were silently ignored for this one client, while lock.py and the cache adapter honored them.
  • setup_blocks() now always builds a connection_string URL from CacheSettings. Scheme switches between redis:// and rediss:// based on tls_enabled; tls_insecure encodes as ssl_cert_reqs=none&ssl_check_hostname=False; tls_ca_file encodes as ssl_ca_certs=<path>. redis.Redis.from_url parses these query params and applies them to the underlying SSLConnection, so all three TLS knobs become deterministic across every Redis client in the codebase.
  • Single code path — no if/else between two constructors, no Prefect upstream change, no follow-on "doesn't apply here" warning needed.

Behavior change

Previously, setting INFRAHUB_CACHE_USERNAME without INFRAHUB_CACHE_PASSWORD produced a Prefect block-construction error. The new helper raises ValueError with an explicit message before reaching Prefect — same outcome (startup fails), clearer diagnostic.

Test plan

  • uv run pytest backend/tests/unit/workflows/ — 276 passed (18 new tests in test_initialization.py)
  • uv run mypy backend/infrahub/workflows/initialization.py — clean
  • uv run ruff check backend/infrahub/workflows/initialization.py backend/tests/unit/workflows/test_initialization.py — clean
  • CI: backend unit + integration suites
  • Customer-side verification against external TLS-only Redis

New test coverage

backend/tests/unit/workflows/test_initialization.py covers:

  1. URL composition (11 parametrized cases): plain defaults, custom port/db, user+password, password-only, special-character escaping, TLS defaults, TLS+credentials, tls_insecure, tls_ca_file, both TLS flags combined, and the negative case that tls_insecure / tls_ca_file are ignored when tls_enabled=False.
  2. Username-without-password validation: raises ValueError with explicit message.
  3. Round-trip through redis.ConnectionPool.from_url (6 parametrized cases): proves the URL we build resolves to the expected connection_class (Connection vs SSLConnection) and propagates host / port / db / username / password / ssl_cert_reqs / ssl_check_hostname / ssl_ca_certs correctly. This guards against silent regressions in redis-py's URL parser.

Closes #9217

🤖 Generated with Claude Code


Summary by cubic

Fixes Prefect result storage against TLS-only Redis by honoring INFRAHUB_CACHE_TLS_* settings via a redis:///rediss:// connection string. Unifies TLS behavior across all Redis clients and prevents background flows from hanging.

  • Bug Fixes
    • Build the connection string from CacheSettings; use rediss:// when INFRAHUB_CACHE_TLS_ENABLED is true.
    • Encode TLS options: INFRAHUB_CACHE_TLS_INSECUREssl_cert_reqs=none&ssl_check_hostname=False; INFRAHUB_CACHE_TLS_CA_FILEssl_ca_certs=<path>. Parsed by redis.Redis.from_url and applied to SSLConnection.
    • Replace RedisStorageContainer.from_host with RedisStorageContainer(connection_string=...) for a single, consistent path.
    • Clearer startup error: setting INFRAHUB_CACHE_USERNAME without INFRAHUB_CACHE_PASSWORD now raises a ValueError with an explicit message.

Written for commit 2ae4c39. Summary will update on new commits.

Background flows hung in RUNNING against TLS-only Redis because setup_blocks()
built the Prefect RedisStorageContainer via from_host(), whose internal client
path constructs redis.Redis(...) with no ssl= argument. INFRAHUB_CACHE_TLS_*
settings were silently ignored for this one client even though lock.py and the
cache adapter honored them.

Always construct a connection_string URL from cache settings. Scheme selects
rediss:// when tls_enabled is set; ssl_cert_reqs / ssl_check_hostname /
ssl_ca_certs propagate as query params through redis.Redis.from_url onto the
underlying SSLConnection. Single deterministic code path; brings the block in
parity with the rest of the codebase's Redis clients.

Closes #9217

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@PhillSimonds PhillSimonds requested a review from a team as a code owner May 11, 2026 17:21
@github-actions github-actions Bot added the group/backend Issue related to the backend (API Server, Git Agent) label May 11, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Confidence score: 3/5

  • There is a concrete connectivity risk in backend/infrahub/workflows/initialization.py: composing the Redis URL without IPv6 brackets can produce an invalid connection string for valid IPv6 hosts.
  • Given the issue is medium severity (5/10) but high confidence (9/10) and can affect cache initialization behavior in IPv6 environments, this introduces some user-impacting regression risk.
  • Pay close attention to backend/infrahub/workflows/initialization.py - ensure IPv6 cache hosts are wrapped in [] when building the Redis URL.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="backend/infrahub/workflows/initialization.py">

<violation number="1" location="backend/infrahub/workflows/initialization.py:53">
P2: Wrap IPv6 addresses in `[]` before composing the Redis URL, otherwise valid IPv6 cache hosts generate an invalid connection string.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.

query["ssl_ca_certs"] = cache.tls_ca_file

qs = f"?{urlencode(query)}" if query else ""
return f"{scheme}://{userinfo}{cache.address}:{cache.service_port}/{cache.database}{qs}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Wrap IPv6 addresses in [] before composing the Redis URL, otherwise valid IPv6 cache hosts generate an invalid connection string.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/infrahub/workflows/initialization.py, line 53:

<comment>Wrap IPv6 addresses in `[]` before composing the Redis URL, otherwise valid IPv6 cache hosts generate an invalid connection string.</comment>

<file context>
@@ -17,6 +21,38 @@
+            query["ssl_ca_certs"] = cache.tls_ca_file
+
+    qs = f"?{urlencode(query)}" if query else ""
+    return f"{scheme}://{userinfo}{cache.address}:{cache.service_port}/{cache.database}{qs}"
+
+
</file context>
Suggested change
return f"{scheme}://{userinfo}{cache.address}:{cache.service_port}/{cache.database}{qs}"
host = cache.address
if ":" in host and not host.startswith("["):
host = f"[{host}]"
return f"{scheme}://{userinfo}{host}:{cache.service_port}/{cache.database}{qs}"

@codspeed-hq

codspeed-hq Bot commented May 11, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 12 untouched benchmarks


Comparing fix/9217-prefect-redis-tls (2ae4c39) with stable (8689f7d)

Open in CodSpeed

@github-actions

Copy link
Copy Markdown
Contributor

This PR has been inactive for 2 weeks and has been marked as stale.

If you're still working on this, please:

  • Push new commits, or
  • Leave a comment to indicate this PR is still active

The stale label will be removed automatically when there's new activity.

@github-actions github-actions Bot added the stale Marks stale issues and pull requests label May 26, 2026
same INFRAHUB_CACHE_TLS_* settings directly.
"""
if cache.username and not cache.password:
raise ValueError("INFRAHUB_CACHE_USERNAME is set but INFRAHUB_CACHE_PASSWORD is not. Both are required.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@minitriga minitriga merged commit 2ebf2fd into stable Jun 2, 2026
65 checks passed
@minitriga minitriga deleted the fix/9217-prefect-redis-tls branch June 2, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

group/backend Issue related to the backend (API Server, Git Agent) stale Marks stale issues and pull requests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Background flows hang against TLS-only Redis (INFRAHUB_CACHE_TLS_* not honored by Prefect result-storage block)

3 participants