When a JWT contains a JWK header without a certificate chain,
the original code only checked if the KeyID (kid) matches one of the trusted keys,
but doesn't verify that the actual key material matches.
As a result, if an attacker guesses the kid, they can inject an
untrusted key which would then be used to grant access to protected
data.
This fixes the issue such as only the trusted key is verified.
Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
Some S3 compatible object storage systems like R2 require that all
multipart chunks are the same size. This was mostly true before, except
the final chunk was larger than the requested chunk size which causes
uploads to fail.
In addition, the two byte slices have been replaced with a single
*bytes.Buffer and the surrounding code simplified significantly.
Fixes: #3873
Signed-off-by: Thomas Way <thomas@6f.io>
when a directory is empty, the s3 api lists it with a trailing slash.
this causes the path to be appended twice to the walkInfo slice, causing
purge uploads path transformations to panic when the `_uploads` is
emtpy.
this adds a check for file paths ending on slash, and do not append
those as regular files to the walkInfo slice.
fixes#4358
Signed-off-by: Flavian Missi <fmissi@redhat.com>
- Add Unit tests for `token.newAccessController`
+ Implemented swappable implementations for `token.getRootCerts` and
`getJwks` to unit test their behavior over the accessController
struct.
- Use RFC7638 [0] mechanics to compute the KeyID of the rootcertbundle
provided in the token auth config.
- Extends token authentication docs:
+ Extend `jwt.md` write up on JWT headers & JWT Validation
+ Updated old reference to a draft that's now RFC7515.
+ Extended the JWT validation steps with the JWT Header validation.
+ Reference `jwt.md` in `token.md`
[0]: https://datatracker.ietf.org/doc/html/rfc7638#autoid-13
Signed-off-by: Jose D. Gomez R <jose.gomez@suse.com>
This test was using a hard-coded value for the size of the manifest,
which made it difficult to correlate the tested value with what it
was testing.
This patch updates populateRepo to return the actual size when
serialized, and updates manifestStoreTestEnv to include the
size to test for.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The latest golangci-lint spits out some govet issues.
This commit fixes them. We are also bumping the linter version.
Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
This change allows users to run the registry as a pull-through cache
that can use a credential helper to authenticate against the upstream
registry.
Signed-off-by: Chun-Hung Hsiao <chhsiao@google.com>
https://github.com/distribution/distribution/pull/4146 introduced a new
rewrite storage middleware but somehow missed to update the init logging
message. This commit fixes that.
Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
There was a small regression introduced in
https://github.com/distribution/distribution/pull/4349.
Specifically, if the certificate chain verification succeeds we should
return immediately instead of following up with further token verification
checks.
This commit fixes that: we only follow up with further token
verifications if x5c header is missing.
We've also refactored this method so it's hopefully clearer.
Co-authored-by: Kyle Squizzato <ksquizz@gmail.com>
Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
Stat always calls ListObjects when stat-ing S3 key.
Unfortauntely ListObjects is not a free call - both in terms of egress
and actual AWS costs (likely because of the egress).
This changes the behaviour of Stat such that we always attempt the
HeadObject call first and only ever fall through to ListObjects if the
HeadObject returns an AWS API error.
Note, that the official docs mention that the only error returned by
HEAD is NoSuchKey; experiments show that this is demonstrably wrong and
the AWS docs are simply outdated at the time of this commit.
HeadObject actually returns the following errors:
* NotFound: if the queried key does not exist
* NotFound: if the queried key contains subkeys i.e. it's a prefix
* BucketRegionError: if the bucket does not exist
* Forbidden: if Head operation is not allows via IAM/ACLs
Co-authored-by: Cory Snider <corhere@gmail.com>
Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
Defining an interface on the implementer side is generally not best
practice in Go code. There is no code in the distribution module which
consumes a ManifestBuilder value so there is no need to define the
interface in the distribution module. Export the concrete
ManifestBuilder types and modify the constructors to return concrete
values.
Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Cory Snider <csnider@mirantis.com>
This allows to rewrite 'URLFor' of the storage driver to use a specific
host/trim the base path.
It is different from the 'redirect' middleware, as it still calls the
storage driver URLFor.
For example, with Azure storage provider, this allows to transform the
SAS Azure Blob Storage URL into the URL compatible with Azure Front
Door.
Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
The garbage-collect should remove unsed layer link file
P.S. This was originally contributed by @m-masataka, now I would like to take over it.
Thanks @m-masataka efforts with PR https://github.com/distribution/distribution/pull/2288
Signed-off-by: Liang Zheng <zhengliang0901@gmail.com>
Huge help from @milosgajdos who figured out how to do the entire
marshalling/unmarshalling for the configs
Signed-off-by: Anders Ingemann <aim@orbit.online>
This bumps go-jose to the latest available version: v4.0.3.
This slightly breaks the backwards compatibility with the existing
registry deployments but brings more security with it.
We now require the users to specify the list of token signing algorithms in
the configuration. We do strive to maintain the b/w compat by providing
a list of supported algorithms, though, this isn't something we
recommend due to security issues, see:
* https://github.com/go-jose/go-jose/issues/64
* https://github.com/go-jose/go-jose/pull/69
As part of this change we now return to the original flow of the token
signature validation:
1. X2C (tls) headers
2. JWKS
3. KeyID
Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
Enable configuration options that can selectively disable validation
that dependencies exist within the registry before the image index
is uploaded.
This enables sparse indexes, where a registry holds a manifest index that
could be signed (so the digest must not change) but does not hold every
referenced image in the index. The use case for this is when a registry
mirror does not need to mirror all platforms, but does need to maintain
the digests of all manifests either because they are signed or because
they are pulled by digest.
The registry administrator can also select specific image architectures
that must exist in the registry, enabling a registry operator to select
only the platforms they care about and ensure all image indexes uploaded
to the registry are valid for those platforms.
Signed-off-by: James Hewitt <james.hewitt@uk.ibm.com>
With the current logic we only verifies the region and return if it's
empty; we were not validating the regionEndpoint parameter.
Signed-off-by: Ankur Kothiwal <ankur.kothiwal@cern.com>
Harbor is using the distribution for it's (harbor-registry) registry component.
The harbor GC will call into the registry to delete the manifest, which in turn
then does a lookup for all tags that reference the deleted manifest.
To find the tag references, the registry will iterate every tag in the repository
and read it's link file to check if it matches the deleted manifest (i.e. to see
if uses the same sha256 digest). So, the more tags in repository, the worse the
performance will be (as there will be more s3 API calls occurring for the tag
directory lookups and tag file reads).
Therefore, we can use concurrent lookup and untag to optimize performance as described in https://github.com/goharbor/harbor/issues/12948.
P.S. This optimization was originally contributed by @Antiarchitect, now I would like to take it over.
Thanks @Antiarchitect's efforts with PR https://github.com/distribution/distribution/pull/3890.
Signed-off-by: Liang Zheng <zhengliang0901@gmail.com>
it is reasonable to ignore the error that the manifest tag path does not exist when querying
all tags of the specified repository when executing gc.
Signed-off-by: Liang Zheng <zhengliang0901@gmail.com>