Commit Graph

2491 Commits

Author SHA1 Message Date
Ben McClelland 7300306886 feat: add group-based role mapping for FreeIPA IAM
FreeIPA users were always assigned RoleUser regardless of their
group membership. This adds --ipa-admin-group-cn so that members
of a specified FreeIPA group are automatically granted the admin
role, and  --ipa-enable-userplus to elevate the default role to
userplus for all IPA users. The user_show RPC is updated to
request all attributes so that memberof_group is reliably
returned.
2026-05-29 20:55:25 -07:00
Ben McClelland f7cc70b157 Merge pull request #2157 from versity/test/list_multipart_uploads
test: ListMultipartUpload query tests
2026-05-28 16:02:30 -07:00
Luke McCrone 179fdc0352 test: ListMultipartUpload query tests, related cleanup 2026-05-28 09:30:59 -03:00
Ben McClelland 2bc4da944f Merge pull request #2153 from versity/sis/policy-key-normalization
fix: normalize object keys during bucket policy evaluation
2026-05-27 20:17:25 -07:00
niksis02 cd0b4e6d9d fix: normalize object keys during bucket policy evaluation
Object key validation allowed internal parent-directory segments such as `public/../private.txt`. Bucket policy and auth checks evaluated the raw key, so a policy allowing bucket/public/* could match the request while posix backend later resolved the key with `filepath.Join` and accessed `bucket/private.txt`.

Add backend-specific object key normalization to close that mismatch. The Backend interface now exposes `NormalizeObjectKey` so authorization can evaluate resources using the same key shape a backend will use for storage access.

Backends that do not collapse object paths, including Azure and the S3 proxy, inherit `BackendUnsupported.NormalizeObjectKey`. That implementation returns the input key unchanged, avoiding unnecessary normalization and keeping policy evaluation unpolluted for object stores where ../ is part of the key name.

posix/scoutfs normalize keys with filepath.Join so policy resources and request keys are compared after internal dot segments are collapsed.

Bucket policy evaluation now normalizes both the incoming object key and object resource patterns from the policy before matching. Object lock governance bypass policy checks use the same backend normalizer as well, so retention and legal hold authorization cannot diverge from backend path resolution.
2026-05-27 22:20:39 +04:00
Ben McClelland d62a11f62c Merge pull request #2151 from versity/ben/embed
feat: extract gateway runtime into embeddable package
2026-05-26 20:33:30 -07:00
Ben McClelland 20939bd7b4 feat: extract gateway runtime into embeddable package
Move the runGateway implementation from cmd/versitygw/main.go into a
new embedgw package, exposing RunVersityGW(ctx, Backend, *Config) and a
Config struct. This allows external applications to embed and run the
VersityGW S3 gateway as a library.
2026-05-26 15:08:28 -07:00
Ben McClelland 7dadbc0277 Merge pull request #2154 from versity/sis/empty-ownership-control-rules
fix: fix empty ownership control rules panic
2026-05-26 11:44:39 -07:00
niksis02 4ef090dbfc fix: fix empty ownership control rules panic
Fix the gateway panic when validating malformed bucket ownership controls bodies with no rules. The handler now checks the rules count before indexing the first rule.
2026-05-23 04:18:06 +04:00
Ben McClelland 6c643db58e Merge pull request #2152 from versity/ben/vulnchk
chore: update go package dependencies
2026-05-22 16:49:58 -07:00
Ben McClelland db3478d8b8 chore: update go package dependencies
Fixes govulncheck report:
Vulnerability #1: GO-2026-5026
    Invoking failure to reject ASCII-only Punycode-encoded labels in
    golang.org/x/net/idna
  More info: https://pkg.go.dev/vuln/GO-2026-5026
  Module: golang.org/x/net
    Found in: golang.org/x/net@v0.54.0
    Fixed in: golang.org/x/net@v0.55.0
2026-05-22 15:26:30 -07:00
Ben McClelland f4e5df3b0f Merge pull request #2147 from versity/sis/post-object-key-validation
fix: reject invalid PostObject keys
2026-05-22 11:53:24 -07:00
niksis02 eecc1a779c fix: reject invalid PostObject keys
Validate multipart PostObject key fields with the existing object name rules so path traversal and degenerate names return BadRequest. This prevents crafted object keys from escaping the gateway root.
2026-05-22 14:48:31 +04:00
Ben McClelland 81c9d4ed2f Merge pull request #2148 from versity/sis/public-bucket-policy-deny
fix: honor explicit public bucket policy deny
2026-05-21 15:07:26 -07:00
Ben McClelland 2a8b15a1c2 Merge pull request #2141 from versity/sis/global-error-refactoring
feat: global error refactoring
2026-05-21 15:05:45 -07:00
niksis02 ed1ad6b623 fix: honor explicit public bucket policy deny
Distinguish public bucket policy no-match from explicit deny during anonymous access checks. This preserves ACL fallback only for requests that are not allowed by policy, while ensuring a matching Deny statement short-circuits authorization and returns AccessDenied even when a public ACL would otherwise grant access.
2026-05-22 00:01:24 +04:00
niksis02 9f786b3c2c feat: global error refactoring
Fixes #2123
Fixes #2120
Fixes #2116
Fixes #2111
Fixes #2108
Fixes #2086
Fixes #2085
Fixes #2083
Fixes #2081
Fixes #2080
Fixes #2073
Fixes #2072
Fixes #2071
Fixes #2069
Fixes #2044
Fixes #2043
Fixes #2042
Fixes #2041
Fixes #2040
Fixes #2039
Fixes #2036
Fixes #2035
Fixes #2034
Fixes #2028
Fixes #2020
Fixes #1842
Fixes #1810
Fixes #1780
Fixes #1775
Fixes #1736
Fixes #1705
Fixes #1663
Fixes #1645
Fixes #1583
Fixes #1526
Fixes #1514
Fixes #1493
Fixes #1487
Fixes #959
Fixes #779
Closes #823
Closes #85

Refactor global S3 error handling around structured error types and centralized XML response generation.

All S3 errors now share the common APIError base for the fields every error has: Code, HTTP status code, and Message. Non-traditional errors that need AWS-compatible XML fields now have dedicated typed errors in the s3err package. Each typed error implements the shared S3Error behavior so controllers and middleware can handle errors consistently while still emitting error-specific XML fields.

Add a dedicated InvalidArgumentError type because InvalidArgument is used widely across request validation, auth, copy source handling, object lock validation, multipart validation, and header parsing. The new InvalidArgument path uses explicit InvalidArgErrorCode constants with predefined descriptions and ArgumentName values, keeping call sites readable while preserving the correct InvalidArgument XML shape and optional ArgumentValue.

New structured errors added in s3err:
- `AccessForbiddenError`: Method, ResourceType
- `BadDigestError`: CalculatedDigest, ExpectedDigest
- `BucketError`: BucketName
- `ContentSHA256MismatchError`: ClientComputedContentSHA256, S3ComputedContentSHA256
- `EntityTooLargeError`: ProposedSize, MaxSizeAllowed
- `EntityTooSmallError`: ProposedSize, MinSizeAllowed
- `ExpiredPresignedURLError`: ServerTime, XAmzExpires, Expires
- `InvalidAccessKeyIdError`: AWSAccessKeyId
- `InvalidArgumentError`: Description, ArgumentName, ArgumentValue
- `InvalidChunkSizeError`: Chunk, BadChunkSize
- `InvalidDigestError`: ContentMD5
- `InvalidLocationConstraintError`: LocationConstraint
- `InvalidPartError`: UploadId, PartNumber, ETag
- `InvalidRangeError`: RangeRequested, ActualObjectSize
- `InvalidTagError`: TagKey, TagValue
- `KeyTooLongError`: Size, MaxSizeAllowed
- `MetadataTooLargeError`: Size, MaxSizeAllowed
- `MethodNotAllowedError`: Method, ResourceType, AllowedMethods
- `NoSuchUploadError`: UploadId
- `NoSuchVersionError`: Key, VersionId
- `NotImplementedError`: Header, AdditionalMessage
- `PreconditionFailedError`: Condition
- `RequestTimeTooSkewedError`: RequestTime, ServerTime, MaxAllowedSkewMilliseconds
- `SignatureDoesNotMatchError`: AWSAccessKeyId, StringToSign, SignatureProvided, StringToSignBytes, CanonicalRequest, CanonicalRequestBytes

Fix CompleteMultipartUpload validation in the Azure backend so missing or empty `ETag` values return the appropriate S3 error instead of allowing a gateway panic.

Fix presigned authentication expiration validation to compare server time in `UTC`, matching the `UTC` timestamp used by presigned URL signing.

Add request ID and host ID support across S3 requests. Each request now receives AWS S3-like identifiers, returned in response headers as `x-amz-request-id` and `x-amz-id-2` and included in all XML error responses as RequestId and HostId. The generated ID structure is designed to resemble AWS S3 request IDs and host IDs.

The request signature calculation/validation for streaming uploads was previously delayed until the request body was fully read, both for Authorization header authentication and presigned URLs.
Now, the signature is validated immediately in the authorization middlewares without reading the request body, since the signature calculation itself does not depend on the request body. Instead, only the `x-amz-content-sha256` SHA-256 hash calculation is delayed.
2026-05-21 23:49:34 +04:00
Ben McClelland eade1e3a71 Merge pull request #2140 from versity/test/util_list_objects
test: ListObjects util code cleanup, multipart updates
2026-05-21 08:14:21 -07:00
Ben McClelland 6fd0b1395e Merge pull request #2145 from versity/dependabot/go_modules/dev-dependencies-a5fc3ebefd
chore(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob from 1.6.4 to 1.7.0 in the dev-dependencies group
2026-05-21 08:13:47 -07:00
Luke McCrone 48f79a6171 test: ListObjects util code reorg, return value/multipart fixes 2026-05-20 14:30:41 -03:00
dependabot[bot] 3cf10d8392 chore(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
Bumps the dev-dependencies group with 1 update: [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go).


Updates `github.com/Azure/azure-sdk-for-go/sdk/storage/azblob` from 1.6.4 to 1.7.0
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/storage/azblob/v1.6.4...sdk/azcore/v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-19 05:58:47 +00:00
Ben McClelland 57beab26c8 Merge pull request #2137 from versity/test/test_rest_head_object 2026-05-14 15:03:18 -07:00
Luke McCrone fd8e4cd69c test: HeadObject query tests, more util code changes 2026-05-14 11:15:15 -03:00
Ben McClelland 6fe0841cc3 Merge pull request #2125 from versity/sis/compress-mp-metadata
fix: store object multipart upload metadata compressed
2026-05-13 11:54:17 -07:00
Ben McClelland 9fffac1297 Merge pull request #2139 from versity/ben/webui-space-encode
fix: decode URL hash in webui before parsing bucket/prefix
2026-05-13 11:48:11 -07:00
Ben McClelland acedcda2e8 Merge pull request #2138 from versity/ben/implicit-dir-objs
fix: ignore implicit directories for  Get/HeadObject
2026-05-13 11:47:15 -07:00
Ben McClelland a5fc7c1ee5 fix: decode URL hash in webui before parsing bucket/prefix
window.location.hash returns the hash percent-encoded by the browser,
so a prefix like "X Y/" is read back as "X%20Y/" (literal %20).
Without decoding, all subsequent operations (list, upload, create
folder) used the encoded string, causing the server to look
for a directory named "X%20Y/" instead of "X Y/" — resulting in empty
listings and uploads landing in a newly created "X%20Y/" directory.

Fix by calling decodeURIComponent() on the hash before splitting into
bucket and prefix parts.

Fixes #2098
2026-05-12 19:45:31 -07:00
Ben McClelland 2c0844ad88 fix: ignore implicit directories for Get/HeadObject
Directories that exist on the filesystem but were not explicitly created
via S3 (put-object with a key ending in '/') do not have an etag
value. ListObjectsV2 already uses the presence of this attribute to
decide whether to include a directory as an object. GetObject and
HeadObject were not performing this check, so they would successfully
return directories that ListObjectsV2 would not list.

Add the etag attribute check in GetObject and HeadObject: if a
directory path is requested but has no etag xattr, return 404. This
makes all three operations agree on which directories are S3 objects.

Fixes #2130
2026-05-12 18:56:00 -07:00
Ben McClelland 67c50ffa0e Merge pull request #2133 from versity/dependabot/github_actions/sigstore/cosign-installer-4.1.2
chore(deps): bump sigstore/cosign-installer from 4.1.1 to 4.1.2
2026-05-12 11:05:06 -07:00
Ben McClelland 9556e5b4e6 Merge pull request #2132 from versity/dependabot/go_modules/dev-dependencies-d72d03fc52 2026-05-11 21:52:08 -07:00
dependabot[bot] deda805c7d chore(deps): bump sigstore/cosign-installer from 4.1.1 to 4.1.2
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v4.1.1...v4.1.2)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-version: 4.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-12 03:32:57 +00:00
dependabot[bot] 2ed8b7873e chore(deps): bump the dev-dependencies group with 9 updates
Bumps the dev-dependencies group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager](https://github.com/aws/aws-sdk-go-v2) | `0.1.20` | `0.1.21` |
| [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) | `1.100.1` | `1.101.0` |
| [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) | `1.51.0` | `1.52.0` |
| [github.com/valyala/fasthttp](https://github.com/valyala/fasthttp) | `1.70.0` | `1.71.0` |
| [golang.org/x/sys](https://github.com/golang/sys) | `0.43.0` | `0.44.0` |
| [github.com/AzureAD/microsoft-authentication-library-for-go](https://github.com/AzureAD/microsoft-authentication-library-for-go) | `1.7.1` | `1.7.2` |
| [golang.org/x/crypto](https://github.com/golang/crypto) | `0.50.0` | `0.51.0` |
| [golang.org/x/net](https://github.com/golang/net) | `0.53.0` | `0.54.0` |
| [golang.org/x/text](https://github.com/golang/text) | `0.36.0` | `0.37.0` |


Updates `github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager` from 0.1.20 to 0.1.21
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/feature/s3/transfermanager/v0.1.20...feature/s3/transfermanager/v0.1.21)

Updates `github.com/aws/aws-sdk-go-v2/service/s3` from 1.100.1 to 1.101.0
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.100.1...service/s3/v1.101.0)

Updates `github.com/nats-io/nats.go` from 1.51.0 to 1.52.0
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.51.0...v1.52.0)

Updates `github.com/valyala/fasthttp` from 1.70.0 to 1.71.0
- [Release notes](https://github.com/valyala/fasthttp/releases)
- [Commits](https://github.com/valyala/fasthttp/compare/v1.70.0...v1.71.0)

Updates `golang.org/x/sys` from 0.43.0 to 0.44.0
- [Commits](https://github.com/golang/sys/compare/v0.43.0...v0.44.0)

Updates `github.com/AzureAD/microsoft-authentication-library-for-go` from 1.7.1 to 1.7.2
- [Release notes](https://github.com/AzureAD/microsoft-authentication-library-for-go/releases)
- [Changelog](https://github.com/AzureAD/microsoft-authentication-library-for-go/blob/main/changelog.md)
- [Commits](https://github.com/AzureAD/microsoft-authentication-library-for-go/compare/v1.7.1...v1.7.2)

Updates `golang.org/x/crypto` from 0.50.0 to 0.51.0
- [Commits](https://github.com/golang/crypto/compare/v0.50.0...v0.51.0)

Updates `golang.org/x/net` from 0.53.0 to 0.54.0
- [Commits](https://github.com/golang/net/compare/v0.53.0...v0.54.0)

Updates `golang.org/x/text` from 0.36.0 to 0.37.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.36.0...v0.37.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager
  dependency-version: 0.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-version: 1.101.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.52.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: github.com/valyala/fasthttp
  dependency-version: 1.71.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: golang.org/x/sys
  dependency-version: 0.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: github.com/AzureAD/microsoft-authentication-library-for-go
  dependency-version: 1.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: golang.org/x/crypto
  dependency-version: 0.51.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: golang.org/x/net
  dependency-version: 0.54.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: golang.org/x/text
  dependency-version: 0.37.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-12 03:30:00 +00:00
Ben McClelland a0ab3f744d Merge pull request #2126 from versity/test/util_removal
test: more util code cleanup
2026-05-11 19:10:29 -07:00
Luke McCrone 37d6ca03ed test: util code cleanup 2026-05-11 16:34:54 -03:00
alexgalie fe3cfbfce9 fix: forward slash url encoded used as bucket/key separator
handle %2F ("/") url encoded separator for bucket/key

Fixes #2024

---------

Co-authored-by: Galie Alexandru MTANA <alexandru.galie@mt.com>
2026-05-11 10:31:02 -07:00
Ben McClelland e49bb1d76a Merge pull request #2121 from versity/test/test_rest_delete_objects 2026-05-09 09:14:52 -07:00
niksis02 5cb5541006 fix: store object multipart upload metadata compressed
Store multipart upload metadata through shared backend helpers so POSIX and Azure use the same encode/decode path. POSIX stores raw gzipped JSON in metadata stores, while Azure stores base64-encoded gzip for string metadata. Retrieval falls back to the legacy raw JSON format for existing objects. Storing the mp metadata compressed in posix will guarantee that for any allowed number of parts, the metadata won't exceed the xattr threshold(64KB).
2026-05-08 22:59:34 +04:00
Luke McCrone 6608c53612 test: DeleteObjects payload testing 2026-05-08 14:46:54 -03:00
Ben McClelland d94b2da5b7 Merge pull request #2118 from versity/ben/bucket-tags
feat: add bucket metrics tag when request specifies a bucket
2026-05-08 08:12:53 -07:00
Ben McClelland ff0cea3f83 Merge pull request #2094 from versity/ben/webui-search
feat: replace webui client-side name filter with server-side prefix filter
2026-05-06 16:30:02 -07:00
Ben McClelland 861c5f5d97 feat: add bucket metrics tag when request specifies a bucket
If the incoming request specifies a bucket name, add a tag
bucket=<bucketname> to the metric.

Fixes #2103
2026-05-06 13:46:08 -07:00
Ben McClelland 12f3d3a1e2 Merge pull request #2117 from versity/test/dockerfile_prep
test: dockerfile, run script updates, README updates
2026-05-06 13:39:00 -07:00
Ben McClelland c6e795f91f Merge pull request #2114 from versity/sis/unsupported-sigv2
fix: reject SigV2 requests
2026-05-06 13:38:14 -07:00
niksis02 e69d073273 fix: reject SigV2 requests
The gateway currently supports only Signature Version 4 (SigV4) authorization. Deprecated AWS SigV2 requests are now rejected with an AWS-specific `InvalidRequest` error for both Authorization-header requests and query-string requests(presigned URLs).

This also fixes SigV4 Authorization-header handling for date headers. SigV4 accepts two date headers: `Date` and `X-Amz-Date`. `X-Amz-Date` takes precedence, but when it is missing, `Date` should be used. The gateway now uses the `Date` header with lower precedence when `X-Amz-Date` is not present. No SDK integration test was added for this case because the SDK always sets `X-Amz-Date`, and this behavior is not configurable.
2026-05-06 23:43:10 +04:00
Ben McClelland cb609e40a6 feat: replace webui client-side name filter with server-side prefix filter
Remove the client-side search that filtered already-loaded objects by
name. Replace it with a prefix input that is appended to the current
path prefix and passed directly to the S3 ListObjectsV2 API, so
filtering is performed server-side and works correctly across all pages.

Fixes #2091
2026-05-06 12:34:52 -07:00
Luke McCrone 0136a0ba84 test: dockerfile, run script updates, README updates 2026-05-06 14:44:50 -03:00
Ben McClelland 79441fa48e Merge pull request #2115 from versity/ben/sidecar-test
chore: fix sidecar flag in runtests to correctly pass test option
2026-05-06 09:04:42 -07:00
Ben McClelland e1578f6a8f Merge pull request #2104 from versity/test/snia_prep
test: add test tags
2026-05-06 09:03:03 -07:00
Ben McClelland e4fa31c91d chore: fix sidecar flag in runtests to correctly pass test option
There was a typo in the runtests script that was preventing
passing the correct sidecar option to the tests.
2026-05-06 08:24:50 -07:00
Luke McCrone 317767b15b test: add test tags 2026-05-05 19:07:56 -03:00