Commit Graph

168 Commits

Author SHA1 Message Date
niksis02
ebdda06633 fix: adds BadDigest error for incorrect Content-Md5 s
Closes #1525

* Adds validation for the `Content-MD5` header.
  * If the header value is invalid, the gateway now returns an `InvalidDigest` error.
  * If the value is valid but does not match the payload, it returns a `BadDigest` error.
* Adds integration test cases for `PutBucketCors` with `Content-MD5`.
2025-09-19 19:51:23 +04:00
niksis02
6176d9eb46 fix: fixes sigv4 and presigned url auth errors.
Fixes #1540
Fixes #1538
Fixes #1513
Fixes #1425

Fixes SigV4 authentication and presigned URL error handling. Adds two sets of errors in the `s3err` package for these authentication mechanisms.

* Adds a check to return a custom "not supported" error when `X-Amz-Security-Token` is present in presigned URLs.
* Adds a check to return a custom "not supported" error when the `AWS4-ECDSA-P256-SHA256` algorithm is used in presigned URLs.
2025-09-18 00:11:12 +04:00
Ben McClelland
406161ba10 Merge pull request #1524 from versity/sis/object-get-part-number
fix: NotImplemented for GetObject/HeadObject PartNumber
2025-09-10 08:54:54 -07:00
niksis02
2bb8a1eeb7 fix: NotImplemented for GetObject/HeadObject PartNumber
Fixes #1520

Removes the incorrect logic for HeadObject returning successful response, when querying an incomplete multipart upload.

Implements the logic to return `NotImplemented` error if `GetObject`/`HeadObject` is attempted with `partNumber` in azure and posix backends. The front-end part is preserved to be used in s3 proxy backend.
2025-09-09 22:40:36 +04:00
niksis02
7a098b925f feat: implement conditional writes
Closes #821

**Implements conditional operations across object APIs:**

* **PutObject** and **CompleteMultipartUpload**:
  Supports conditional writes with `If-Match` and `If-None-Match` headers (ETag comparisons).
  Evaluation is based on an existing object with the same key in the bucket. The operation is allowed only if the preconditions are satisfied. If no object exists for the key, these headers are ignored.

* **CopyObject** and **UploadPartCopy**:
  Adds conditional reads on the copy source object with the following headers:

  * `x-amz-copy-source-if-match`
  * `x-amz-copy-source-if-none-match`
  * `x-amz-copy-source-if-modified-since`
  * `x-amz-copy-source-if-unmodified-since`
    The first two are ETag comparisons, while the latter two compare against the copy source’s `LastModified` timestamp.

* **AbortMultipartUpload**:
  Supports the `x-amz-if-match-initiated-time` header, which is true only if the multipart upload’s initialization time matches.

* **DeleteObject**:
  Adds support for:

  * `If-Match` (ETag comparison)
  * `x-amz-if-match-last-modified-time` (LastModified comparison)
  * `x-amz-if-match-size` (object size comparison)

Additionally, this PR updates precondition date parsing logic to support both **RFC1123** and **RFC3339** formats. Dates set in the future are ignored, matching AWS S3 behavior.
2025-09-09 01:55:38 +04:00
niksis02
b3ed7639f0 feat: implements conditional reads for GetObject and HeadObject
Closes #882

Implements conditional reads for `GetObject` and `HeadObject` in the gateway for both POSIX and Azure backends. The behavior is controlled by the `If-Match`, `If-None-Match`, `If-Modified-Since`, and `If-Unmodified-Since` request headers, where the first two perform ETag comparisons and the latter two compare against the object’s `LastModified` date. No validation is performed for invalid ETags or malformed date formats, and precondition date headers are expected to follow RFC1123; otherwise, they are ignored.

The Integration tests cover all possible combinations of conditional headers, ensuring the feature is 100% AWS S3–compatible.
2025-09-01 18:33:01 -07:00
Ben McClelland
0bf49872cf Merge pull request #1507 from versity/ben/get-object-overrides
feat: add response header overrides for GetObject
2025-09-01 14:17:28 -07:00
Ben McClelland
8cad7fd6d9 feat: add response header overrides for GetObject
GetObject allows overriding response headers with the following
paramters:
response-cache-control
response-content-disposition
response-content-encoding
response-content-language
response-content-type
response-expires

This is only valid for signed (and pre-singed) requests. An error
is returned for anonymous requests if these are set.

More info on the GetObject overrides can be found in the GetObject
API reference.

This also clarifies the naming of the AccessOptions IsPublicBucket
to IsPublicRequest to indicate this is a public access request
and not just accessing a bucket that allows public access.

Fixes #1501
2025-08-30 14:13:20 -07:00
Ben McClelland
58117c011a feat: add get bucket location frontend handlers
GetBucketLocation is being deprecated by AWS, but is still used
by some clients. We don't need any backend handlers for this since
the region is managed by the frontend. All we need is to test for
bucket existence, so we can use HeadBucket for this.

Fixes #1499
2025-08-30 12:29:26 -07:00
niksis02
843620235b fix: adds full wildcard and any character match for bucket policy actions
Fixes #1488

Adds full wildcard (`*`) and single-character (`?`) support for bucket policy actions, fixes resource detection with wildcards, and includes unit tests for `bucket_policy_actions`, `bucket_policy_effect`, and `bucket_policy_principals`.
2025-08-27 20:44:30 +04:00
nitin
630651254f fix: update marker/continuation token to be the azure next marker
This changes the marker/continuation token from the object name
to the marker from the azure list objects pager. This is needed
because passing the object name as the token to the azure next
call causes the Azure API to throw 400 Bad Request with
InvalidQueryParameterValue. So we have to use the azure marker
for compatibility with the azure API pager.

To do this we have to align the s3 list objects request to the
Azure ListBlobsHierarchyPager. The v2 requests have an optional
startafter where we will have to page through the azure blobs
to find the correct starting point, but after this we will
only return with the single paginated results form the Azure
pager to maintain the correct markers all the way through to
Azure.

The ListObjects (non V2) assumes that the marker must be an object
name, so for this case we have to page through the azure listings
for each call to find the correct starting point. This makes the
V2 method far more efficient, but maintains correctness for the
ListObjects.

Also remove continuation token string checks in the integration
tests since this is supposed to be an opaque token that the
client should not care about. This will help to maintain the
tests for mutliple backend types.

Fixes #1457
2025-08-25 11:28:42 -07:00
niksis02
d90944afd1 feat: implementes GetBucketPolicyStatus s3 action
Closes #1454

Adds the implementation of [S3 GetBucketPolicyStatus action](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicyStatus.html). The implementation goes to front-end. Front-End loads the bucket policy and checks if it grants public access to all users.

A bucket policy document `is public` only when `Principal` contains `*`(all users): only when it grants access to `ALL` users.
2025-08-25 21:48:06 +04:00
niksis02
14a2984d59 feat: adds not implemented routes for bucket website actions
Closes #1450

Adds `NotImplemented` routes for bucket website S3 actions:
- `PutBucketWebsite`
- `GetBucketWebsite`
- `DeleteBucketWebsite`
2025-08-22 19:56:51 +04:00
niksis02
0895ada9ed feat: adds not implemented routes for bucket accelerate configuration actions
Closes #1452

Adds `NotImplemented` routes for bucket accelerate configuration S3 actions:
- `PutBucketAccelerateConfiguration`
- `GetBucketAccelerateConfiguration`
2025-08-22 14:45:42 +04:00
niksis02
d784c0a841 feat: adds not implemented routes for bucket notification configuration actions
Closes #1453

Adds `NotImplemented` routes for bucket notification configuration S3 actions:
- `PutBucketNotificationConfiguration`
- `GetBucketNotificationConfiguration`
2025-08-21 20:40:18 +04:00
niksis02
be79fc249d feat: adds not implemented routes for bucket public access block actions
Closes #1451

Adds `NotImplemented` routes for bucket public access block S3 actions:
- `PutPublicAccessBlock`
- `GetPublicAccessBlock`
- `DeletePublicAccessBlock`
2025-08-21 20:10:29 +04:00
niksis02
88f84bfd89 feat: adds not implemented routes for bucket replication actions
Closes #1449

Adds `NotImplemented` routes for bucket replication S3 actions:
- `PutBucketReplication`
- `GetBucketReplication`
- `DeleteBucketReplication`

Adds missing actions in metrics `ActionMap`
2025-08-21 16:44:29 +04:00
niksis02
45a1f7ae7c feat: adds not implemented routes for bucket metrics configuration actions
Closes #1445

Adds `NotImplemented` routes for bucket metrics configuration S3 actions:
- `PutBucketMetricsConfiguration`
- `GetBucketMetricsConfiguration`
- `ListBucketMetricsConfigurations`
- `DeleteBucketMetricsConfiguration`

Adds the missing bucket actions to `supportedActionList` in bucket policy supported actions list.
2025-08-21 16:05:06 +04:00
Ben McClelland
be1708b1df Merge pull request #1476 from versity/sis/bucket-request-payment-actions-not-implemented
feat: adds not implemented routes for bucket request payment actions
2025-08-20 17:10:54 -07:00
Ben McClelland
617ad0fd31 Merge pull request #1475 from versity/sis/bucket-logging-actions-not-implemented
feat: adds not implemented routes for bucket logging actions
2025-08-20 17:10:32 -07:00
Ben McClelland
3e4c31f14a Merge pull request #1474 from versity/sis/bucket-lifecycle-configuration-actions-not-implemented
feat: adds not implemented routes for bucket lifecycle configuration actions
2025-08-20 17:09:59 -07:00
niksis02
6b450a5c11 feat: adds not implemented routes for bucket request payment actions
Closes #1455

Adds `NotImplemented` routes for bucket request payment S3 actions:
- `PutBucketRequestPayment`
- `GetBucketRequestPayment`
2025-08-21 00:54:31 +04:00
niksis02
5f28a7449e feat: adds not implemented routes for bucket logging actions
Closes #1444

Adds `NotImplemented` routes for bucket logging S3 actions:
- `PutBucketLogging`
- `GetBucketLogging`
2025-08-20 21:07:09 +04:00
niksis02
025b0ee3c8 feat: adds not implemented routes for bucket lifecycle configuration actions
Closes #1443

Adds `NotImplemented` routes for bucket lifecycle configuration S3 actions.
- `PutBucketLifecycleConfiguration`
- `GetBucketLifecycleConfiguration`
- `DeleteBucketLifecycle`
2025-08-20 20:48:58 +04:00
niksis02
09031a30e5 feat: bucket cors implementation
Closes #1003

**Changes Introduced:**

1. **S3 Bucket CORS Actions**

   * Implemented the following S3 bucket CORS APIs:

     * `PutBucketCors` – Configure CORS rules for a bucket.
     * `GetBucketCors` – Retrieve the current CORS configuration for a bucket.
     * `DeleteBucketCors` – Remove CORS configuration from a bucket.

2. **CORS Preflight Handling**

   * Added an `OPTIONS` endpoint to handle browser preflight requests.
   * The endpoint evaluates incoming requests against bucket CORS rules and returns the appropriate `Access-Control-*` headers.

3. **CORS Middleware**

   * Implemented middleware that:

     * Checks if a bucket has CORS configured.
     * Detects the `Origin` header in the request.
     * Adds the necessary `Access-Control-*` headers to the response when the request matches the bucket CORS configuration.
2025-08-20 20:45:09 +04:00
niksis02
24b88e20e0 feat: adds not implemented routes for bucket inventory configuration actions
Closes #1440

Adds `NotImplemented` routes for bucket inventory configuration S3 actions:
- `PutBucketInventoryConfiguration`
- `GetBucketInventoryConfiguration`
- `ListBucketInventoryConfigurations`
- `DeleteBucketInventoryConfiguration`
2025-08-19 21:49:38 +04:00
niksis02
cdccdcc4d6 feat: adds not implemented routes for bucket intelligent tiering actions
Closes #1440

Adds `NotImplemented` routes for intelligent tiering S3 actions:
- `PutBucketIntelligentTieringConfiguration`
- `GetBucketIntelligentTieringConfiguration`
- `ListBucketIntelligentTieringConfigurations`
- `DeleteBucketIntelligentTieringConfiguration`
2025-08-19 21:23:05 +04:00
niksis02
ed92ad3daa feat: adds not implemented routes for bucket ecryption actions
Closes #1439

Adds `NotImplemented` routes for bucket encryption S3 actions:

- `PutBucketEncryption`
- `GetBucketEncryption`
- `DeleteBucketEncryption`
2025-08-19 20:30:02 +04:00
niksis02
8db196634b fix: adds not implemented routes for bucket analytics s3 actions.
Fixes #1433
Fixes #1437
Fixes #1438

Adds 4 routes to return `NotImplemented` for bucket analytics `S3` actions:

- `PutBucketAnalyticsConfiguration`
- `GetBucketAnalyticsConfiguration`
- `DeleteBucketAnalyticsConfiguration`
- `ListBucketAnalyticsConfiguration`
2025-08-19 02:14:31 +04:00
Ben McClelland
e134f63ebc fix: add test cases and fix behavior for head/get range requests
This adds a bunch of test cases for non-0 len object, 0 len
object, and directory objects to match verified AWS responses
for the various range bytes cases.

This fixes the posix head/get range responses for these test
cases as well.
2025-08-12 14:46:58 -07:00
niksis02
69ba00a25f fix: fixes the UploadPart failure with no precalculated checksum header for FULL_OBJECT checksum type
Fixes #1342

This PR includes two main changes:

1. It fixes the case where `x-amz-checksum-x` (precalculated checksum headers) are not provided for `UploadPart`, and the checksum type for the multipart upload is `FULL_OBJECT`. In this scenario, the server no longer returns an error.

2. When no `x-amz-checksum-x` is provided for `UploadPart`, and `x-amz-sdk-checksum-algorithm` is also missing, the gateway now calculates the part checksum based on the multipart upload's checksum algorithm and stores it accordingly.

Additionally, the PR adds integration tests for:

* The two cases above
* The case where only `x-amz-sdk-checksum-algorithm` is provided
2025-07-28 23:01:35 +04:00
Ben McClelland
bcbe739158 Merge pull request #1416 from versity/sis/create-mp-checksum-headers-case-sensitivity
fix: makes checksum type and algorithm case insensitive in CreateMultipartUpload
2025-07-25 10:11:03 -07:00
niksis02
3363988206 fix: makes checksum type and algorithm case insensitive in CreateMultipartUpload
Fixes #1339

`x-amz-checksum-type` and `x-amz-checksum-algorithm` request headers should be case insensitive in `CreateMultipartUpload`.

The changes include parsing the header values to upper case before validating and passing to back-end. `x-amz-checksum-type` response header was added in`CreateMultipartUpload`, which was missing before.
2025-07-25 20:35:26 +04:00
niksis02
4187b4d400 fix: adds validation for x-amz-content-sha256 header
Fixes #1352

Adds a validation check step in `SigV4` authentication for `x-amz-content-sh256` to check it to be either a valid sha256 hash or a special payload type(UNSIGNED-PAYLOAD, STREAMING-UNSIGNED-PAYLOAD-TRAILER...).
2025-07-25 01:59:55 +04:00
niksis02
891672bf7e fix: fixes the HeadObject version access control with policies.
Fixes #1385

When accessing a specific object version, the user must have the `s3:GetObjectVersion` permission in the bucket policy. The `s3:GetObject` permission alone is not sufficient for a regular user to query object versions using `HeadObject`.

This PR fixes the issue and adds integration tests for both `HeadObject` and `GetObject`. It also includes cleanup in the integration tests by refactoring the creation of user S3 clients, and moves some test user data to the package level to avoid repetition across tests.
2025-07-24 01:04:45 +04:00
niksis02
e5850ff11f feat: adds copy source validation for x-amz-copy-source header.
Fixes #1388
Fixes #1389
Fixes #1390
Fixes #1401

Adds the `x-amz-copy-source` header validation for `CopyObject` and `UploadPartCopy` in front-end.
The error:
```
	ErrInvalidCopySource: {
		Code:           "InvalidArgument",
		Description:    "Copy Source must mention the source bucket and key: sourcebucket/sourcekey.",
		HTTPStatusCode: http.StatusBadRequest,
	},
```
is now deprecated.

The conditional read/write headers validation in `CopyObject` should come with #821 and #822.
2025-07-22 14:40:11 -07:00
niksis02
dc16c0448f feat: implements integration tests for the new advanced router 2025-07-22 21:00:24 +04:00
niksis02
b7c758b065 feat: implements advanced routing for bucket POST and object PUT operations.
Fixes #1036

Fixes the issue when calling a non-existing root endpoint(POST /) the gateway returns `NoSuchBucket`. Now it returns the correct `MethodNotAllowed` error.
2025-07-22 20:55:22 +04:00
niksis02
98a7b7f402 feat: adds a middleware to validate bucket/object names
Implements a middleware that validates incoming bucket and object names before authentication. This helps prevent malicious attacks that attempt to access restricted or unreachable data in `POSIX`.

Adds test cases to cover such attack scenarios, including false negatives where encoded paths are used to try accessing resources outside the intended bucket.

Removes bucket validation from all other layers—including `controllers` and both `POSIX` and `ScoutFS` backends — by moving the logic entirely into the middleware layer.
2025-07-04 00:55:03 +04:00
niksis02
458db64e2d feat: implements public bucket access.
This implementation introduces **public buckets**, which are accessible without signature-based authentication.

There are two ways to grant public access to a bucket:

* **Bucket ACLs**
* **Bucket Policies**

Only `Get` and `List` operations are permitted on public buckets. All **write operations** require authentication, regardless of whether public access is granted through an ACL or a policy.

The implementation includes an `AuthorizePublicBucketAccess` middleware, which checks if public access has been granted to the bucket. If so, authentication middlewares are skipped. For unauthenticated requests, appropriate errors are returned based on the specific S3 action.

---

**1. Bucket-Level Operations:**

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::test"
    }
  ]
}
```

**2. Object-Level Operations:**

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::test/*"
    }
  ]
}
```

**3. Both Bucket and Object-Level Operations:**

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::test"
    },
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::test/*"
    }
  ]
}
```

---

```sh
aws s3api create-bucket --bucket test --object-ownership BucketOwnerPreferred
aws s3api put-bucket-acl --bucket test --acl public-read
```
2025-07-02 00:11:10 +04:00
niksis02
3e50e29306 fix: overrides empty checksum type and algorithm with 'null' for ListParts
Fixes #1288

If the checksum algorithm/type is not specified during multipart upload initialization, it is considered `null`, and the `ListParts` result should also set it to `null`.
2025-05-14 08:22:45 -07:00
Ben McClelland
4b34ef1a5f Merge pull request #1263 from versity/sis/headobject-range
fix: fixes the range parsing for GetObject. Adds range query support for HeadObject.
2025-05-05 12:23:15 -07:00
niksis02
dfa1ed2358 fix: fixes the range parsing for GetObject. Adds range query support for HeadObject.
Fixes #1258
Fixes #1257
Closes #1244

Adds range queries support for `HeadObject`.
Fixes the range parsing logic for `GetObject`, which is used for `HeadObject` as well. Both actions follow the same rules for range parsing.

Fixes the error message returned by `GetObject`.
2025-05-05 22:41:12 +04:00
Ben McClelland
e9286f7a23 feat: add scoutfs group tests to integration 2025-05-03 12:04:47 -07:00
niksis02
5e6056467e fix: fixes tagging string parsing for PutObject, CopyObject and CreateMultipartUpload
Fixes #1215
Fixes #1216

`PutObject`, `CopyObject` and `CreateMultipartUpload` accept tag string as an http request header which should be url-encoded. The tag string should be a valid url-encoded string and each key/value pair should be valid, otherwise they should fail with `APIError`.

If the provided tag set contains duplicate `keys` the calls should fail with the same `InvalidURLEncodedTagging` error.

Not all url-encoded characters are supported by `S3`. The tagging string should contain only `letters`, `digits` and the following special chars:
- `-`
- `.`
- `/`
- `_`
- `+`
- ` `(space)

And their url-encoded versions: e.g. `%2F`(/), `%2E`(.) ... .

If the provided tagging string contains invalid `key`/`value`, the calls should fail with the following errors respectively:
`invalid key` - `(InvalidTag) The TagKey you have provided is invalid`
`invalid value` - `(InvalidTag) The TagValue you have provided is invalid`
2025-04-28 20:28:20 +04:00
niksis02
f831578d51 fix: handles tag parsing error cases for PutBucketTagging and PutObjectTagging
Fixes #1214
Fixes #1231
Fixes #1232

Implements `utils.ParseTagging` which is a generic implementation of parsing tags for both `PutObjectTagging` and `PutBucketTagging`.

- The actions now return `MalformedXML` if the provided request body is invalid.
- Adds validation to return `InvalidTag` if duplicate keys are present in tagging.
- For invalid tag keys, it creates a new error: `ErrInvalidTagKey`.
2025-04-23 20:35:19 +04:00
niksis02
66b979ee86 fix: Sets limit to tag set count to 10 for PutObjectTagging and 50 for PutBucketTagging
Fixes #1204
Fixes #1205

Tag count in `PutBucketTagging` and `PutObjectTagging` is limited.
`PutBucketTagging`: 50
`PutObjectTagging`: 10

Adds the changes to return errors respectively
2025-04-11 21:07:08 +04:00
niksis02
aaee7afa98 fix: Changes the backend.Walk implementation to return non-truncated result if both delimiter and max-keys are provided
Fixes #816

`ListObjects(V2)` used to return truncated response, if delimiter is provided and the result is limited by max-keys and the number of common prefixes is the same as `max-keys`.
e.g
PUT -> `foo/bar`
PUT -> `foo/quxx`
LIST: `max-keys=1;delim=/` -> foo/

`ListObjects(V2)` should return `foo/` as common prefix and `truncated` should be `false`.

The PR makes this fix to return `non-truncated` response for the above described case.
2025-04-09 21:29:58 +04:00
niksis02
f627b2efec fix: Makes the crc64nvme checksum as default for PutObject, even if no checksum is provided
Fixes #1182

S3 calculates the `CRC64NVME` checksum of an object on object upload(`PutObject`), when no checksum algorithm or precalculated checksum header is provided.
Makes the `CRC64NVME` checksum as default for `PutObject`, when no checksum is provided.
2025-04-04 00:08:54 +04:00
Ben McClelland
90a67272a7 Merge pull request #1184 from versity/sis/deleteobject-non-empty-dir-obj
fix: Fixes non empty directory objects deletion
2025-04-02 13:09:48 -07:00