countingReader was not respecting the single responsibility principle
and the implementation was hard to understand
Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
* 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>
* 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>
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>
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>
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>
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>
Wrap request.Body with http.MaxBytesReader before io.ReadAll in
UpdateManifest. Bodies exceeding MaxManifestBodySize (4 MiB) now
return HTTP 413 with a MANIFEST_INVALID error body instead of
buffering unlimited data into memory.
Add the MaxManifestBodySize constant and a unit test that sends an
oversized body and asserts the 413 status.
Agent-Logs-Url: https://github.com/project-zot/zot/sessions/5eca86eb-9749-4cf8-9fb8-7b9ace2ba87f
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
Replace MakeTempFile usage with MakeTempFilePath and MakeTempFileWithContent
helpers that automatically handle file lifecycle. This prevents resource
leaks by ensuring temporary files are properly closed.
Shoudld also make the tests easier to read.
Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
feat: add support for sha256 and sha512 htpasswd formats
Fixes issue #3495
We currently support only bcrypt htpasswd hashes, however bcrypt is not
FIPS-140 approved since it uses Blowfish.
This PR adds support for sha256 and sha512 formats and enforces that
bcrypt be disabled when fips140 mode is enabled.
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
* fix: migrate to Go module v2 for proper semantic versioning
This change updates the module path from 'zotregistry.dev/zot' to
'zotregistry.dev/zot/v2' to comply with Go's semantic versioning rules.
According to Go's module versioning requirements, major version v2+
must include the major version in the module path. The current
module path 'zotregistry.dev/zot' only supports v0.x.x and v1.x.x
versions, making existing v2.x.x tags (like v2.1.8) unusable.
Changes:
- Updated go.mod module path to zotregistry.dev/zot/v2
- Updated all internal import paths across 280+ Go source files
- Updated configuration files (golangcilint.yaml, gqlgen.yml)
- Updated README.md Go reference badge
This fix enables proper use of existing v2.x.x Git tags and allows
external packages to import zot v2+ versions without compatibility
errors.
Resolves: Go module import compatibility for v2+ versions
Fixes: #3071
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
* fix: regenerate GraphQL files with updated v2 import paths
The gqlgen tool needs to regenerate the GraphQL schema files after
the module path change to use the new v2 imports.
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
---------
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
* fix: migrate from github.com/rs/zerolog to golang-native log/slog
We have been using zerolog for a really long time.
golang now has structured logging using slog.
Best to move to this in interests of long-term support.
This is a tech debt item.
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
* fix: a few changes on top
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
* fix: address comments
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
---------
Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
* fix: get groups claim from idtokenclaims
Signed-off-by: Philipp Lange <ph.lange@pm.me>
* fix: lint
Signed-off-by: Philipp Lange <ph.lange@pm.me>
---------
Signed-off-by: Philipp Lange <ph.lange@pm.me>
Which could be imported independently. See more details:
1. "zotregistry.io/zot/pkg/test/common" - currently used as
tcommon "zotregistry.io/zot/pkg/test/common" - inside pkg/test
test "zotregistry.io/zot/pkg/test/common" - in tests
. "zotregistry.io/zot/pkg/test/common" - in tests
Decouple zb from code in test/pkg in order to keep the size small.
2. "zotregistry.io/zot/pkg/test/image-utils" - curently used as
. "zotregistry.io/zot/pkg/test/image-utils"
3. "zotregistry.io/zot/pkg/test/deprecated" - curently used as
"zotregistry.io/zot/pkg/test/deprecated"
This one will bre replaced gradually by image-utils in the future.
4. "zotregistry.io/zot/pkg/test/signature" - (cosign + notation) use as
"zotregistry.io/zot/pkg/test/signature"
5. "zotregistry.io/zot/pkg/test/auth" - (bearer + oidc) curently used as
authutils "zotregistry.io/zot/pkg/test/auth"
6. "zotregistry.io/zot/pkg/test/oci-utils" - curently used as
ociutils "zotregistry.io/zot/pkg/test/oci-utils"
Some unused functions were removed, some were replaced, and in
a few cases specific funtions were moved to the files they were used in.
Added an interface for the StoreController, this reduces the number of imports
of the entire image store, decreasing binary size for tests.
If the zb code was still coupled with pkg/test, this would have reflected in zb size.
Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
fix(authz): fix isAdmin not using groups to determine if a user is admin.
fix(authz): return 401 instead of 403
403 is correct as per HTTP spec
However authz is not part of dist-spec and clients know only about 401
So this is a compromise.
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
BREAKING CHANGE: The functionality provided by the mgmt endpoint has beed redesigned - see details below
BREAKING CHANGE: The API keys endpoint has been moved - see details below
BREAKING CHANGE: The mgmt extension config has been removed - endpoint is now enabled by having both the search and the ui extensions enabled
BREAKING CHANGE: The API keys configuration has been moved from extensions to http>auth>apikey
mgmt and imagetrust extensions:
- separate the _zot/ext/mgmt into 3 separate endpoints: _zot/ext/auth, _zot/ext/notation, _zot/ext/cosign
- signature verification logic is in a separate `imagetrust` extension
- better hanling or errors in case of signature uploads: logging and error codes (more 400 and less 500 errors)
- add authz on signature uploads (and add a new middleware in common for this purpose)
- remove the mgmt extension configuration - it is now enabled if the UI and the search extensions are enabled
userprefs estension:
- userprefs are enabled if both search and ui extensions are enabled (as opposed to just search)
apikey extension is removed and logic moved into the api folder
- Move apikeys code out of pkg/extensions and into pkg/api
- Remove apikey configuration options from the extensions configuration and move it inside the http auth section
- remove the build label apikeys
other changes:
- move most of the logic adding handlers to the extensions endpoints out of routes.go and into the extensions files.
- add warnings in case the users are still using configurations with the obsolete settings for mgmt and api keys
- add a new function in the extension package which could be a single point of starting backgroud tasks for all extensions
- more clear methods for verifying specific extensions are enabled
- fix http methods paired with the UI handlers
- rebuild swagger docs
Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
This change introduces OpenID authn by using providers such as Github,
Gitlab, Google and Dex.
User sessions are now used for web clients to identify
and persist an authenticated users session, thus not requiring every request to
use credentials.
Another change is apikey feature, users can create/revoke their api keys and use them
to authenticate when using cli clients such as skopeo.
eg:
login:
/auth/login?provider=github
/auth/login?provider=gitlab
and so on
logout:
/auth/logout
redirectURL:
/auth/callback/github
/auth/callback/gitlab
and so on
If network policy doesn't allow inbound connections, this callback wont work!
for more info read documentation added in this commit.
Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro>
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
Co-authored-by: Alex Stan <alexandrustan96@yahoo.ro>
ci(workflow): show disk usage and free up disk space used by unneeded tooling
ci(tests): routes tests: do not copy large images if they are not used later
ci(trivy): update a test: download trivy.db to a temporary folder
Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
Suppose we push two identical manifests (sharing same digest) but with
different tags, then deleting by digest should throw an error otherwise
we end up deleting all image tags (with gc) or dangling references
(without gc)
This behaviour is controlled via Authorization, added a new policy
action named detectManifestsCollision which enables this behaviour
Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
Co-authored-by: Ramkumar Chinchani <rchincha@cisco.com>
- Digests were represented by different ways
- We needed a uniform way to represent the digests and enforce a format
- also replace usage of github.com/google/go-containerregistry/pkg/v1
with github.com/opencontainers/image-spec/specs-go/v1
Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com>
(cherry picked from commit 96b2f29d6d57070a913ce419149cd481c0723815)
(cherry picked from commit 3d41b583daea654c98378ce3dcb78937d71538e8)
Co-authored-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com>
Files were added to be built whether an extension is on or off.
New build tags were added for each extension, while minimal and extended disappeared.
added custom binary naming depending on extensions used and changed references from binary to binary-extended
added automated blackbox tests for sync, search, scrub, metrics
added contributor guidelines
Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro>