Skip to content

Refs #39303 - Narrow redhat_cdn_host? to actual CDN hostnames#11766

Merged
jeremylenz merged 1 commit into
Katello:masterfrom
vsedmik:fix-39303-redhat-cdn-host-check
May 28, 2026
Merged

Refs #39303 - Narrow redhat_cdn_host? to actual CDN hostnames#11766
jeremylenz merged 1 commit into
Katello:masterfrom
vsedmik:fix-39303-redhat-cdn-host-check

Conversation

@vsedmik
Copy link
Copy Markdown
Contributor

@vsedmik vsedmik commented May 28, 2026

Problem

The *.redhat.com check in redhat_cdn_host? is too broad — it matches any host in the redhat.com domain, including Satellite instances hosted in Red Hat infrastructure. This caused subscription client certificates to be injected when enabling repos via a custom CDN pointing at such a host, which the server rejected with tlsv1 alert unknown ca.

Solution

Narrow the check to cdn.redhat.com and cdn-{region}.redhat.com (e.g. cdn-eu.redhat.com, cdn-us.redhat.com) using a constant regex REDHAT_CDN_HOST_PATTERN. The three tests added by #11732 are unaffected — all use cdn-eu.redhat.com which still matches.

Testing

Added unit tests for redhat_cdn_host? covering:

  • Known Red Hat CDN hostnames (cdn.redhat.com, cdn-eu.redhat.com, cdn-us.redhat.com) → match
  • Generic *.redhat.com hosts → no match
  • Non-redhat.com hosts → no match
  • Malformed URL → no match (returns false)

Existing tests in cdn_test.rb and yum_test.rb added by #11732 pass unchanged.

Robottelo test that hit this issue should pass with this fix:

pytest tests/foreman/cli/test_satellitesync.py -k test_positive_custom_cdn_with_credential

Summary by CodeRabbit

  • Bug Fixes

    • Improved Red Hat CDN hostname detection to more reliably recognize official CDN hostnames (including optional suffix variants), reducing false negatives/positives during validation.
  • Tests

    • Added unit tests that verify detection against multiple matching and non-matching hostnames and invalid URL inputs to guard against regressions.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2112452a-72a1-4552-9b01-dc3bbad852dd

📥 Commits

Reviewing files that changed from the base of the PR and between 1e4e65d and cfe13fb.

📒 Files selected for processing (2)
  • app/models/katello/cdn_configuration.rb
  • test/models/cdn_configuration_test.rb
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/models/cdn_configuration_test.rb
  • app/models/katello/cdn_configuration.rb

📝 Walkthrough

Walkthrough

This PR adds a reusable REDHAT_CDN_HOST_PATTERN regex and updates Katello::CdnConfiguration#redhat_cdn_host? to match the parsed URL host against that pattern. A unit test exercises positive Red Hat CDN hostnames, non-matching variants, and invalid URL input.

Changes

Red Hat CDN Host Pattern Validation

Layer / File(s) Summary
Red Hat CDN host pattern validation
app/models/katello/cdn_configuration.rb, test/models/cdn_configuration_test.rb
Adds REDHAT_CDN_HOST_PATTERN and changes redhat_cdn_host? to use URI.parse(url).host with regex matching; test test_redhat_cdn_host covers matching hosts, similar non-matching domains, a different CDN domain, and invalid URL strings.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • Katello/katello#11732: Both PRs directly change and rely on the Katello::CdnConfiguration#redhat_cdn_host? logic and its behavior for CDN host validation and handling.

Suggested reviewers

  • ianballou
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: narrowing the redhat_cdn_host? predicate to match only actual CDN hostnames instead of all *.redhat.com domains.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/models/katello/cdn_configuration.rb`:
- Around line 46-48: The redhat_cdn_host? method currently calls URI.parse(url)
without guarding against nil/blank and only rescues URI::InvalidURIError; update
redhat_cdn_host? to first return false for nil/blank url (e.g., return false if
url.blank? or url.nil?) before calling URI.parse(url). Keep the existing rescue
for URI::InvalidURIError and ensure the method uses REDHAT_CDN_HOST_PATTERN on
the parsed host as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06c52de2-87b0-4647-94b2-cf2b6b5a19eb

📥 Commits

Reviewing files that changed from the base of the PR and between a46d7af and a230d90.

📒 Files selected for processing (2)
  • app/models/katello/cdn_configuration.rb
  • test/models/cdn_configuration_test.rb

Comment on lines +46 to 48
URI.parse(url).host&.match?(REDHAT_CDN_HOST_PATTERN)
rescue URI::InvalidURIError
false
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Ruby's stdlib URI module, what exception does URI.parse raise for nil input, and what exception does it raise for malformed URL strings?

💡 Result:

For nil input: URI.parse(nil) raises NoMethodError (e.g., “undefined method `[]' for nil:NilClass”), instead of the expected URI::InvalidURIError in some cases [1]. For malformed URL strings: URI.parse("...") raises URI::InvalidURIError when the URI string does not match the parser’s expected syntax (e.g., URI::RFC2396_Parser.parse / URI.parse shown in docs to raise URI::InvalidURIError) [2][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the method definition around the reported lines
FILE="app/models/katello/cdn_configuration.rb"
if [ -f "$FILE" ]; then
  echo "== $FILE =="
  nl -ba "$FILE" | sed -n '1,140p' | sed -n '35,90p'
else
  echo "File not found: $FILE"
fi

# Find references to redhat_cdn_host? and to any method/attribute named url in this context
rg -n "redhat_cdn_host\?" -S .
rg -n "cdn_configuration\.rb" -S .
rg -n "URI\.parse\(url\)" -S .

# Find where `url` is coming from in redhat_cdn_host? (could be an attribute, method, or local)
# Print the whole method if found
rg -n "def redhat_cdn_host\?" -S app/models/katello/cdn_configuration.rb

Repository: Katello/katello

Length of output: 166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="app/models/katello/cdn_configuration.rb"
echo "== $FILE =="
if [ -f "$FILE" ]; then
  # Print lines 35-90 with line numbers using awk (no nl available)
  awk 'NR>=35 && NR<=90 {printf "%6d:%s\n", NR, $0}' "$FILE"
else
  echo "File not found: $FILE"
fi

echo
echo "== Search: redhat_cdn_host? =="
rg -n "def redhat_cdn_host\?" "$FILE" || true
rg -n "redhat_cdn_host\?" -S app/models/katello || true

echo
echo "== Search: where URI.parse(url) occurs =="
rg -n "URI\.parse\(url\)" -S app/models/katello/cdn_configuration.rb || true
rg -n "URI\.parse\(" -S app/models/katello/cdn_configuration.rb || true

echo
echo "== Search: possible `url` sources in this file =="
rg -n "\burl\b" -S app/models/katello/cdn_configuration.rb || true

Repository: Katello/katello

Length of output: 2395


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="app/models/katello/cdn_configuration.rb"
awk 'NR>=1 && NR<=90 {printf "%6d:%s\n", NR, $0}' "$FILE"

echo
echo "== Call sites for redhat_cdn_host? =="
rg -n "redhat_cdn_host\?" -S . || true

Repository: Katello/katello

Length of output: 4180


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect call sites with context
echo "== app/services/katello/pulp3/repository.rb around 500-580 =="
awk 'NR>=500 && NR<=580 {printf "%6d:%s\n", NR, $0}' app/services/katello/pulp3/repository.rb

echo
echo "== app/lib/katello/resources/cdn.rb around 40-95 =="
awk 'NR>=40 && NR<=110 {printf "%6d:%s\n", NR, $0}' app/lib/katello/resources/cdn.rb

echo
echo "== test/models/cdn_configuration_test.rb around 1-90 =="
awk 'NR>=1 && NR<=110 {printf "%6d:%s\n", NR, $0}' test/models/cdn_configuration_test.rb

Repository: Katello/katello

Length of output: 11553


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== app/services/katello/pulp3/repository.rb around 500-580 =="
awk 'NR>=500 && NR<=580 {printf "%6d:%s\n", NR, $0}' app/services/katello/pulp3/repository.rb

echo
echo "== app/lib/katello/resources/cdn.rb around 40-110 =="
awk 'NR>=40 && NR<=110 {printf "%6d:%s\n", NR, $0}' app/lib/katello/resources/cdn.rb

echo
echo "== test/models/cdn_configuration_test.rb around 1-110 =="
awk 'NR>=1 && NR<=110 {printf "%6d:%s\n", NR, $0}' test/models/cdn_configuration_test.rb

Repository: Katello/katello

Length of output: 11555


Guard redhat_cdn_host? against nil/blank url.

redhat_cdn_host? rescues only URI::InvalidURIError, but URI.parse(url) can raise when url is nil/blank (Ruby commonly raises NoMethodError), so the method may not reliably return false. Add a url.blank?/nil guard (or rescue NoMethodError) to make it defensive.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/models/katello/cdn_configuration.rb` around lines 46 - 48, The
redhat_cdn_host? method currently calls URI.parse(url) without guarding against
nil/blank and only rescues URI::InvalidURIError; update redhat_cdn_host? to
first return false for nil/blank url (e.g., return false if url.blank? or
url.nil?) before calling URI.parse(url). Keep the existing rescue for
URI::InvalidURIError and ensure the method uses REDHAT_CDN_HOST_PATTERN on the
parsed host as before.

Copy link
Copy Markdown
Member

@jturel jturel left a comment

Choose a reason for hiding this comment

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

Nice fix :)

Comment thread test/models/cdn_configuration_test.rb Outdated
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@vsedmik vsedmik force-pushed the fix-39303-redhat-cdn-host-check branch from 1e4e65d to cfe13fb Compare May 28, 2026 17:10
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@jeremylenz jeremylenz merged commit fc753dd into Katello:master May 28, 2026
23 checks passed
@vsedmik vsedmik deleted the fix-39303-redhat-cdn-host-check branch May 29, 2026 06:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants