Skip to content

Commit

Permalink
feat: Define a public Signer trait for the signing interface
Browse files Browse the repository at this point in the history
  • Loading branch information
carols10cents committed Oct 6, 2023
1 parent 760e0ac commit 66f481a
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 44 deletions.
3 changes: 2 additions & 1 deletion object_store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ walkdir = "2"

# Cloud storage support
base64 = { version = "0.21", default-features = false, features = ["std"], optional = true }
http = { version = "0.2", default_features = false, optional = true }
hyper = { version = "0.14", default-features = false, optional = true }
quick-xml = { version = "0.30.0", features = ["serialize", "overlapped-lists"], optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
Expand All @@ -64,7 +65,7 @@ tokio = { version = "1.25.0", features = ["sync", "macros", "rt", "time", "io-ut
nix = { version = "0.27.1", features = ["fs"] }

[features]
cloud = ["serde", "serde_json", "quick-xml", "hyper", "reqwest", "reqwest/json", "reqwest/stream", "chrono/serde", "base64", "rand", "ring"]
cloud = ["serde", "serde_json", "quick-xml", "dep:http", "hyper", "reqwest", "reqwest/json", "reqwest/stream", "chrono/serde", "base64", "rand", "ring"]
azure = ["cloud"]
gcp = ["cloud", "rustls-pemfile"]
aws = ["cloud"]
Expand Down
36 changes: 1 addition & 35 deletions object_store/src/aws/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,41 +184,7 @@ impl<'a> AwsAuthorizer<'a> {
request.headers_mut().insert(AUTH_HEADER, authorization_val);
}

/// Authorize a request via `method` to `url` valid for the duration specified in `expires_in`
/// by attaching the relevant [AWS SigV4] query parameters.
///
/// [AWS SigV4]: https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html
///
/// # Example
///
/// This example modifies `url` to add the signing parameters needed to enable a user to upload
/// a file to "some-folder/some-file.txt" in the next hour.
///
/// ```
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// use object_store::{aws::{AmazonS3Builder, AwsAuthorizer}, path::Path};
/// use reqwest::Method;
/// use std::time::Duration;
/// use url::Url;
///
/// let region = "us-east-1";
/// let s3 = AmazonS3Builder::new()
/// .with_region(region)
/// .with_bucket_name("my-bucket")
/// .with_access_key_id("my-access-key-id")
/// .with_secret_access_key("my-secret-access-key")
/// .build()?;
/// let credential = s3
/// .credentials()
/// .get_credential()
/// .await?;
/// let authorizer = AwsAuthorizer::new(&credential, "s3", region);
/// let mut url = Url::parse(&s3.path_url(&Path::from("some-folder/some-file.txt")))?;
/// authorizer.sign(Method::PUT, &mut url, Duration::from_secs(60 * 60));
/// # Ok(())
/// # }
/// ```
pub fn sign(&self, method: Method, url: &mut Url, expires_in: Duration) {
pub(crate) fn sign(&self, method: Method, url: &mut Url, expires_in: Duration) {
let date = self.date.unwrap_or_else(Utc::now);
let scope = self.scope(date);

Expand Down
20 changes: 12 additions & 8 deletions object_store/src/aws/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use crate::client::{
};
use crate::config::ConfigValue;
use crate::multipart::{PartId, PutPart, WriteMultiPart};
use crate::signer::Signer;
use crate::{
ClientOptions, GetOptions, GetResult, ListResult, MultipartId, ObjectMeta,
ObjectStore, Path, Result, RetryConfig,
Expand Down Expand Up @@ -210,6 +211,14 @@ impl AmazonS3 {
&self.client.config().credentials
}

/// Create a full URL to the resource specified by `path` with this instance's configuration.
fn path_url(&self, path: &Path) -> String {
self.client.config().path_url(path)
}
}

#[async_trait]
impl Signer for AmazonS3 {
/// Create a URL containing the relevant [AWS SigV4] query parameters that authorize a request
/// via `method` to the resource at `path` valid for the duration specified in `expires_in`.
///
Expand All @@ -222,8 +231,8 @@ impl AmazonS3 {
///
/// ```
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// use object_store::{aws::AmazonS3Builder, path::Path};
/// use reqwest::Method;
/// use object_store::{aws::AmazonS3Builder, path::Path, signer::Signer};
/// use http::Method;
/// use std::time::Duration;
///
/// let region = "us-east-1";
Expand All @@ -242,7 +251,7 @@ impl AmazonS3 {
/// # Ok(())
/// # }
/// ```
pub async fn signed_url(
async fn signed_url(
&self,
method: Method,
path: &Path,
Expand All @@ -260,11 +269,6 @@ impl AmazonS3 {

Ok(url)
}

/// Create a full URL to the resource specified by `path` with this instance's configuration.
fn path_url(&self, path: &Path) -> String {
self.client.config().path_url(path)
}
}

#[async_trait]
Expand Down
2 changes: 2 additions & 0 deletions object_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ pub mod local;
pub mod memory;
pub mod path;
pub mod prefix;
#[cfg(feature = "cloud")]
pub mod signer;
pub mod throttle;

#[cfg(feature = "cloud")]
Expand Down
40 changes: 40 additions & 0 deletions object_store/src/signer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//! Abstraction of signed URL generation for those object store implementations that support it
use crate::{path::Path, Result};
use async_trait::async_trait;
use http::Method;
use std::{fmt, time::Duration};
use url::Url;

/// Universal API to presigned URLs generated from multiple object store services. Not supported by
/// all object store services.
#[async_trait]
pub trait Signer: Send + Sync + fmt::Debug + 'static {
/// Given the intended [`Method`] and [`Path`] to use and the desired length of time for which
/// the URL should be valid, return a signed [`Url`] created with the object store
/// implementation's credentials such that the URL can be handed to something that doesn't have
/// access to the object store's credentials, to allow limited access to the object store.
async fn signed_url(
&self,
method: Method,
path: &Path,
expires_in: Duration,
) -> Result<Url>;
}

0 comments on commit 66f481a

Please sign in to comment.