|
| 1 | +Proposal: Limit proxy cache repositories by filter |
| 2 | + |
| 3 | +Author: stonezdj |
| 4 | + |
| 5 | +## Abstract |
| 6 | + |
| 7 | +Harbor proxy cache projects currently allow pulling any repository from the configured upstream registry. This proposal introduces a repository filter on proxy cache projects so administrators can explicitly allow only selected repositories. Requests that do not match the configured filter are denied before Harbor proxies content from upstream. |
| 8 | + |
| 9 | +## Motivation |
| 10 | + |
| 11 | +Many organizations use Harbor as the only approved image source for runtime environments, while direct access to public registries is restricted for security and compliance reasons. Proxy cache simplifies image consumption, but without repository filtering it also opens access to unintended or untrusted content. |
| 12 | + |
| 13 | +Today users commonly work around this by creating many replication rules for individual repositories and tags. This is operationally expensive and hard to maintain at scale. |
| 14 | + |
| 15 | +With proxy cache filters, administrators can define an allowlist such as: |
| 16 | + |
| 17 | +- `library/**` -- doublestar matching for all repositories under `library` |
| 18 | +- `goharbor/**` -- doublestar matching for all repositories under `goharbor` |
| 19 | +- `myorg/.*` -- regex matching for all repositories under `myorg` |
| 20 | + |
| 21 | +This keeps the proxy cache workflow while preserving repository governance. |
| 22 | + |
| 23 | +## Issues |
| 24 | + |
| 25 | +[Limit Proxy Cache Images - by adding filter](https://github.com/goharbor/harbor/issues/13231) |
| 26 | + |
| 27 | +## Goals and Non-Goals |
| 28 | + |
| 29 | +1. Add per-project proxy cache repository filter configuration. |
| 30 | +2. Enforce filter matching before upstream proxy pull behavior is executed. |
| 31 | +3. Keep backward compatibility: if no filter is configured, current behavior remains unchanged. |
| 32 | +4. Provide API and UI support for creating and updating filter configuration as part of proxy cache project configuration. |
| 33 | + |
| 34 | +1. This proposal does not add denylist precedence rules. Initial scope is allowlist-only. |
| 35 | +2. This proposal does not introduce global/system-level proxy filter policy. |
| 36 | +3. This proposal does not support tag-based filtering in this phase, because pull requests by tag are often converted to pull requests by digest in client side. |
| 37 | +4. This proposal does not perform content trust or vulnerability policy evaluation as part of filter matching. |
| 38 | + |
| 39 | +## Solution |
| 40 | + |
| 41 | +Add a new optional setting for proxy cache projects: `repository_filter`. |
| 42 | + |
| 43 | +Matching semantics: |
| 44 | + |
| 45 | +1. If `repository_filter` is empty or not set, all repositories are allowed (same as today). |
| 46 | +2. If `repository_filter` is configured, Harbor allows the pull only when the requested repository matches the configured pattern. |
| 47 | +3. The filter format is JSON: `{"filter":"<pattern>","kind":"regex"|"doublestar"}`. |
| 48 | +4. `kind` is optional. If omitted, Harbor uses `regex` matching by default. |
| 49 | +5. If the repository does not match, Harbor returns `404 Not Found` and does not request content from upstream. |
| 50 | + |
| 51 | +Pattern format: |
| 52 | + |
| 53 | +- `regex`: regular expression matching against repository path. |
| 54 | +- `doublestar`: glob-style matching with doublestar support (`*`, `**`, `{a,b}`, and related glob features). |
| 55 | + |
| 56 | +## Implementation Details |
| 57 | + |
| 58 | +### Request enforcement point |
| 59 | + |
| 60 | +Enforcement should happen in proxy middleware before upstream manifest proxy operations: |
| 61 | + |
| 62 | +- Entry point: proxy pre-check logic in `src/server/middleware/repoproxy/proxy.go`. |
| 63 | +- After project and proxy configuration are resolved. |
| 64 | +- Before issuing upstream manifest requests. |
| 65 | + |
| 66 | +Processing flow: |
| 67 | + |
| 68 | +1. Resolve current project and verify it is a proxy cache project. |
| 69 | +2. Load project proxy filter configuration. |
| 70 | +3. Build artifact request context (repository). |
| 71 | +4. Evaluate against repository filter. |
| 72 | +5. If not matched, return `404 Not Found`. |
| 73 | +6. If matched, continue existing proxy logic unchanged. |
| 74 | + |
| 75 | +Notes on behavior: |
| 76 | + |
| 77 | +1. Invalid `repository_filter` JSON or invalid pattern is treated as non-match at runtime. |
| 78 | +2. In project metadata API validation, invalid JSON or unsupported `kind` value is rejected with `400 Bad Request`. |
| 79 | + |
| 80 | +### Data model |
| 81 | + |
| 82 | +Store filter as project metadata, consistent with existing proxy project settings. |
| 83 | + |
| 84 | +Proposed metadata key: |
| 85 | + |
| 86 | +- `repository_filter` |
| 87 | + |
| 88 | +Proposed JSON value: |
| 89 | + |
| 90 | +```json |
| 91 | +{ |
| 92 | + "filter": "^library/.*", |
| 93 | + "kind": "regex" |
| 94 | +} |
| 95 | +``` |
| 96 | + |
| 97 | +Validation: |
| 98 | + |
| 99 | +1. `filter` can be empty (empty means match all). |
| 100 | +2. `kind` must be `regex` or `doublestar` when specified. |
| 101 | +3. Invalid JSON is rejected during project metadata validation. |
| 102 | + |
| 103 | +### API changes |
| 104 | + |
| 105 | +Extend project APIs for proxy cache configuration: |
| 106 | + |
| 107 | +1. `POST /api/v2.0/projects` |
| 108 | +2. `PUT /api/v2.0/projects/{project_name_or_id}` |
| 109 | +3. `GET /api/v2.0/projects/{project_name_or_id}` and list APIs should include configured filters in response. |
| 110 | + |
| 111 | +`repository_filter` is metadata for proxy cache projects only. For non-proxy projects, this metadata is ignored on create/update and omitted from response. |
| 112 | + |
| 113 | +Request example: |
| 114 | + |
| 115 | +```json |
| 116 | +{ |
| 117 | + "project_name": "dockerhub-proxy", |
| 118 | + "registry_id": 1, |
| 119 | + "metadata": { |
| 120 | + "repository_filter": "{"filter":"library/**","kind":"doublestar"}" |
| 121 | + } |
| 122 | +} |
| 123 | +``` |
| 124 | + |
| 125 | +### UI changes |
| 126 | + |
| 127 | +In proxy cache project create view, add a new configuration item: |
| 128 | + |
| 129 | +- Label: `Repository filter` |
| 130 | +- A text input for filter pattern -- input the pattern for repository filtering. |
| 131 | +- A kind selector with options: `Regex` and `Doublestar` |
| 132 | + |
| 133 | +Validation should happen both client-side and server-side. |
| 134 | + |
| 135 | +### Audit and observability |
| 136 | + |
| 137 | +1. Record project update audit entries when filter set is changed. |
| 138 | +2. Add log item for blocked proxy pulls (project, repository, reason) to help operators tune filters. |
| 139 | + |
| 140 | +## Database Schema Changes |
| 141 | + |
| 142 | +No new table is required for initial implementation when storing as project metadata. |
| 143 | + |
| 144 | + |
| 145 | +## Compatibility |
| 146 | + |
| 147 | +1. Existing proxy cache projects without filters keep current behavior (allow all). |
| 148 | +2. New behavior is opt-in by configuring `repository_filter`. |
| 149 | +3. Clients receive `404 Not Found` for repositories that do not match the configured filter. |
| 150 | + |
| 151 | +## Open issues |
| 152 | + |
| 153 | +N/A |
0 commit comments