1556 Commits

Author SHA1 Message Date
Vishwas Rajashekar c18a4a975d fix(authz): metrics: deny authenticated users not in ACL even with anonymous read (#4131)
* fix(authz): metrics: reject users not in list even with anonymous read

Even when anonymous reads are enabled for metrics, users not in the
allowed list should not be allowed.

This change also refactors the MetricsAuthzHandler to align better
with this logic.

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>

* fix(authz): address review comments

Address comments to pass username when present
to AuthzFail if user is not allowed for metrics.
This changes the response to Forbidden instead of
Unauthorized.

Use isAnonymous() check instead of only checking for
empty username.

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>

* fix(authz): fix additional review comments

Fix a few more review comments

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>

---------

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>
2026-06-14 17:29:22 +03:00
Vishwas Rajashekar 6a143cadfa feat: config: validate metrics config (#4130)
This change adds validation for metrics config.
In particular, the metrics path is checked to
ensure it starts with a / and is not one of the
disallowed paths.

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>
2026-06-14 16:00:03 +03:00
Ramkumar Chinchani 225e2fb96d chore: fix dependabot alerts (#4126)
* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix: bump zui version

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-06-11 17:22:15 -07:00
Janko Thyson a675ac96b9 fix(storage): treat dedupe-candidate cache miss as no candidates, not an error (#4122)
GetAllDedupeReposCandidates propagated zerr.ErrCacheMiss from the cache's
GetAllBlobs verbatim. But a cache miss is the normal case for a not-yet-cached
blob — the first push of a new blob, or a cross-repo mount check during a push
— and semantically means "no dedupe/mount candidates", not a failure.

Propagating it caused canMount (used by the CheckBlob and CreateBlobUpload
handlers) to surface the error, which the route handlers log as an
"unexpected error". With remote (e.g. S3) storage a cache is always present
(dedupe:false does not disable it), so this logs an error-level line for every
fresh blob digest on every push — significant log spam during bulk pushes and
cross-repo mounts, with no functional impact (the push still succeeds via a
normal upload).

Handle ErrCacheMiss the same way as the existing nil-cache branch above:
return no candidates and no error.

Signed-off-by: Janko Thyson <janko@kaosmaps.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 10:24:52 +03:00
uaggarwa 66e9cfb01f feat(metrics): anonymous access when enabled in accessControl config (#4110)
* feat: add anonymouspolicy support in metrics

Signed-off-by: uaggarwa <uaggarwa@akamai.com>

* test: add unit tests

Signed-off-by: uaggarwa <uaggarwa@akamai.com>

---------

Signed-off-by: uaggarwa <uaggarwa@akamai.com>
2026-06-10 10:19:28 +03:00
Jacob McSwain 273b15364b metadb: add optional fast restart path that skips storage walk when (version + commit + storage config) matches metaDB stamp (#4026)
* chore(metadb): add writer version to interface

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* chore(metadb): add writer version to db mock

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* chore(metadb): implement writer version for bolt, redis, and dynamodb

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* feat(metadb): add optional fast restart path that skips storage walk when binary identity matches metaDB stamp

binary identity is determined by the current release tag/commit and stored in metaDB after a successful storage parse. When fast restart is enabled, the next startup will skip the parse if the stored identity matches the current binary

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* chore(cli): serve: add a way to force reparse storage

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* refactor(meta): version: split to avoid global state mutation in tests

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* fix(meta): version: include commit in writerVersion to distinguish retags

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* chore(config): add IsFastRestartEnabled() test

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* fix(meta): skip writer-version stamp when storage parse is incomplete

ParseStorage returns nil even when individual repos fail to parse or are only partially parsed (a missing manifest blob), so MaybeParseStorage would stamp a partially-populated metaDB as good. On the next restart fastRestart trusts the stamp, skips the storage walk, and never recovers.

Track per-repo outcomes via parseStats and stamp only when the walk fully populated the metaDB, otherwise log and continue so the next restart reparses

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* fix(docs): readme: remove trailing comma from JSON config

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* fix(meta): dynamodb: use context.Background instead of context.TODO

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* fix(meta): invalidate fast restart on storage config changes

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* chore(meta): dynamodb: use context.Background() instead of context.TODO()

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* docs(meta): dynamodb: add comment about nil AttributeValue handling in GetWriterVersion

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* chore: rename writer-version stamp to fast-restart stamp

also replaces the version/commit tracking to use BinaryVersion instead of WriterVersion

This should make things more clear

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* fix(config): ensure FastRestart is on GlobalStorageConfig

This is not a per-subpath setting

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

* fix(metadb): redis: tests: ensure clients are closed

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>

---------

Signed-off-by: Jacob McSwain <jacob@mcswain.dev>
2026-06-09 10:47:20 -07:00
Andrei Aaron d480380ef7 ci: Update GH runner labels (#4121)
* ci: migrate workflows off deprecated oracle-vm runners

Switch CI jobs from oracle-vm-* runner labels to cncf-ubuntu-* as the oracle-cm-* CNCF runner labels are deprecated.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>

* ci: increase resources available for ecosystem tools tests

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>

---------

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-06-09 12:46:21 +03:00
Andrei Aaron 1dc5c8e51d fix: skip DynamoDB table creation when tables exist (#4120)
Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-06-07 18:56:30 -07:00
Ramkumar Chinchani 879fcee3c3 feat: enhance config sanitization to mask sensitive keys in storage a… (#4119)
* feat: enhance config sanitization to mask sensitive keys in storage and session drivers

Fixes issue #4117

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix: annotate test fixture tokens to suppress security linter warnings

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix: update test fixture credentials to suppress security linter warnings

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix: simplify slice value sanitization by removing unnecessary index handling

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix: update RedisDB test to use a guaranteed-invalid endpoint for CI stability

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix: update sanitization logic to handle empty credentials for event sinks

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix: format sensitive config map keys for improved readability

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-06-06 22:18:20 -07:00
charles-openclaw 3ff9d6ddc1 fix(cve): prefer cve.org links for AVD references (#4107)
Signed-off-by: Charles <charles-openclaw@9bcfae.inboxapi.ai>
2026-06-06 07:10:37 +03:00
Ramkumar Chinchani e8c38a5639 chore: fix dependabot alerts (#4113)
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-06-05 15:12:32 +03:00
yosinn1-blip 2261151508 docs: fix alongside spelling in search docs (#4095)
Signed-off-by: Yoshiki <yosinn1@gmail.com>
2026-05-31 22:53:06 +03:00
Ramkumar Chinchani a2d738c575 fix: miscellaneous fixes for ai-reported suggestions (#4101)
* test(cli): replace panic with t.Fatalf in deprecated config tests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(trivy): keep sbom generation failures non-fatal in runTrivy

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* docs(meta): fix typos in hooks comments

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* refactor(requestcontext): align package name and godoc comments

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* test(gc): factor metrics setup helper and fix typo

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* test(trivy): cover non-fatal SBOM generation failures

- add runTrivy test ensuring scan succeeds when SBOM generation fails

- inject artifact runner constructor for deterministic internal testing

- fix matchesRepo doc comment to be action-agnostic

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-26 14:58:30 -07:00
Ramkumar Chinchani 4e4d00a0a6 feat: add trivy-based sbom artifact generation support (#4088)
fixes issue #4067

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-23 23:24:12 -07:00
Ramkumar Chinchani d8fb19819b chore: fix dependabot alerts (#4091)
* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-22 22:20:08 -07:00
Ramkumar Chinchani a4c55e288c chore: fix dependabot alerts (#4082)
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-21 08:50:48 -07:00
Ramkumar Chinchani 08b26876da chore: bump zui version (#4074)
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
v2.1.17
2026-05-17 22:21:26 -07:00
Ramkumar Chinchani 555a35d3dc chore: fix dependabot alerts (#4072)
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-16 23:33:48 -07:00
Benoit Tigeot 6c1f1bdd40 feat(metrics): add Prometheus GC metrics (#3863)
* feat(metrics): add Prometheus GC metrics

Track garbage collection activity with three new metrics:
- zot_gc_runs_total (counter, label: error) — GC run count
- zot_gc_duration_seconds (summary) — GC run duration
- zot_gc_deleted_total (counter, label: type) — items deleted
  by type: blob, manifest, upload

MetricServer is added to GarbageCollect and wired through
all callers (controller, verify-feature retention, tests).

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* fix(test): add missing metrics var in GCS GC tests

TestGCSGarbageCollectImageIndex and
TestGCSGarbageCollectChainedImageIndexes were missing the
metrics variable required by NewGarbageCollect after the
MetricServer parameter was added.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* fix(test): add defer metrics.Stop() in GC tests

Prevent goroutine/port leaks by stopping MetricsServer in
storage_test.go (3 functions) and gcs_test.go (also add
missing metrics declaration in TestGCSGarbageCollectImageManifest).

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* fix(test): cover `CleanRepo` error path

Add test that exercises the error branch in
`CleanRepo` where `cleanRepo` fails, covering
the metrics calls and log lines flagged by Codecov.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* test: Cover GC error paths for codecov

Add three tests in gc_internal_test.go to cover previously
untested error branches in `removeBlobUploads` and
`removeUnreferencedBlobs`: `ListBlobUploads` failure,
`addIndexBlobsToReferences` failure, and `PathNotFoundError`
from `GetAllBlobs`.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* test(gc): cover remaining error paths

Cover `StatBlobUpload`, `digest.Validate()`,
`isBlobOlderThan`, and `CleanupRepo` error branches
in `removeBlobUploads` and `removeUnreferencedBlobs`.

`removeUnreferencedBlobs` now at 100% coverage,
`removeBlobUploads` from 78.3% to 91.3%.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* test: cover `sanityChecks` label name mismatch

Try to avoid -0.09% coverage regression on `minimal.go`
by exercising the uncovered branch in `sanityChecks`
where label names have correct count but wrong values.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* test(gc): exercise real GC path in metrics test

TestGCMetrics was calling metric helpers directly instead of
running actual garbage collection, so it couldn't catch wiring
regressions where `CleanRepo` stops recording metrics.

Now uploads an orphaned blob and runs `gc.CleanRepo` end-to-end,
verifying metrics appear on the Prometheus endpoint.

Suggestion from Copilot: https://github.com/project-zot/zot/pull/3863#discussion_r3129324719

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* fix(gc): skip deletion metrics when DryRun is enabled

https://github.com/project-zot/zot/pull/3863#discussion_r3129324684

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* fix(test): stop leaked MetricsServer goroutines in GCS tests

https://github.com/project-zot/zot/pull/3863#discussion_r3129324657

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* refactor(test): drop unnecessary zlog import alias

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* fix(monitoring): expose metric types outside build tag

`MetricsCopy` and related types were only visible under `\!metrics`,
causing a typecheck failure when golangci-lint runs with `-tags metrics`.
Moving the type definitions to `common.go` makes them unconditionally available.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* fix(monitoring): remove extra blank line for gci

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* test(gc): cover both dry-run and real deletion metrics

And fix issue with build tag with metrics

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* Satisfy testpackage linter for gc metrics test

The `testpackage` linter allows `package gc` only in files named
`*_internal_test.go`; rename to follow that convention.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

---------

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
2026-05-16 23:03:36 -07:00
Benoit Tigeot 4d6bf18825 fix(lint): silence deprecated gomodguard linter warning (#4070)
Remove warning:

```
WARN The linter 'gomodguard' is deprecated (since v2.12.0) due to: new major version. Replaced by gomodguard_v2.
WARN Suggested new configuration:
linters:
  enable:
    - gomodguard_v2
```

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
2026-05-16 11:46:40 -07:00
Ramkumar Chinchani 5087d725e6 chore: fix dependabot alerts (#4059) 2026-05-12 10:50:02 +03:00
Ramkumar Chinchani b272e0994e fix: downgrade expected missing-blob HEAD logging from error to debug (#4056)
Fixes issue #4044

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-11 21:25:44 -07:00
Ramkumar Chinchani 9aff5b8d08 chore: fix dependabot alerts (#4048)
* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix golangci-lint findings from CI

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix golangci-lint gosec warnings

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update code to use slices package and address gosec linting issues

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* build: fix makefile target

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests and add gosec annotations

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: bump zui version

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update test helpers and improve security settings in tests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: add gosec linting directive for test path construction

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-11 09:29:05 +03:00
Andrei Aaron 9757f7cf41 ci: fix golangci-lint install URL (#4052)
1. Cause
SBOM assets were added to the release checksum file, so you get two lines that contain the same substring, e.g. …linux-amd64.tar.gz and …linux-amd64.tar.gz.sbom.json.
The old install.sh logic used something like grep "${BASENAME}", so both lines matched. That breaks want (wrong or ambiguous hash) and shows up as checksum verification errors (including the 8df… vs fd3… style mismatch you debugged).

2. The upstream fix is in https://github.com/golangci/golangci-lint/pull/6539
The matcher was changed so the checksum line must end with the archive name — i.e. grep "${BASENAME}$" — so the .sbom.json line no longer matches.

3. In the same thread they say master on raw.githubusercontent.com is not the right branch anymore and recommend the canonical installer URL:
https://golangci-lint.run/install.sh
(see the PR description and local install / binaries.)

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-10 20:35:59 +03:00
Andrei Aaron 5d323c4dd5 ci: sync go 1.26 images to ghcr.io/project-zot/golang (#4049)
Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-10 08:23:06 +03:00
Matheus Pimenta 8a6674f198 feat(authz): introduce conditional access control via CEL (#4040) 2026-05-09 22:43:00 +03:00
Andrei Aaron ddb6279a25 fix(zli config): print help for missing args (#4046)
Make `zli config` and config subcommands show usage/help when invoked with
missing required args, instead of Cobra’s generic “accepts N arg(s)” errors.

Example:
- before: `zli config add` -> `Error: accepts 2 arg(s), received 0`
- after:  `zli config add` prints `zli config add <config-name> <url>` usage/help1~fix(zli config): print help for missing args

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-08 23:22:15 +03:00
Andrei Aaron c7ddbe2e36 feat(zli): add config list/show/get/set/reset and isolate deprecated syntax (#4037)
* feat(zli): add config list/show/get/set/reset and isolate deprecated syntax

Introduce first-class subcommands for listing profiles, showing a profile,
getting and setting keys, and resetting optional keys (alongside existing add/remove).
The parent command now resolves ~/.zot via zliUserConfigPath(),
documents that profile names must not clash with subcommand names,
and states that positional/--list/--reset usage is deprecated and will be removed soon.

Legacy behavior is delegated to config_cmd_deprecated.go with stderr warnings for old flags and positional get/set.
Examples and inline help point users at the new commands.
FormatNames/FormatListedVars comments reference config list/show.

Tests are split so config_cmd_test.go exercises the supported subcommands
while config_cmd_deprecated_test.go retains coverage for the deprecated
paths under renamed TestConfigCmdDeprecated* entries.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>

* test: stabilize retention check tests

See https://github.com/project-zot/zot/actions/runs/25361779632/job/74362802944?pr=4037

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>

---------

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-08 20:19:26 +03:00
Andrei Aaron b89d10834c refactor(build): move build metadata to pkg/buildinfo (#4045)
Keep CLI binaries from importing pkg/api/config just for version strings by
centralizing Commit/ReleaseTag/BinaryType/GoVersion in a tiny buildinfo package.
Update ldflags targets and callers accordingly.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-08 19:37:04 +03:00
Andrei Aaron fa92366009 refactor(zli): add typed ~/.zot config layer and strict validation (#4030)
feat(cli): add typed ~/.zot config layer and strict validation

Introduce pkg/cli/client/config.go with ZliConfigFile/ZliConfig and
ReadZliConfigFile, replacing the loose map[string]any load/save path in
config_cmd.go.

Parsing now rejects malformed JSON with ErrCliBadConfig and requires a
non-null configs array (ErrCliMissingConfigsField when wrapped). Each
profile must have non-empty _name and url.

Config commands delegate to typed helpers (Find, AddEntry, RemoveEntry,
GetVar/SetVar/ResetVar, FormatNames, WriteFile). Fresh or minimal files
still behave as empty via isFreshCliRead (ErrEmptyJSON or missing configs).

Tests: prefer t.Setenv("HOME", t.TempDir()) where CLI resolution uses --url
only; align CVE/client/search tests with mandatory profile URL and HOME
isolation.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-05 08:52:59 +03:00
Andrei Aaron 7ec34a9520 feat(api): log session/audit subject from UserAccessControl (#4029)
Read identity from request context after handlers run so Basic, Bearer,
OIDC, mTLS, etc. are covered; use subject "anonymous" when unset.
Redact Authorization in SessionLogger without decoding credentials.
Add session_test.go for SessionLogger and SessionAuditLogger.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-01 09:35:22 -07:00
Andrei Aaron fa2960b705 fix(auth): refine OIDC identity handling and claim-mapping logs (#4028)
Rename getOpenIDUsername to getOpenIDIdentity and thread "identity"
through bearer OIDC, Basic-auth parsing, OAuth2Callback, and log fields.

Only fall back (and warn) to the default email claim when the configured
username claim is non-default but missing or empty.

Stop emitting Info logs when groups are absent on only UserInfo or only ID
token claims; log once at Debug when no groups remain after merging both.

Update ClaimMapping docs to mention username and groups claims; fix mTLS
extractIdentity comment typo; clarify GetAuthUserFromRequestSession doc.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-01 09:34:48 -07:00
Andrei Aaron 8f27949dcb test: refactor countingReader into partialReaderOpenTracker and partialReaderReadCloser (#4027)
countingReader was not respecting the single responsibility principle
and the implementation was hard to understand

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-05-01 13:51:24 +03:00
Akash Kumar cb9d682a69 feat(auth): map OpenID groups claim (#3999)
* feat(auth): map OpenID groups claim

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* fix(auth): refine OIDC claim mapping logs

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* refactor(auth): collapse OIDC username fallback into nested if

Reuse the empty-username branch for the email fallback so the value is
checked once and the failure path lives next to the recovery attempt.

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* refactor(auth): consolidate OIDC claim extraction into authn.go

Move getOpenIDClaimMapping, getOpenIDUsername, and appendOpenIDGroups
out of routes.go into authn.go alongside a new extractOpenIDIdentity
helper that owns the username/groups extraction flow. This keeps the
HTTP callback in routes.go thin and groups OIDC plumbing with the rest
of the authentication code.

Also:
- Filter nil and empty entries consistently across the []any, []string,
  and string branches of appendOpenIDGroups, with new test cases
  covering []any{nil, ""} and []string{"admin","",...}.
- Surface a Warn log when an operator-configured username claim is
  missing/empty so the fallback to email isn't silent.
- Rename openid_claim_mapping_internal_test.go to authn_internal_test.go
  and drop the build tags that aren't needed for the internal tests.

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

---------

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
2026-05-01 11:59:51 +03:00
Ramkumar Chinchani 0b2eaa0f9a feat(cosign): add support for cosign bundle (#4023)
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-05-01 10:21:06 +03:00
Akash Kumar 993a17f5d0 docs(config): reference generated config schema (#4015)
- document `zot schema` as the generated JSON Schema reference for
  configuration files
- add a top-level configuration map to help users discover the major
  config sections before reading examples

Fixes #2967

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
2026-04-28 09:29:46 +03:00
Andrei Aaron 1a1f84d184 Multipart download enhancements (#4021)
* fix(api): set blob response Content-Type from OCI descriptor

Blob HEAD responses had no Content-Type and GET responses echoed the
request's Accept header verbatim, which produced missing or malformed
media types and left multipart/byteranges parts without a per-part
Content-Type. This breaks OCI distribution-spec conformance and
consumers like stargz-snapshotter that need a well-formed layer media
type.

Add a blobResponseMediaType helper that resolves the descriptor's
MediaType via GetBlobDescriptorFromRepo and falls back to
application/octet-stream. Use it in CheckBlob (HEAD), GetBlob full
(200), GetBlob single-range (206), and per-part in
writeMultipartRanges (206 multipart). Lookup is deferred until after
the blob is known to exist.

Cover the new behaviour with mock-based unit tests in routes_test.go
and end-to-end assertions in TestPullRange.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>

* perf(api): stream multipart blob ranges lazily with precomputed Content-Length

writeMultipartRanges previously opened every range reader up front
and emitted no Content-Length, so an N-range request held N
concurrent storage readers (and their fds / read buffers) per
response window and forced chunked encoding on HTTP/1.1 — neither
friendly to proxies nor to fan-out scenarios like stargz lazy pulls.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>

---------

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-04-28 08:43:15 +03:00
Akash Kumar bb5b77aeaa fix(sync): apply tag filters before destination mapping (#4003)
* fix(sync): apply tag filters before destination mapping

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* fix(sync): return stable pointer from getContentByUpstreamRepo

Iterate by index and return &cm.contents[i] so callers get the slice
element rather than a copy of the loop variable, matching the existing
GetContentByLocalRepo helper.

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

---------

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
2026-04-27 08:27:46 +03:00
Akash Kumar 9e13be8b61 fix(api): support multipart range blob pulls (#3995)
* fix(api): support multipart range blob pulls

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* fix(api): tighten multipart range response

- Drop the redundant deferred closeRangeReaders; the deferred cleanup
  registered when the slice is created already covers all paths.
- Stop copying the request Accept header into each multipart part's
  Content-Type. Accept can be a list of media ranges (e.g.
  "application/octet-stream,*/*"), which is not a valid Content-Type and
  may confuse multipart parsers. RFC 9110 lets us omit it entirely.
- Set Docker-Content-Digest on the partial-content response so range
  pulls expose the same header as a full GET.
- Drop the over-broad build tag on routes_internal_test.go; the parser
  unit test does not need any extension build tags.

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

---------

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
2026-04-27 08:17:08 +03:00
Ramkumar Chinchani 113c4819ec chore: fix dependabot alerts (#4020)
* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: bump zui version

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-04-26 21:52:54 -07:00
Akash Kumar 8905b48bb7 fix(zli): Improve zli CVE diff output (#3994)
* fix(cli): improve zli CVE diff output

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* test(api): avoid TestRoutes port collision

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* test(cli): cover CVE diff formatting helpers

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

* test(search): remove redundant test case copy

Signed-off-by: Akash Kumar <meakash7902@gmail.com>

---------

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
2026-04-26 22:25:10 +03:00
Ramkumar Chinchani 934b22d124 fix(security): enhance timeout configurations and body size limits fo… (#3984)
* fix(security): enhance timeout configurations and body size limits for HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(tests): refactor backend result handling in proxyHTTPRequest test

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): preserve ContentLength in proxied requests to prevent server hang

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): preserve explicit zero-length request bodies in proxyHTTPRequest
fix(tests): add test for normalizedTimeout function to ensure default fallback

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): prevent default HTTP timeout values from being set unless explicitly configured

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): refactor timeout handling to use explicit checks for nil and non-positive values

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(tests): add wait_for_event_count function to ensure expected event generation

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): improve timeout handling and update error responses for large requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): enhance HTTP timeout handling with explicit accessors and default values

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): increase default API key body size and timeout values for improved performance

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): unify timeout handling by replacing specific read/write timeouts with a single default timeout

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): consolidate HTTP timeout accessors and enhance timeout handling

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): simplify HTTP timeout accessors and set default values for read/write timeouts

Co-authored-by: Copilot <copilot@github.com>
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
2026-04-26 22:23:48 +03:00
Nikita Vakula 8282aef12b feat(auth): support OIDC RP-Initiated Logout (#3975)
POST /zot/auth/logout now returns an endSessionUrl in the JSON
response body when the session was established via an OIDC provider
whose discovery document advertises an endSessionEndpoint, so the
UI can navigate the browser to it and terminate the session at the
IdP in addition to clearing the local cookie.

- The OIDC callback records the provider name in the session after
  login; the github OAuth2 path is untouched.
- end_session_endpoint is read from the zitadel/oidc RelyingParty
  and validated as an absolute http(s) URL.
- post_logout_redirect_uri prefers http.externalUrl when set and
  falls back to deriving the origin from the incoming request.
- No id_token_hint is sent; client_id identifies the RP, so the
  ID token does not need to be persisted.
- Non-OIDC sessions (local/basic/LDAP/GitHub) retain the existing
  200 OK, no body behavior.

Operators must register the URI zot sends as a valid post-logout
redirect URI on the IdP client.

Ref: https://openid.net/specs/openid-connect-rpinitiated-1_0.html

Signed-off-by: Nikita Vakula <programmistov.programmist@gmail.com>
2026-04-25 23:19:29 +03:00
Ramkumar Chinchani 8bec9b365e chore: fix dependabot alerts (#3990)
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-04-25 09:09:59 +03:00
Marco 0eafaeb043 fix(api): recognize Docker Compose/Buildx User-Agent in v2 challenge workaround (#3992)
Docker Compose and Buildx proxy through the Docker daemon, which sends
a User-Agent starting with "docker/<version>" rather than the
"Docker-Client/<version>" string sent by direct Docker CLI pulls.
This caused compose/buildx pulls to skip the 401 challenge on
registries with mixed anonymous/authenticated access policies,
resulting in 'unauthorized' errors.

Add strings.HasPrefix(ua, "docker/") alongside the existing
Docker-Client check so daemon-proxied requests from any upstream
tool (compose, buildx, etc.) are handled correctly.

Fixes #3991
2026-04-25 08:58:22 +03:00
Vishwas Rajashekar 97b65b5b39 feat(zb): Support for TTFB measurement + on-demand sync tests (#3929)
feat(zb): support for measuring TTFB + sync tests

Adds supports for measuring time to first byte (TTFB)
for Pull tests for the manifest check, the manifest get,
the config get, and the blob get.

Additionally, this introduces 2 new sync tests which measure
the performance of on-demand sync.

Setup code has been refactored to accomodate a new
blob size of 1GB.

Parts of zb have been refactored to address linter errors.

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>
2026-04-24 09:03:11 -07:00
Andrei Aaron 9ba59559d2 fix(api): return 416 for bad upload range on PUT; fix GET upload Range at size zero (#3983)
Align closing blob upload (PUT) with the OCI Distribution Spec: invalid /
out-of-order upload ranges (ErrBadUploadRange) return 416 Requested Range Not
Satisfiable instead of 400, for both the final-chunk PutBlobChunk path and
FinishBlobUpload.

GetBlobUpload (GET upload status): fix the Range response when zero bytes have
been received—send Range: 0-0 instead of Range: 0--1, consistent with a new
session and the spec’s Location + Range upload status shape. Only map
ErrBadBlobDigest to 400 here; do not handle ErrBadUploadRange on GET (that
request carries no range; ImageStore.GetBlobUpload does not return it).

Document PUT upload failures 400 and 416 in swagger; regenerate swagger
artifacts. Update route tests (expect 416 on UpdateBlobUpload for
ErrBadUploadRange), drop the mock-only GetBlobUpload+ErrBadUploadRange case,
and assert Range: 0-0 in TestPullRange after GET on a new upload location.

Fix potential panic when parsing Content-Range (index out of range)
when accessing `tokens[0]`.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2026-04-20 08:24:36 +03:00
Ramkumar Chinchani b47b643e05 fix(security): remove InsecureSkipVerify from metrics client (TLS-1) (#3982)
* fix(security): remove InsecureSkipVerify from metrics client (TLS-1)

Replace the unconditional InsecureSkipVerify: true TLS config in
newHTTPMetricsClient with the system cert pool (+ TLS 1.2 minimum).

Add an optional CACert field to MetricsConfig and to the exporter
ServerConfig so operators running zot with a self-signed or private
CA can point the exporter at the correct CA file instead of
disabling certificate verification entirely.

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* feat(metrics): add HTTPS configuration for metrics exporter

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): enhance CA certificate handling in metrics client and add tests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(security): improve CA certificate error handling in metrics client and update tests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(tests): correct package name in minimal_client_test.go and simplify error declaration

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* fix(tests): update package name in minimal_client_test.go for consistency

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
v2.1.16
2026-04-19 08:57:24 +03:00
Ramkumar Chinchani bfc59ad120 security: suppress Allow-Credentials on wildcard CORS origin (CORS-1) (#3980)
fix(security): suppress Allow-Credentials on wildcard CORS origin (CORS-1)

Per CORS spec §3.2, Access-Control-Allow-Credentials must not be
"true" when Access-Control-Allow-Origin is the wildcard "*".

ACHeadersMiddleware (pkg/common/http_server.go) and
getUIHeadersHandler (pkg/api/routes.go) now only emit the
credentials header when an explicit, non-empty AllowOrigin is
configured.  Deployments that leave AllowOrigin blank (default
wildcard) no longer produce a contradictory header pair.

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-04-18 21:14:52 +03:00
Ramkumar Chinchani eadc9b65ed fix(security): limit API key creation body to 4 KiB (INPUT-2) (#3978)
Wrap req.Body with http.MaxBytesReader before io.ReadAll in
CreateAPIKey. Requests with bodies larger than MaxAPIKeyBodySize
(4 KiB) now return HTTP 413 instead of buffering arbitrary data.

Add the MaxAPIKeyBodySize constant, update the Swagger @Failure
annotation to document 413, and add a unit test.

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
2026-04-18 20:39:08 +03:00