1
0
mirror of https://github.com/goharbor/harbor.git synced 2026-10-23 10:08:57 +03:00

1444 Commits

Author SHA1 Message Date
Youngju KIM
1e21dd147a Stamp version info into the bundled Trivy adapter binary (#24164)
The adapter is built without -ldflags, so its startup log and
/api/v1/metadata report version "dev", commit "none" and build date
"unknown". Pass the version, commit and date the same way the
upstream release build does.

Signed-off-by: YoungjuKim <fjvbn2003@gmail.com>
2026-10-20 14:00:27 +08:00
Vadim Bauer
f6f5bac8d1 feat(webhook): add webhook egress policy levels and allowlist (#24079)
The webhook SSRF guard was a single boolean. With it off (the default
since #24078) webhooks can reach loopback and cloud metadata; with it on,
every internal receiver breaks.

HARBOR_WEBHOOK_EGRESS_POLICY (harbor.yml webhook_egress.policy) selects a
level: allow_all, block_restricted (default) or public_only. Restricted
covers loopback, link-local, cloud metadata, unspecified, multicast and
NAT64/6to4/Teredo. HARBOR_WEBHOOK_EGRESS_ALLOWLIST takes IPs, CIDRs,
hostnames and *.domain suffixes that are allowed at every level.

When the policy is unset, the deprecated HARBOR_ALLOW_PRIVATE_NETWORK_ACCESS
keeps its 2.15 meaning: true is allow_all, false is public_only. Invalid
values fail closed, prepare rejects an unknown policy, and a blocked
target is logged with the setting that reopens it.

Signed-off-by: Vadim Bauer <vb@container-registry.com>
2026-10-08 07:15:15 +05:30
Wang Yan
9a37bcf55f fix(webhook): allow private network access by default to avoid regres… (#24078)
* fix(webhook): allow private network access by default to avoid regression

Default HARBOR_ALLOW_PRIVATE_NETWORK_ACCESS to true to prevent breaking
existing on-premise and Kubernetes deployments where webhooks target
internal services.

Remove the allow_private_network_access field from harbor.yml to keep
the YAML schema clean, managing this toggle solely via the environment
variable.

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* resolve copilot review

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* resolve the comments

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

---------

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
2026-10-07 20:04:17 +08:00
Vadim Bauer
b323c0c8ec Merge commit from fork
* fix(webhook): block SSRF to private-network targets and stop reflecting response bodies

Webhook and Slack notification jobs delivered to any operator-supplied URL with
no address classification, and folded a non-2xx response body into the
project-readable task log. A project admin could reach loopback, RFC1918,
link-local and cloud-metadata (169.254.169.254) targets and read internal
service responses back through the webhook task log (CWE-918).

Classify destinations against the IANA special-purpose registries and reject
non-public targets at (1) webhook policy validation and (2) a dial-time guard on
the notification HTTP clients; drop the response body from the task-log error;
refuse redirects. The HARBOR_ALLOW_PRIVATE_NETWORK_ACCESS opt-out (default off)
restores delivery to internal endpoints for operators who rely on it.

Signed-off-by: Vadim Bauer <vb@container-registry.com>

* test(webhook): cover SSRF target rejection, body-drop and redirect refusal

Signed-off-by: Vadim Bauer <vb@container-registry.com>

* test(webhook): resolve upstream's mixed-case target host in the stub resolver

Upstream #23889 added a create-policy test that posts a mixed-case target
address and expects 201. With the SSRF target check in place that hostname
now goes through the stub resolver, which only knew hooks.example.com, so
the test failed with 400. Teach the stub the second hostname; the upstream
test keeps asserting lowercasing, the SSRF tests keep asserting rejection.

Signed-off-by: Vadim Bauer <vb@container-registry.com>

* fix(webhook): honour the jobservice proxy settings in the SSRF-safe transport

The public-network guard cleared Transport.Proxy, so webhook and Slack
delivery ignored the HTTP_PROXY/HTTPS_PROXY/NO_PROXY settings that
prepare writes for jobservice. Deployments without a direct Internet
route lost every public webhook.

Keep the transport's proxy function. When it selects a proxy, validate
the target host (literal or all resolved addresses) as public before the
request is handed to the proxy, and let only dials to that proxy address
skip the dial-time private-address check. When no proxy applies
(NO_PROXY, loopback), the resolved-address dial guard is unchanged. A
direct request aimed at the proxy's own address is refused so it cannot
inherit the proxy exemption.

Signed-off-by: Vadim Bauer <vb@container-registry.com>

* chore: describe the fix without advisory identifiers

Signed-off-by: Vadim Bauer <vb@container-registry.com>
(cherry picked from commit 54cc3fca7a741ecb31293a767b998ceffec9d5b5)

* fix(webhook): drain notification response bodies before closing

Closing an unread response body forces the transport to drop the
keep-alive connection. Discard up to 64KiB of the body (never surfacing
it) so the pooled connection is reused after non-2xx responses.

Signed-off-by: Vadim Bauer <vb@container-registry.com>

* test(webhook): assert the dial guard on production clients and pin the env

Exercise the production notification clients against a loopback target
so dropping the public-network guard fails a test, cover connection
reuse after non-2xx responses, and pin HARBOR_ALLOW_PRIVATE_NETWORK_ACCESS
to false in tests that assert the default blocking behaviour.

Signed-off-by: Vadim Bauer <vb@container-registry.com>

* fix(prepare): keep network.allow_private_network_access across migrate

The migrate command re-renders harbor.yml from the 2.15.0 template, so a
key missing there is dropped. Render the network block, preserving an
operator-set value and defaulting to false.

Signed-off-by: Vadim Bauer <vb@container-registry.com>

---------

Signed-off-by: Vadim Bauer <vb@container-registry.com>
2026-10-06 14:04:35 +02:00
Max
37dc02fdff feat: custom project roles (hybrid — built-ins in code, custom in DB) (#23804)
* feat: custom project roles (hybrid — built-ins in code, custom in DB)

Adds admin-defined custom project roles as an alternative to #22815, per
maintainer feedback: built-in project roles keep resolving their permissions
from the compile-time rolePoliciesMap (no DB, no cache — identical to today),
and ONLY custom roles are stored in and loaded from the database. There is no
permission cache.

Backend + API only (UI ships separately). Highlights:
- RBAC (common/rbac/project): projectRBACRole gains an optional custom *role.Role.
  The built-in path is byte-identical to upstream; the role controller is
  consulted only for non-built-in role IDs, so built-in authorization incurs no
  DB lookup. Custom roles expand their DB-loaded permissions.
- Role subsystem: pkg/role (model/dao/manager) + controller/role for CRUD and
  persistence; existing role_permission/permission_policy reused for custom perms.
- REST API: /roles endpoints (sysadmin-gated), an effective-permissions endpoint,
  anti-escalation checks on member/robot assignment, and audit events.
- Migration 0191 adds is_builtin/description/audit columns to `role`, widens the
  name, enforces name uniqueness, and marks seeded roles built-in. Built-in
  permissions are NOT seeded into the DB.

Rebased onto current main; API bindings regenerated via gen_apis.

Tracking: #18124
Alternative to: #22815

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: make role a system RBAC resource; drop checkSysAdmin & ResourceSelf

Addresses stonezdj's review on PR #23804:
- Define rbac.ResourceRole (system-level) and add it to the system permission
  catalog; gate CreateRole/UpdateRole/DeleteRole with RequireSystemAccess(action,
  ResourceRole) instead of the hand-rolled checkSysAdmin — so the permission is
  managable while still effectively system-only.
- Remove the checkSysAdmin helper and its unit tests; update handler tests to
  mock Can().
- Drop ResourceSelf from the ScopeRole permission catalog.
- Remove tests/integration/.gitignore (per-dir ignore file).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: close built-in-role escalation gap; reject nil role payloads

Addresses Copilot findings on PR #23804:
- checkNoEscalation treated built-in roles as permissionless: it read permissions
  from role_permission, which has no rows for built-in roles, so a caller with
  member:create could assign projectAdmin (or any built-in) without holding its
  permissions. Built-in permissions are now synthesized from the compile-time
  policy map via the new rbac/project.BuiltinRolePolicies; custom roles still read
  the DB. Adds TestCheckNoEscalation_BuiltinRoleSynthesized.
- role validate() now rejects nil permission/access elements (permissions:[null],
  access:[null]) with 400 instead of panicking. Adds nil-payload tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: validate that a member's custom role exists in the database

Addresses stonezdj's review on PR #23804: isValidRole returned true for any
integer above the built-in range, so a member could be assigned a non-existent
custom role ID. The member controller now holds a role manager and validateRole
verifies custom role IDs (>5) exist via roleMgr.Get, rejecting unknown IDs with
ErrInvalidRole; built-in roles (1-5) still pass without a DB lookup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: make role Create/Update/Delete atomic via orm.WithTransaction

Addresses Copilot findings on PR #23804:
- Create: the role row and its permission records are now created in one
  transaction, so a failed permission insert no longer leaves a named role with
  missing permissions (whose unique name would block a clean retry).
- Update: the field update and the delete+recreate of permissions run in one
  transaction, so the role's authorization is never observable in a partial state.
- Delete: the member-assignment guard and the role/permission deletes run in one
  transaction, serializing the guard with the delete and ensuring permission rows
  never outlive the role. (Full prevention of a concurrent assignment needs a
  DB-level FK on project_member.role — tracked as a follow-up.)

Controller unit tests inject a fake ormer (testing/lib/orm) so the transaction
wrappers resolve an ormer from context.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: group /roles/{role_id} right after /roles in swagger

Addresses stonezdj's review on PR #23804: the two role endpoints serve the same
feature and should be adjacent in the spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: split out role audit-log events; drop the standalone integration test

Addresses stonezdj's review on PR #23804 (shrink the PR):
- Remove the role audit-log event wiring from this PR (controller/event
  metadata/role.go, topic.go role topics/events, init.go subscriptions, and the
  notification.AddEvent calls in the role controller). It will be submitted as a
  separate follow-up PR; the code is preserved on branch 18124-role-audit-events.
- Remove tests/integration/test_custom_roles.py: it is not wired into Harbor CI
  (which uses tests/apitests) and contained the issues Copilot flagged. Feature
  behavior is covered by the Go unit tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: validate role on member UpdateRole; fix stale invalid-role message

Addresses stonezdj's follow-up review on PR #23804:
- UpdateRole (changing a member's role) now runs the same validateRole check as
  AddProjectMember, so a member can't be moved to a non-existent role.
- ErrInvalidRole no longer claims "role is not in 1,2,3"; it now states the role
  must be a built-in role (1-5) or an existing custom role.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: remove duplicate effective-permissions endpoint

Addresses stonezdj's review on PR #23804: GET /projects/{id}/permissions/effective
duplicated the existing GET /users/current/permissions, which already supports a
project scope and a `relative` flag (scope=/project/{id}&relative=true returns the
same set of project permissions the caller holds). Removed the handler and the
swagger path (bindings regenerated). The shared mapRobotToHumanResource helper is
kept — it is still used by the robot anti-escalation check.

The robot-account UI (separate PR) will use /users/current/permissions instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* fix(rbac): keep role management sysadmin-only, not delegable

Role write access is checked via RequireSystemAccess(ctx, action,
rbac.ResourceRole), but ResourceRole was also added to the grantable
ScopeSystem catalog (NolimitProvider). That published role:* as an
assignable system permission: it could be granted to a system robot
(robots evaluate system-scope policies) and listed in /permissions,
even though a human non-admin never evaluates system-scope perms.

A system robot granted role:update could then rewrite any custom
role's permission set (UpdateRole/updateV2Role has no subset guard)
= privilege escalation.

Remove the ResourceRole entries from the ScopeSystem catalog. The
admin evaluator bypasses the catalog, so sysadmins still pass the
RequireSystemAccess check and manage roles exactly as before, but
role:* is no longer assignable/enumerable to non-admins. This keeps
role management strictly sysadmin-only while still expressing it as
a first-class action+resource check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* fix(rbac): grant custom-role members baseline self:read (project visibility)

self:read (ResourceSelf) is the permission that gates viewing a project:
RequireProjectAccess(ctx, id, ActionRead) with no subresource checks
<project-ns>:"" and GetProject/GetSummary use exactly that. Built-in
roles carry self:read in rolePoliciesMap, and public projects grant it
via publicProjectPolicies, but a custom role in a private project had no
way to obtain it -- self:* is intentionally excluded from the ScopeRole
catalog, and GetPolicies returned only the role's explicit permissions.

Result: a member whose only access to a private project was a custom
role got a 403 opening that project.

Append {ResourceSelf, ActionRead} to the custom-role branch of
projectRBACRole.GetPolicies (de-duplicated), mirroring the built-in
roles and the public-project baseline. Only self:read is granted, never
self:update/self:delete (project edit/delete stay exclusive to the
projectAdmin built-in), and self:* remains out of the user-facing
catalog so it is guaranteed by the system rather than a tickable option.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* refactor(rbac): grant self:read at membership level, not per custom role

Move the baseline project-visibility grant out of the custom-role branch
of projectRBACRole.GetPolicies and into rbacUser.GetPolicies: any user
who holds at least one role in a project (len(projectRoles) > 0) is
granted self:read on that project.

This makes baseline visibility a property of project membership rather
than a per-custom-role special case, sitting beside the existing
public-project baseline (getPoliciesForPublicProject) and using the same
eval-time idiom -- no permission data seeded into the database. Built-in
and custom roles now obtain self:read the same way, and the grant stays
scoped to the membership project (ListRoles is per-project), so it never
exposes projects the user is not a member of.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* chore(deps-dev): bump webpack-cli from 4.10.0 to 7.2.3 in /src/portal/app-swagger-ui (#23850)

chore(deps-dev): bump webpack-cli in /src/portal/app-swagger-ui

Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.10.0 to 7.2.3.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.10.0...webpack-cli@7.2.3)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-version: 7.2.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Prasanth Baskar <prasanth@8gears.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: consolidate 2.16.0 migration into 0190 and simplify robot resource map

Address two review comments from stonezdj on PR #23804:

- 2.16.0 is not released yet, so keep all its schema changes in a single
  migration file. Move the custom-role `role` table additions (columns,
  name widened to varchar(255), uq_role_name unique index, is_builtin
  update) from 0191 into 0190 and delete 0191.

- Simplify mapRobotToHumanResource: replace the single-entry
  robotToHumanResourceMap + lookup with a direct
  `if r == rbac.ResourceProject { return rbac.ResourceSelf }`.

Also commit the cross-project isolation test for the membership-level
self:read baseline (a member of one private project cannot read another).

No behavior change; robot resource-mapping tests pass unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: fix bugs from bupd's review (keep roles global + sysadmin-only)

Address the correctness findings from bupd's review of PR #23804, keeping
the global, sysadmin-managed role model (project-scoped roles remain a
separate future feature):

- evaluator: a failed custom-role load no longer drops the whole rbacUser.
  Returning nil stripped every role the member held in the project (built-ins
  included), turning a transient DB error or a dangling project_member.role
  into a total 403 / permanent lockout. Skip only the failing role instead.
- role validate(): reject any permission Effect other than "" or "allow".
  It was stored verbatim and handed to casbin, so a mis-cased "Allow" or a
  bogus value was accepted and silently granted nothing.
- read path: GET /roles(/{id}) now returns a built-in role's real permissions
  (resolved from rolePoliciesMap via BuiltinRolePolicies) instead of an empty
  set; built-ins have no role_permission rows by design. Removed the dead
  "Visible" list filter (model.Role has no such field).
- controller Delete: a custom role with no permission rows is deletable again
  (DeletePermissionsByRole's NotFound no longer rolls back the txn); dropped
  the unused variadic option parameter.
- controller Update: persist a role name change instead of silently dropping
  it (validated in the handler; DB unique index rejects collisions).
- permissions.go: restore the sysadmin-or-project-admin gate on GET
  /permissions (it had been relaxed to any authenticated user), and expose the
  role-level catalog only to sysadmins.
- rolePoliciesMap["projectAdmin"]: add metadata:list, restoring 2.15 behavior
  where a project admin can create a robot with metadata:list (the new robot
  anti-escalation check validated against projectAdmin, which lacked it).
- swagger: document that role reads are open to any authenticated user while
  writes are sysadmin-only.
- add a drift-guard test asserting the ScopeRole catalog equals projectAdmin
  minus self:{read,update,delete}, plus tests for the fixes above.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: make role name uniqueness case-insensitive

Per bupd's review: enforce uniqueness on lower(name) so "Maintainer" and
"maintainer" cannot coexist and be confused for one another. 2.16.0 is
unreleased, so the index is dropped and recreated in place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* fix(role): correct stale TestList assertion (roles have no "visible" concept)

TestDaoTestSuite/TestList asserted that a freshly created role is NOT
returned by List (len == 0), a leftover from a removed "visible" column.
model.Role has no such field and the List DAO applies no visibility
filter, so the role is returned. Assert it is listed (len == 1) to match
the actual, intended behavior. Surfaced now that UTTEST runs on the PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

* review: robot-refresh escalation, deny-effect guard, delete-race FK, swagger 409/412

Address chlins' and Copilot's review of PR #23804:

- RefreshSec escalation (chlins #1): refreshing a robot's secret is
  equivalent to being granted the robot's permissions, so it now runs the
  same no-escalation check as create/update (load the robot with
  permissions; human callers checked via validateNoEscalation, robot
  callers via isValidPermissionScope). A member with robot:update but not
  the robot's own permissions can no longer take over a more-privileged
  robot.
- Deny-effect guard (chlins #2): member checkNoEscalation now skips
  Effect==deny accesses; they restrict rather than grant, so requiring the
  caller to hold them wrongly blocked assigning a role that merely denies
  something.
- Delete-vs-assign race (chlins #3): add FK project_member.role ->
  role(role_id) ON DELETE RESTRICT so the DB atomically rejects deleting an
  assigned role, closing the count-then-delete race; the resulting FK error
  is mapped to 412 in the role Delete controller.
- Swagger: document 409 (CreateRole duplicate-name conflict) and 412
  (DeleteRole still-assigned) responses.
- Tests: FK-race delete -> 412, and a Create failure-injection so dropping
  the transaction would fail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>

---------

Signed-off-by: Max Grau Stenzel <max.grau.stenzel@gmail.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Prasanth Baskar <prasanth@8gears.com>
2026-09-29 19:51:23 +08:00
stonezdj(Daojun Zhang)
fb6f06b6cc fix(migration): make sbom_report index creation idempotent (#23895)
Add IF NOT EXISTS to CREATE INDEX idx_sbom_report_sbom_digest
in make/migrations/postgresql/0190_2.16.0_schema.up.sql so that
the upgrade migration script can run idempotently without failing
if the index already exists.

Fixes #23894

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
Signed-off-by: stonezdj <stonezdj@gmail.com>
2026-09-11 07:21:26 +00:00
Rudra
74691f57cc Fix CPU saturation from full table scans during artifact deletion by indexing sbom_digest (#23773)
* fixed Artifact deletion runs an unindexable report::jsonb @> DELETE on sbom_report, causing DB CPU saturation during retention runs #23772

Signed-off-by: Rudra Pratap <rudra888pratap@gmail.com>
Signed-off-by: raudhra <rudra888pratap@gmail.com>

* address review comments: use generated column and add attribute validation

Signed-off-by: Rudra Pratap <rudra888pratap@gmail.com>
Signed-off-by: raudhra <rudra888pratap@gmail.com>

* remove sbom_digest from models to fix generated column insert conflicts

Signed-off-by: raudhra <rudra888pratap@gmail.com>

* refactor(sbom): use expression index for sbom_digest deletion

Avoid database table rewrites and ORM mapping conflicts by replacing the generated column strategy with an expression index on sbom_report.

Signed-off-by: raudhra <rudra888pratap@gmail.com>

* test: remove deleted SBOMDigest field from dao tests

Signed-off-by: raudhra <rudra888pratap@gmail.com>

---------

Signed-off-by: Rudra Pratap <rudra888pratap@gmail.com>
Signed-off-by: raudhra <rudra888pratap@gmail.com>
2026-08-29 10:05:21 +00:00
stonezdj(Daojun Zhang)
b9b2e8c717 fix: convert setup_timestamp, status_revision, and revision columns to bigint to avoid Y2K38 overflow (#23711) (#23718)
Alters the column types in p2p_preheat_instance, task, and schedule tables to bigint to prevent Y2K38 integer overflow issues.

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
Co-authored-by: Wang Yan <wangyan_0219@hotmail.com>
2026-08-13 06:44:47 +00:00
Wang Yan
95ed8f0eda fix: convert robot account ID columns and sequence to bigint (#23633)
* fix(robot): convert robot account ID columns and sequence to bigint (#23091)

Convert robot.id, creator_ref, role_permission.role_id, and robot_id_seq
to bigint in PostgreSQL migration and update swagger.yaml parameters to
format: int64.

The sequence is capped at 9007199254740991 (2^53 - 1, JavaScript's
Number.MAX_SAFE_INTEGER) instead of the bigint maximum, so every possible
robot ID stays exactly representable as a JSON number for clients that
decode into IEEE 754 doubles (portal, jq, generated JS clients). This
still provides ~4 million times the int4 range.

Unmarshaling extra_attrs using json.Decoder.UseNumber() and helper
task.Int64FromAny ensures numeric IDs above 2^53 (e.g. execution or
artifact IDs of other vendors) do not lose precision during scan task
callbacks and data exports.

Fixes: #23091
Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* resovle the review comments

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

---------

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
2026-08-06 08:53:06 +00:00
Hoai-Thu Vuong
da420bcad0 lowercase value of metric enable when migrate from old to new version (#22580)
lowercase metric enable

Signed-off-by: Hoai-Thu Vuong <thuvh87@gmail.com>
Co-authored-by: Wang Yan <wangyan_0219@hotmail.com>
2026-08-04 14:20:27 +08:00
Denis
f89aad3720 fix: add registry component to proxy configuration support (#23437)
When proxy is configured with registry in components list, the
registry service will now receive proxy environment variables
(HTTP_PROXY, HTTPS_PROXY, NO_PROXY) through the registry/env file.

Changes:
- Added 'registry' to proxy.components list in harbor.yml.tmpl
- Added 'registry' to proxy.components list in values.yaml (Helm charts)
- Created registry/env.jinja template with proxy env vars
- Updated registry.py to render registry env file
- Added env_file directive to registry service in docker-compose.yml

Signed-off-by: Kibakus <den01246@gmail.com>
2026-07-16 06:11:19 +00:00
dependabot[bot]
4a09f715e1 chore(deps-dev): bump pygments from 2.19.2 to 2.20.0 in /make/photon/prepare (#23053)
chore(deps-dev): bump pygments in /make/photon/prepare

Bumps [pygments](https://github.com/pygments/pygments) from 2.19.2 to 2.20.0.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.19.2...2.20.0)

---
updated-dependencies:
- dependency-name: pygments
  dependency-version: 2.20.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 09:05:14 +00:00
Yannick Müller
687298935d fix: increase access_key column length to 4096 (#23414)
Signed-off-by: Yannick Müller <mail@ynnk.dev>
2026-06-22 09:54:35 +00:00
Wang Yan
c8ed06b1df fix(build): pin Photon base to stable multi-arch digest (#23352)
The latest upstream photon:5.0 arm64 image currently has an empty rootfs,
which fails during the multi-arch base build with "/bin/sh: no such file
or directory". Pin the Photon base to a known-good stable digest to keep
the amd64 and arm64 builds reproducible.

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
2026-06-12 10:09:24 +08:00
Wang Yan
8ee16b8074 fix: solve db build conflict and robustify workflow repo list saving (#23350)
pin qemu binfmt and prevent publish races

- Pin docker/setup-qemu-action to tonistiigi/binfmt:qemu-v9.2.2 for stable arm64 emulation.
- Add per-branch concurrency in build-package workflow to avoid overlapping runs racing on mutable tags/manifests.
- Rename Go setup step label to match the actual configured version.

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
2026-06-11 12:09:26 +00:00
Wang Yan
a37374efe9 Harden crypto usage and drop unused SMTP package (#23307)
- Use stdlib crypto/pbkdf2 instead of golang.org/x/crypto/pbkdf2 for
  password/secret hashing (output unchanged; no migration needed).
- Restrict JWT signing to RSA/RSA-PSS and reject other methods in
  pkg/token (default RS256 unchanged).
- Remove unused common/utils/email package (no references in codebase).

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
Co-authored-by: wang yan <yan-yw.wang@broadcom.com>
2026-06-11 14:48:09 +08:00
Vadim Bauer
7d0cac2a6f fix: publish harbor-*-base images as multi-arch manifests (#23348)
The per-component base images (goharbor/harbor-core-base, harbor-db-base,
harbor-portal-base, ...) were pushed by both BUILD_PACKAGE matrix jobs to the
same unsuffixed tag (e.g. :dev), so whichever architecture finished last
overwrote the other and the published tag ended up single-arch — the same
last-writer-wins problem goharbor/photon:5.0 had before #23334 (#23324).

Apply the same pattern already used for the component images:

- make/photon/Makefile: _build_base keeps building the local unsuffixed tag
  (component Dockerfiles build FROM it unchanged) but pushes an arch-suffixed
  tag instead: harbor-<name>-base:<tag>-amd64 / -arm64.
- .github/workflows/build-package.yml: each matrix job also saves the list of
  goharbor/*-base repos it built; CREATE_MANIFEST combines the two suffixed
  tags into the unsuffixed multi-arch manifest with docker buildx imagetools
  create, using the base tag scheme (dev on main, the release version on
  release-* branches). The base manifest step only runs when BUILD_BASE_IMAGE
  decided to rebuild bases, since otherwise no suffixed tags were pushed in
  this run.

Consumers that pull harbor-*-base:<tag> (PULL_BASE_FROM_DOCKERHUB=true flows)
now resolve the correct architecture via the manifest list instead of getting
whatever architecture won the race.

Signed-off-by: Vadim Bauer <vb@container-registry.com>
2026-06-11 10:37:45 +08:00
Ashish Patel
a821bae24a feat(portal): upgrade Angular to v21, Clarity to v18, Node.js to v22 (#22937 (#23078)
Upgrade Harbor UI to Angular 21, Clarity v18, and Node.js v22

- Upgrade the Harbor UI (src/portal) from Angular 16 to Angular 19 and subsequently to Angular 21.
- Upgrade VMware Clarity from v17 to v18, and Node.js from v20 to v22 (updated .nvmrc, CI.yml, Makefile, Dockerfile).
- Migrate Angular templates to the new @if/@for control flow syntax.
- Fix UI issues #1 through #35, including robot accounts, layout, dropdown overlay, and input styling.
- Fix unit tests: resolve NG0100 ExpressionChangedAfterItHasBeenCheckedError in policy.component.spec.ts, replace autoDetectChanges(true) with explicit detectChanges cycles, and use TestBed.overrideComponent to stub AddP2pPolicyComponent template.
- Fix Clarity v18 breaking changes: update dark-theme SCSS import, add cds-theme attribute for theming, update ClrDatagridStateInterface import path, add ClrIconModule to app module.
- Stabilize npm installs and resolve CI/CD pipeline hangs.
- Fix swagger-ui crash caused by React 19 createRoot removal:
  - swagger-ui 5.28+ resolves a nested react-dom@19 which removed createRoot
    from the main react-dom entry point (moved to react-dom/client). The
    swagger-ui-es-bundle-core.js still imports createRoot from react-dom,
    making it undefined and causing "TypeError: i is not a function" at render.
  - app-swagger-ui/webpack.prod.js: alias bare 'swagger-ui' import to
    swagger-ui-bundle.js (the standalone UMD build that ships with React 18
    already bundled), bypassing the broken external react-dom@19 entirely.
  - app-swagger-ui/package.json: add npm overrides to pin react and
    react-dom to ^18.3.1 so future npm installs do not re-introduce React 19.
  - angular.json: expose swagger-ui.bundle.js and swagger-ui-index.html
    from app-swagger-ui/dist as Angular dev-server assets, enabling the
    proxy to serve the locally built, fixed bundle during development.
- Convert eslint-plugin-header config from JSON to JS to apply the ESLint 9 schema fix at config-load time, removing the need for patch-package.
- Pin all dependency versions to exact installed versions from the lock file, and remove unused prettier-eslint package.
- Fix flake in P2pProviderService unit test by initializing date with 0 milliseconds to prevent cross-second duration calculation mismatches.

Signed-off-by: Ashish Patel <zoom2ashish@gmail.com>
Co-authored-by: stonezdj <stone.zhang@broadcom.com>
2026-06-09 15:16:20 +00:00
Vadim Bauer
2b29348cbd fix: publish goharbor/photon:5.0 as a multi-arch manifest (#23324) (#23334)
goharbor/photon:5.0 was built and pushed independently by both the amd64 and
arm64 BUILD_PACKAGE matrix jobs to the same tag, so whichever job finished last
overwrote the other and the published tag ended up single-arch ("sometimes
amd64, sometimes arm64", #23324).

Build it once as an amd64+arm64 manifest list in a dedicated BUILD_BASE_IMAGE
job that BUILD_PACKAGE depends on, and exclude goharbor/photon from the
component manifest list in CREATE_MANIFEST (it is published here and stays at
tag 5.0).

The db base image keeps the photon-snapshot repo (the stable Photon source) and
installs both postgresql15-server (old binaries at /usr/pgsql/15/bin, required
by pg_upgrade) and postgresql18-server (runtime), temporarily un-pinning the
snapshot to pull whichever major Photon has deprecated out of the current
snapshot per architecture (pg15 on amd64, pg18 on arm64). common/Dockerfile
keeps photon-snapshot and merges its setup into a single RUN.

Signed-off-by: Vadim Bauer <vb@container-registry.com>
2026-06-09 22:04:47 +08:00
Prasanth Baskar
a4b9d434b1 fix: use Photon updates repo for base images (#23316)
fix: support pg18 install on arm64

Signed-off-by: Prasanth Baskar <bupdprasanth@gmail.com>
2026-06-09 03:30:56 +00:00
Mandepudi Rani Chowdary
eb944bb199 fix: build valkey from source to support arm64 (#23282)
fix: support arm64 valkey build while preserving amd64 package path

- Keep amd64 behavior unchanged with tdnf install of valkey
- Isolate source-build fallback to arm64 only
- Verify source tarball with SHA256
- Move valkey version/checksum definition to root Makefile and pass as build args

Signed-off-by: ranimandepudi <ranichowdary.mandepudi@arm.com>
2026-06-02 08:17:10 +00:00
jUDASmILE
2f79ecceb5 remove install net-tools from db dockerfile as photon removed it (#23266)
remove install net-tools from db dockerfile as photon removed it from repo already

Signed-off-by: jUDASmILE <judasmile@gmail.com>
2026-05-21 03:23:50 +00:00
Wang Yan
bbe79cae65 bump pg to v18 (#23184)
currently harbor is using the pg 15, I will use this pull request to bump it to pg 18.

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
Co-authored-by: wang yan <yan-yw.wang@broadcom.com>
2026-05-21 10:32:06 +08:00
jUDASmILE
33b363c81b Rebuild goharbor/photon image before create new harbor base images (#23248)
* refresh goharbor photon:5.0 when create new base image

Signed-off-by: jUDASmILE <judasmile@gmail.com>

* correct date and format in buildbaselog

Signed-off-by: jUDASmILE <judasmile@gmail.com>

---------

Signed-off-by: jUDASmILE <judasmile@gmail.com>
2026-05-18 10:01:58 +00:00
Mandepudi Rani Chowdary
18f7abd8ed Full Multi-Architecture Enablement for Harbor (amd64 + arm64) (#22311)
Co-authored-by: Orlix <7236111+OrlinVasilev@users.noreply.github.com>
Co-authored-by: Vadim Bauer <vb@container-registry.com>
Co-authored-by: Vadim Bauer <Bauer.vadim@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: bupd <bupdprasanth@gmail.com>
2026-05-12 09:03:22 +02:00
stonezdj(Daojun Zhang)
729e277d69 Support custom PyPI index URL for prepare image builds (#23205)
build: support custom PyPI index URL for prepare image builds

Pass PIP_INDEX_URL through the make build chain as a Docker --build-arg,
mirroring the existing NPM_REGISTRY pattern for the portal build.

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
2026-05-08 02:23:40 +00:00
Chlins Zhang
88ab66244e feat: replace redis with valkey as cache backend (#23157)
Signed-off-by: chlins <chlins.zhang@gmail.com>
2026-04-28 14:59:43 +08:00
stonezdj(Daojun Zhang)
914738c3f1 Update artifact_accessory to add source column to identify accessory (#23144)
Add project_metadata config item proxy_referrer_api
   Rename getRemoteRepo to GetRemoteRepo

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
2026-04-24 08:11:28 +00:00
Anurag Ojha
4cedb8c0e2 fix(exporter): add Docker HEALTHCHECK (#22778)
* Add Docker HEALTHCHECK for harbor-exporter

Signed-off-by: intojhanurag <aojharaj2004@gmail.com>

* configurable port use

Signed-off-by: intojhanurag <aojharaj2004@gmail.com>

* add comment

Signed-off-by: intojhanurag <aojharaj2004@gmail.com>

---------

Signed-off-by: intojhanurag <aojharaj2004@gmail.com>
Co-authored-by: Chlins Zhang <chlins.zhang@gmail.com>
2026-04-22 04:06:19 +00:00
Wang Yan
b173fc3f0a fix db scheme migration issue (#22998)
we should not put the changes of v2.15.0 into the v2.14.1, create an 180 db scheme for v2.15.0

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
Co-authored-by: wang yan <yan-yw.wang@broadcom.com>
2026-03-16 17:00:57 +08:00
Wang Yan
6ab025c5bd add the 2.14.1 sql into main (#22947)
since we introduces a change on sql in the v2.14.1, it should be maintained the same version 171 in main, rather than adding the sql into the 180.

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
Co-authored-by: wang yan <yan-yw.wang@broadcom.com>
2026-03-06 14:51:19 +08:00
miner
2cbdacff87 update version for prepare migrate script (#22805)
Signed-off-by: my036811 <miner.yang@broadcom.com>
2026-02-03 16:50:27 +08:00
miner
56e9958e83 add prepare migration script for 2.15.0 (#22788)
Signed-off-by: my036811 <miner.yang@broadcom.com>
2026-01-30 15:28:02 +08:00
Quentin B.
aafc47d7fa add support for configure trivy db repository via harbor.yml (#21193)
Add support for trivy db_repository and java_db_repository

Signed-off-by: Quentin Bouteiller <quentin.bouteiller@values-associates.com>
Co-authored-by: Daniel Jiang <daniel.jiang@broadcom.com>
Co-authored-by: miner <miner.yang@broadcom.com>
2026-01-29 08:56:41 +00:00
stonezdj(Daojun Zhang)
e8d78eb110 Revert "Proxy the referrer's API to upstream registry" (#22779)
Revert "Proxy the referrer's API to upstream registry (#22746)"

This reverts commit 30ba1b3cd3.

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
2026-01-27 10:14:23 +00:00
stonezdj(Daojun Zhang)
30ba1b3cd3 Proxy the referrer's API to upstream registry (#22746)
Signed-off-by: stonezdj <stonezdj@gmail.com>
2026-01-26 08:00:54 +00:00
miner
a8343d3c7d support parse redis acl for registry config (#22770)
Signed-off-by: my036811 <miner.yang@broadcom.com>
2026-01-23 08:19:16 +00:00
Vadim Bauer
6606d184f5 fix(exporter): Export Harbor version via Prometheus exporter binary. (#22733)
fix(exporter): bake Harbor version into exporter binary at build time

Signed-off-by: Vadim Bauer <vb@container-registry.com>
2026-01-22 16:01:19 +08:00
Ikram ALOUI
e7f0333979 Add Cosign keyless signing for Harbor release artifacts (#22578)
* feat: implement keyless signing in release workflow

- Move signing from build to release workflow
- Use .sigstore.json naming convention (Sigstore standard)
- update signature verification documentation and readme file
- Update workflows to sign artifacts at release time only

Signed-off-by: Aloui-Ikram <ikram@container-registry.com>

* WIP: update release workflow and utils

Signed-off-by: Aloui-Ikram <ikram@container-registry.com>

* Add Cosign signing and fix accidental deletions

- Add Cosign signing to releases for security
- Revert to using getAssets function
- Restore latest installer uploads
- Restore pre-release comment

Signed-off-by: Aloui-Ikram <ikram@container-registry.com>

* Remove braces from variable names for consistency

Signed-off-by: Aloui-Ikram <ikram@container-registry.com>

* Remove unnecessary permissions from build-package.yml

Signed-off-by: Aloui-Ikram <ikram@container-registry.com>

---------

Signed-off-by: Aloui-Ikram <ikram@container-registry.com>
Co-authored-by: Aloui-Ikram <ikram@container-registry.com>
Co-authored-by: Daniel Jiang <daniel.jiang@broadcom.com>
2026-01-13 09:47:28 +00:00
Wang Yan
7f5ac5b57b add per-endpoint CA certificate support for registry endpoints (#22535)
* add per-endpoint CA certificate support for registry endpoints

fixes #22203

Allowing Harbor to trust self-signed or private CA certificates for individual registry endpoints without modifying the system-level trust store.

1. Database schema changes, API updates with PEM validation.
2. HTTP transport layer modifications across all the registry adapters.
3. UI field to fill in the certificate.

The feature is backward compatible - existing installations using system-level CA trust will continue to work without any changes.

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* resolve lint failures

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* add i18n changes

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* resolve review comments

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* make the input as non-required and updates i18n

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

* resolve comments

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>

---------

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
Co-authored-by: wang yan <yan-yw.wang@broadcom.com>
2026-01-13 17:10:22 +08:00
Wang Yan
c305a80616 refactor the logic to init skip_audit_log_database (#22493)
simplify the sql to set the value of skip_audit_log_database, any evidence of previous usage of db to record the audit, set it to false.

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
Co-authored-by: wang yan <yan-yw.wang@broadcom.com>
2025-10-24 10:22:38 +00:00
Wang Yan
c878bbf98f add migraiton sql for skip_audit_log_database (#22487)
give the value of skip_audit_log_database bases on the real usage.

1. If audit logs exist in the system (either in audit_log or audit_log_ext tables),
   set skip_audit_log_database to false
2. If no audit logs exist but the tables show evidence of previous usage
   set skip_audit_log_database to false

Signed-off-by: wang yan <yan-yw.wang@broadcom.com>
Co-authored-by: wang yan <yan-yw.wang@broadcom.com>
2025-10-23 07:19:23 +00:00
Max Fröhlich
26b61390a0 Remove unused SYNC_QUOTA from env.jinja template (#22280)
Remove SYNC_QUOTA from env.jinja template

`SYNC_QUOTA` is not used throughout the whole code.

It looks like the feature using it was removed.

Signed-off-by: Max Fröhlich <maxbruchmann@gmail.com>
Co-authored-by: Wang Yan <wangyan@vmware.com>
2025-09-01 16:31:56 +08:00
miner
e80b940942 add prepare migration script for 2.14.0 (#22247)
Signed-off-by: my036811 <miner.yang@broadcom.com>
2025-08-13 08:38:27 +00:00
Prasanth Baskar
221037378a feat: Single Active Replication (#21347)
feat(replication): add Single Active Replication per policy

* Added single_active_replication field to schema & DB table
* Updated API, controller & handler to enforce single execution per policy
* Added checkbox in UI to enable/disable single_active_replication for a
  policy
* Implemented necessary backend & frontend tests
* Prevents parallel runs per policy if single_active_replication is enabled

Signed-off-by: bupd <bupdprasanth@gmail.com>
2025-08-11 18:02:56 +08:00
Wang Yan
9f809f17ba update the support list of proxy cache (#22237)
According to PR #22198, some inactive adapters have been removed from the default adapter list.
This pull request updates PERMITTED_REGISTRY_TYPES_FOR_PROXY_CACHE accordingly, since the list of proxy cache adapters should be a subset of the replication adapters.

Signed-off-by: wy65701436 <wangyan@vmware.com>
2025-08-11 08:20:31 +00:00
Wang Yan
de657686b3 add the replicaiton adapter whitelist (#22198)
fixes #21925

According to https://github.com/goharbor/harbor/wiki/Harbor-Replicaiton-Adapter-Owner, some replication adapters are no longer actively maintained by the Harbor community. To address this, a whitelist environment variable is introduced to define the list of actively supported adapters, which will be used by the Harbor portal and API to display and allow usage.

If you still wish to view and use the unsupported or inactive adapters, you must manually update the whitelist and include the desired adapter names. For the list of adapter names, refer to https://github.com/goharbor/harbor/blob/main/src/pkg/reg/model/registry.go#L22

Signed-off-by: wang yan <wangyan@vmware.com>
2025-07-23 10:25:21 +00:00
stonezdj(Daojun Zhang)
ebdfb547ba Set MAX_JOB_DURATION_SECONDS from jobservice config.yml (#22116)
Signed-off-by: stonezdj <stone.zhang@broadcom.com>
2025-07-18 10:01:18 +00:00
Daniel Jiang
19f4958ec3 Add "status" of CVEs to artfact scan report (#22177)
This commit adds the field "status" to the struct of a vulnerability and adds
column "status" to vulnerability record table.  It makes sure the statuses
of CVEs returned by trivy scanner are persisted and can be returned via
the vulnerabilities addition API of an artifact.

Signed-off-by: Daniel Jiang <daniel.jiang@broadcom.com>
2025-07-16 11:11:40 +08:00
miner
2565491758 add BUILD_INSTALLER parameter for optionally build prepare and log container (#22148)
add BUILD_INSTALLER parameter to optionally build prepare and log container only when we need to build offline_installer

Signed-off-by: my036811 <miner.yang@broadcom.com>
2025-07-03 18:23:17 +08:00