From 89db1923b6ca12579c6bfb660a66bcb03af93c95 Mon Sep 17 00:00:00 2001 From: stonezdj Date: Thu, 2 Apr 2026 17:37:32 +0800 Subject: [PATCH] Add proxy cache filter proposal Signed-off-by: stonezdj --- proposals/new/filter_repository_proxycache.md | 157 ++++++++++++++++++ .../filter_repository_proxycache_ui.png | Bin 0 -> 39602 bytes 2 files changed, 157 insertions(+) create mode 100644 proposals/new/filter_repository_proxycache.md create mode 100644 proposals/new/images/filter_repository_proxycache_ui.png diff --git a/proposals/new/filter_repository_proxycache.md b/proposals/new/filter_repository_proxycache.md new file mode 100644 index 00000000..ab777f93 --- /dev/null +++ b/proposals/new/filter_repository_proxycache.md @@ -0,0 +1,157 @@ +Proposal: Limit proxy cache repositories by filter + +Author: stonezdj + +## Abstract + +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. + +## Motivation + +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. + +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. + +With proxy cache filters, administrators can define an allowlist such as: + +- `library/**` -- doublestar matching for all repositories under `library` +- `{library,goharbor}/**` -- doublestar matching for all repositories under `goharbor` and `library` +- `^(library|goharbor|myorg)/.*` -- regex matching for all repositories under `goharbor` and `library` and `myorg`, for regex kind, the pattern must be a valid regular expression. and always auto-anchored. + +This keeps the proxy cache workflow while preserving repository governance. + +## Issues + +[Limit Proxy Cache Images - by adding filter](https://github.com/goharbor/harbor/issues/13231) + +## Goals and Non-Goals + +1. Add per-project proxy cache repository filter configuration. +2. Enforce filter matching before upstream proxy pull behavior is executed. +3. Keep backward compatibility: if no filter is configured, current behavior remains unchanged. +4. Provide API and UI support for creating and updating filter configuration as part of proxy cache project configuration. + +1. This proposal does not add denylist precedence rules. Initial scope is allowlist-only. +2. This proposal does not introduce global/system-level proxy filter policy. +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. +4. This proposal does not perform content trust or vulnerability policy evaluation as part of filter matching. + +## Solution + +Add two new optional metadata settings for proxy cache projects: `proxy_cache_filter_pattern` and `proxy_cache_filter_kind`. + +Matching semantics: + +1. If `proxy_cache_filter_pattern` is empty or not set, all repositories are allowed (same as today). +2. If `proxy_cache_filter_pattern` is configured, Harbor allows the pull only when the requested repository matches the configured pattern. +3. `proxy_cache_filter_kind` specifies the matching mode: `regex` or `doublestar`. It is optional; if omitted, Harbor uses `doublestar` matching by default. +4. The repository name will be normalized by removing the leading proxy cache project name, If the normalized repository does not match, Harbor returns `404 Not Found` for the upstream proxy attempt and does not request content from upstream or local. The matching pattern is applied to both upstream registry repository and the local proxy cache repository. + +Pattern format: + +- `regex`: regular expression matching against repository path. always auto-anchored. +- `doublestar`: glob-style matching with doublestar support (`*`, `**`, `{a,b}`, and related glob features). + +## Implementation Details + +### Request enforcement point + +Enforcement should happen in proxy middleware before upstream manifest proxy operations: + +- Entry point: proxy pre-check logic in `src/server/middleware/repoproxy/proxy.go`. +- After project and proxy configuration are resolved. +- Before issuing upstream manifest requests. + +Processing flow: + +1. Resolve current project and verify it is a proxy cache project. +2. Load project proxy filter configuration. +3. Build artifact request context (repository). +4. Evaluate against repository filter. +5. If not matched, return `404 Not Found`. +6. If matched, continue existing proxy logic unchanged. + +Notes on behavior: + +1. Invalid pattern in `proxy_cache_filter_pattern` is treated as non-match at runtime when evaluating pull requests. +2. Invalid pattern in `proxy_cache_filter_pattern` is rejected with `400 Bad Request` when creating/updating project metadata. +3. In project metadata API validation, an unsupported `proxy_cache_filter_kind` value is rejected with `400 Bad Request`. + +### Data model + +Store filter as project metadata, consistent with existing proxy project settings. Both values are plain strings, matching the convention of all existing Harbor metadata keys. + +Proposed metadata keys: + +- `proxy_cache_filter_pattern`: the filter pattern string (e.g. `^library/.*`). +- `proxy_cache_filter_kind`: the matching mode, either `doublestar` or `regex`. + +Example metadata values: + +```json +{ + "proxy_cache_filter_pattern": "^library/**", + "proxy_cache_filter_kind": "doublestar" +} +``` + +Validation: + +1. `proxy_cache_filter_pattern` can be empty (empty means match all). +2. `proxy_cache_filter_kind` must be `regex` or `doublestar` when specified; defaults to `doublestar` if omitted. +3. An unrecognised `proxy_cache_filter_kind` value is rejected with `400 Bad Request` during project metadata validation. + +### API changes + +Extend project APIs for proxy cache configuration: + +1. `POST /api/v2.0/projects` +2. `PUT /api/v2.0/projects/{project_name_or_id}` +3. `GET /api/v2.0/projects/{project_name_or_id}` and list APIs should include configured filters in response. + +`proxy_cache_filter_pattern` and `proxy_cache_filter_kind` are metadata for proxy cache projects only. For non-proxy projects, these keys are ignored on create/update and omitted from response. + +Request example: + +```json +{ + "project_name": "dockerhub-proxy", + "registry_id": 1, + "metadata": { + "proxy_cache_filter_pattern": "library/**", + "proxy_cache_filter_kind": "doublestar" + } +} +``` + +### UI changes + +In proxy cache project create view, add a new configuration item: + +- Label: `Repository filter` +- A kind selector with options: `regex` and `doublestar` +- A text input for filter pattern -- input the pattern for repository filtering. + +Validation should happen both client-side and server-side. + +![Repository filter UI in proxy cache project creation](images/filter_repository_proxycache_ui.png) + +### Audit and observability + +1. Record project update audit entries when filter set is changed. +2. Add log item for blocked proxy pulls (project, repository, reason) to help operators tune filters. + +## Database Schema Changes + +No new table is required for initial implementation when storing as project metadata. + + +## Compatibility + +1. Existing proxy cache projects without filters keep current behavior (allow all). +2. New behavior is opt-in by configuring `proxy_cache_filter_pattern` and `proxy_cache_filter_kind`. +3. Clients receive `404 Not Found` for repositories that do not match the configured filter. there is a log item for blocked requests to help operators identify and adjust filters as needed. + +## Open issues + +N/A diff --git a/proposals/new/images/filter_repository_proxycache_ui.png b/proposals/new/images/filter_repository_proxycache_ui.png new file mode 100644 index 0000000000000000000000000000000000000000..6866315c8ce758e7ec340b73bcdbcc55001bba15 GIT binary patch literal 39602 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