Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

object_store: Add support for requester pays buckets #6768

Merged
merged 5 commits into from
Nov 22, 2024

Conversation

kylebarron
Copy link
Contributor

Which issue does this PR close?

Closes #6716.

Rationale for this change

Support for AWS S3 requester pays buckets. Open data is commonly provided through these buckets because it allows data providers to pay only for the cost of the data and not for the data egress.

What changes are included in this PR?

  • Add new public AmazonS3Builder::with_request_payer config option
  • Include the required header when authorizing and signing requests via the AwsAuthorizer

Are there any user-facing changes?

Addition of AmazonS3Builder::with_request_payer

@github-actions github-actions bot added the object-store Object Store Interface label Nov 21, 2024
@kylebarron
Copy link
Contributor Author

I also ran some manual testing locally to ensure it works end-to-end, but not sure if there's any place for them here

#[tokio::test]
async fn test_get_request_payer() {
    let client = AmazonS3Builder::new()
        .with_access_key_id("REDACTED")
        .with_secret_access_key("REDACTED")
        .with_bucket_name("naip-visualization")
        .with_region("us-west-2")
        .with_request_payer(true)
        .build()
        .unwrap();
    let resp = client.get(&"readme.txt".into()).await.unwrap();
    let buf = resp.bytes().await.unwrap();
    let s = String::from_utf8(buf.into()).unwrap();
    dbg!(s);
}

ran successfully and gave:

successes:

---- aws::client::tests::test_get_request_payer stdout ----
[src/aws/client.rs:908:9] s = "Visualization NAIP on AWS\n\nThe National Agriculture Imagery Program (NAIP) acquires aerial imagery during the agricultural growing seasons in the continental United States. This leaf-on imagery typically ranges from 60 centimeters to 100 centimeters in resolution. In the naip-visualization Amazon S3 bucket, you’ll find GeoTIFF 3-band RGB imagery at source resolution, which has been compressed, tiled, and cloud-optimized. This data is useful as source for background imagery, or to use to download a subsampled version of the original.\n\nNAIP is administered by t
...

and

#[tokio::test]
async fn test_signed_get_request_payer() {
    let client = AmazonS3Builder::new()
        .with_access_key_id("REDACTED")
        .with_secret_access_key("REDACTED")
        .with_bucket_name("naip-visualization")
        .with_region("us-west-2")
        .with_request_payer(true)
        .build()
        .unwrap();
    let url = client
        .signed_url(Method::GET, &"readme.txt".into(), Duration::from_secs(60))
        .await
        .unwrap();
    dbg!(url.to_string());
}

gave

https://s3.us-west-2.amazonaws.com/naip-visualization/readme.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=REDACTED%2F20241121%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20241121T131723Z&X-Amz-Expires=60&X-Amz-SignedHeaders=host&x-amz-request-payer=requester&X-Amz-Signature=8b9b548bd41b24a0cdf8eacfbccb3364472efdf5ebf5d9cf943e7c6c23e1d3be

which also worked:
image

@kylebarron
Copy link
Contributor Author

I don't think the CI failure is related to my changes.

};

signer.authorize(&mut request, None);
assert_eq!(request.headers().get(&AUTHORIZATION).unwrap(), "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220806/us-east-1/ec2/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=a3c787a7ed37f7fdfbfd2d7056a3d7c9d85e6d52a2bfbec73793c0be6e7862d4")
}

#[test]
fn test_sign_with_signed_payload_request_payer() {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@tustvold tustvold left a comment

Choose a reason for hiding this comment

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

Just a minor question, otherwise looks good thank you

}

static DATE_HEADER: HeaderName = HeaderName::from_static("x-amz-date");
static HASH_HEADER: HeaderName = HeaderName::from_static("x-amz-content-sha256");
static TOKEN_HEADER: HeaderName = HeaderName::from_static("x-amz-security-token");
static REQUEST_PAYER_HEADER: HeaderName = HeaderName::from_static("x-amz-request-payer");
static REQUEST_PAYER_HEADER_VALUE: HeaderValue = HeaderValue::from_static("requester");
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there other values for this header? Wondering if it should be an enumeration instead of a boolean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tustvold tustvold merged commit def94a8 into apache:master Nov 22, 2024
14 checks passed
@kylebarron kylebarron deleted the kyle/request-payer branch November 22, 2024 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
object-store Object Store Interface
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for AWS Requester Pays buckets
2 participants