Uploaded image for project: 'Project Quay'
  1. Project Quay
  2. PROJQUAY-10865

Quay 3.17 Org Mirror missing no_proxy support in discovery phase causes proxy bypass failures

XMLWordPrintable

    • False
    • Hide

      None

      Show
      None
    • False

      Problem

      The organization-level mirror feature has broken no_proxy support in the discovery phase (repository listing via Harbor/Quay API), causing failures when trying to bypass proxy for specific hosts.

      Status:

      • Repository mirror: ✅ Works correctly
      • Org mirror - Discovery phase (HTTP API): ❌ BROKEN
      • Org mirror - Image copy phase (skopeo): ✅ Works correctly

      Root Cause

      File: util/orgmirror/registry_adapter.py:64-71

      The _build_proxies() method builds a proxies dict for Python's requests library but ignores the no_proxy configuration:

      def _build_proxies(self) -> Dict:
          """Build proxies dict for requests library."""
          proxies = {}
          if self.proxy.get("http_proxy"):
              proxies["http"] = self.proxy["http_proxy"]
          if self.proxy.get("https_proxy"):
              proxies["https"] = self.proxy["https_proxy"]
          # ❌ MISSING: no_proxy handling
          return proxies
      

      Affected adapters:

      • harbor_adapter.py:78 - Harbor project repository discovery
      • quay_adapter.py:121 - Quay namespace repository discovery

      Technical Details

      The Python requests library does NOT support no_proxy via the proxies dict parameter. It only reads no_proxy from environment variables NO_PROXY or no_proxy.

      Comparison with repository mirror:

      Repository mirror correctly implements no_proxy in util/repomirror/skopeomirror.py:166-176:

      def setup_env(self, proxy):
          env = os.environ.copy()
          if proxy.get("http_proxy"):
              env["HTTP_PROXY"] = proxy.get("http_proxy")
          if proxy.get("https_proxy"):
              env["HTTPS_PROXY"] = proxy.get("https_proxy")
          if proxy.get("no_proxy"):
              env["NO_PROXY"] = proxy.get("no_proxy")  # ✅ Works
          return env
      

      Org mirror does reuse this skopeo code for image operations (workers/repomirrorworker/_init_.py:1376, 1583), so no_proxy works for image copying and tag listing via skopeo.

      Impact

      Severity: Medium
      User Impact:

      • Organizations cannot bypass proxy for internal/private registries during discovery
      • All Harbor/Quay API calls are forced through proxy, even for .local or .internal hosts
      • Workaround: Deploy proxy with passthrough rules (requires infrastructure changes)

      Affected Scenarios:

      1. Harbor registry on internal network (registry.internal.company.com)
      2. Quay registry with split-horizon DNS (quay.local)
      3. Cloud metadata endpoints that should not be proxied
      4. Corporate networks with selective proxy bypass requirements

      Recommended Fix

      Set NO_PROXY environment variable in _build_proxies() method:

      def _build_proxies(self) -> Dict:
          """Build proxies dict for requests library."""
          import os
          
          proxies = {}
          if self.proxy.get("http_proxy"):
              proxies["http"] = self.proxy["http_proxy"]
          if self.proxy.get("https_proxy"):
              proxies["https"] = self.proxy["https_proxy"]
          
          # ✅ FIX: Set NO_PROXY environment variable
          # The requests library reads this, but not from the proxies dict
          if self.proxy.get("no_proxy"):
              os.environ["NO_PROXY"] = self.proxy["no_proxy"]
              os.environ["no_proxy"] = self.proxy["no_proxy"]  # Lowercase for compatibility
          
          return proxies
      

      Alternative (thread-safe): Use context manager to set/restore env vars

      Testing Requirements

      1. Unit test: Verify NO_PROXY env var is set when no_proxy config provided
      2. Integration test: Mock Harbor/Quay API, verify requests bypass proxy for no_proxy hosts
      3. End-to-end test: Configure org mirror with no_proxy, verify discovery succeeds without proxy

      Related Code

      • Repository mirror (working reference): util/repomirror/skopeomirror.py:166-176
      • Org mirror discovery: util/orgmirror/harbor_adapter.py:54-150, util/orgmirror/quay_adapter.py:93-182
      • Org mirror image copy (works): workers/repomirrorworker/_init_.py:1366-1379

      References

              rh-ee-shossain Shaon Hossain
              lzha1981 luffy zhang
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated: