Skip to content

feat(s3s): implement access point and S3 on Outposts ARN support in CopySource#527

Merged
Nugine merged 4 commits intomainfrom
feat/access-point
Mar 1, 2026
Merged

feat(s3s): implement access point and S3 on Outposts ARN support in CopySource#527
Nugine merged 4 commits intomainfrom
feat/access-point

Conversation

@Nugine
Copy link
Member

@Nugine Nugine commented Mar 1, 2026

Summary

Implements full parsing and formatting support for the two ARN-based x-amz-copy-source formats defined in the AWS S3 CopyObject API, resolving the // FIXME: support access point comment in copy_source.rs.


AWS Format Reference

The x-amz-copy-source header supports three formats:

Format Pattern
Bucket <bucket>/<key>[?versionId=<id>]
Access Point ARN arn:<partition>:s3:<region>:<account-id>:accesspoint/<name>/object/<key>[?versionId=<id>]
S3 on Outposts ARN arn:<partition>:s3-outposts:<region>:<account-id>:outpost/<outpost-id>/object/<key>[?versionId=<id>]

Supported partitions: aws, aws-cn, aws-us-gov.


Changes

crates/s3s/src/dto/copy_source.rs

Enum changes:

  • AccessPoint variant: add partition field and version_id field
  • New Outpost variant: partition, region, account_id, outpost_id, key, version_id

New error variants:

  • InvalidArn — malformed ARN structure or unsupported service/partition
  • InvalidAccessPointName — name fails AWS naming rules
  • InvalidAccountId — account ID is not exactly 12 ASCII digits

New validation functions:

  • check_access_point_name(name) — 3–63 chars, lowercase alphanumeric + hyphens, no leading/trailing hyphens, no consecutive hyphens
  • check_account_id(id) — exactly 12 ASCII digits

Parsing (parse()):

  • Extracted extract_version_id() helper
  • After URL decode, detects arn: prefix and dispatches to parse_arn()
  • parse_arn() uses splitn(6, ':') to preserve colons in the resource segment
  • Access point name and account ID are validated during parsing
  • partition is propagated through the call chain and stored in the variant

Formatting (format_to_string()):

  • Implemented for AccessPoint and Outpost using the stored partition field
  • Full roundtrip fidelity for all three AWS partitions

crates/s3s-fs/src/s3.rs

  • Two match CopySource sites: added CopySource::Outpost { .. } arm returning NotImplemented

Test Coverage

Tests expanded from 31 → 48, all passing.

Category Count Coverage
Bucket format 4 Basic parse, leading slash + percent decode, versionId, format, no-key error
Access Point ARN 14 Basic parse (partition asserted), versionId, URL-encoded ARN, leading slash, aws-cn/aws-us-gov partitions, format, roundtrip (aws/cn/gov), key with special chars/spaces
Outpost ARN 5 Basic parse (partition asserted), versionId, format, roundtrip (aws/cn)
Access point name validation 8 Valid names, too short/long, uppercase, leading/trailing/consecutive hyphens, special chars, invalid name in ARN
Account ID validation 6 Valid IDs, wrong length, non-digits, invalid ID in ARN
Other error paths 11 Missing ARN parts, bad partition/service/region, missing /object/ delimiter, empty resource components, invalid encoding

Quality

cargo test -p s3s --lib dto::copy_source   # 48/48 passed
cargo clippy -p s3s -p s3s-fs -p s3s-aws -- -D warnings  # clean

- Add `Outpost` variant to `CopySource` enum with `partition`, `region`,
  `account_id`, `outpost_id`, `key`, and `version_id` fields
- Add `partition` field to `AccessPoint` variant for full roundtrip fidelity
  across all AWS partitions (aws, aws-cn, aws-us-gov)
- Add `check_access_point_name()`: validates 3-63 chars, lowercase
  alphanumeric + hyphens, no consecutive hyphens, no leading/trailing hyphens
- Add `check_account_id()`: validates exactly 12 ASCII digits
- Add `ParseCopySourceError::InvalidArn`, `::InvalidAccessPointName`,
  `::InvalidAccountId` error variants
- Implement `format_to_string()` for `AccessPoint` and `Outpost` using stored
  partition for correct ARN reconstruction
- Expand test suite from 31 to 48 tests covering parse, format, roundtrip,
  and validation edge cases for all three CopySource formats

Co-authored-by: GitHub Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings March 1, 2026 15:20
@codecov
Copy link

codecov bot commented Mar 1, 2026

Codecov Report

❌ Patch coverage is 92.84468% with 41 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/s3s/src/dto/copy_source.rs 92.84% 15 Missing and 26 partials ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for parsing and formatting ARN-based x-amz-copy-source values (Access Point and S3 on Outposts) in the s3s DTO layer, enabling CopyObject/UploadPartCopy callers to accept these AWS-defined header formats.

Changes:

  • Extended CopySource to represent Access Point ARNs (with partition + versionId) and added a new Outpost ARN variant.
  • Implemented ARN parsing/validation (partition/service/region/account-id, access point name checks) and formatting for the new variants.
  • Updated s3s-fs to explicitly reject Outpost copy sources with NotImplemented (matching existing AccessPoint behavior).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
crates/s3s/src/dto/copy_source.rs Adds new CopySource variants, ARN parsing/validation helpers, formatting, and expanded unit tests.
crates/s3s-fs/src/s3.rs Treats CopySource::Outpost as NotImplemented in filesystem backend copy paths.

Nugine added 2 commits March 1, 2026 23:37
- Add encode_path() helper that URL-encodes path segments while preserving / separators
- Update format_to_string() for all three variants (Bucket, AccessPoint, Outpost) to use encode_path(key) and urlencoding::encode(version_id)
- Add error branch tests covering InvalidBucketName, InvalidKey (bucket and outpost), InvalidEncoding (version_id), and InvalidArn (outpost bad resource prefix)
- Add encoded roundtrip tests verifying parse -> format_to_string preserves URL-encoded keys with spaces and special characters
@Nugine Nugine added this pull request to the merge queue Mar 1, 2026
Merged via the queue into main with commit 8c19396 Mar 1, 2026
18 checks passed
@Nugine Nugine deleted the feat/access-point branch March 1, 2026 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants