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

0.31.0 #268

Merged
merged 9 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions aws-creds/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aws-creds"
version = "0.28.0"
version = "0.29.1"
authors = ["Drazen Urch"]
description = "Tiny Rust library for working with Amazon IAM credential,s, supports `s3` crate"
repository = "https://github.com/durch/rust-s3"
Expand All @@ -15,10 +15,10 @@ name = "awscreds"
path = "src/lib.rs"

[dependencies]
anyhow = "1.0"
thiserror = "1"
dirs = "4"
rust-ini = "0.18"
attohttpc = { version = "0.18", default-features = false, features = ["json"], optional = true }
attohttpc = { version = "0.19", default-features = false, features = ["json"], optional = true }
url = "2"
serde-xml-rs = "0.5"
serde = "1"
Expand Down
42 changes: 19 additions & 23 deletions aws-creds/src/credentials.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![allow(dead_code)]
use anyhow::{anyhow, bail, Result};
use crate::error::CredentialsError;
use ini::Ini;
use serde_xml_rs as serde_xml;
use std::collections::HashMap;
Expand Down Expand Up @@ -168,7 +168,7 @@ fn http_get(url: &str) -> attohttpc::Result<attohttpc::Response> {

impl Credentials {
#[cfg(feature = "http-credentials")]
pub fn from_sts_env(session_name: &str) -> Result<Credentials> {
pub fn from_sts_env(session_name: &str) -> Result<Credentials, CredentialsError> {
let role_arn = env::var("AWS_ROLE_ARN")?;
let web_identity_token_file = env::var("AWS_WEB_IDENTITY_TOKEN_FILE")?;
let web_identity_token = std::fs::read_to_string(web_identity_token_file)?;
Expand All @@ -180,7 +180,7 @@ impl Credentials {
role_arn: &str,
session_name: &str,
web_identity_token: &str,
) -> Result<Credentials> {
) -> Result<Credentials, CredentialsError> {
let url = Url::parse_with_params(
"https://sts.amazonaws.com/",
&[
Expand Down Expand Up @@ -220,11 +220,11 @@ impl Credentials {
}

#[cfg(feature = "http-credentials")]
pub fn default() -> Result<Credentials> {
pub fn default() -> Result<Credentials, CredentialsError> {
Credentials::new(None, None, None, None, None)
}

pub fn anonymous() -> Result<Credentials> {
pub fn anonymous() -> Result<Credentials, CredentialsError> {
Ok(Credentials {
access_key: None,
secret_key: None,
Expand All @@ -242,7 +242,7 @@ impl Credentials {
security_token: Option<&str>,
session_token: Option<&str>,
profile: Option<&str>,
) -> Result<Credentials> {
) -> Result<Credentials, CredentialsError> {
if access_key.is_some() {
return Ok(Credentials {
access_key: access_key.map(|s| s.to_string()),
Expand All @@ -263,7 +263,7 @@ impl Credentials {
secret_key_var: Option<&str>,
security_token_var: Option<&str>,
session_token_var: Option<&str>,
) -> Result<Credentials> {
) -> Result<Credentials, CredentialsError> {
let access_key = from_env_with_default(access_key_var, "AWS_ACCESS_KEY_ID")?;
let secret_key = from_env_with_default(secret_key_var, "AWS_SECRET_ACCESS_KEY")?;

Expand All @@ -277,12 +277,12 @@ impl Credentials {
})
}

pub fn from_env() -> Result<Credentials> {
pub fn from_env() -> Result<Credentials, CredentialsError> {
Credentials::from_env_specific(None, None, None, None)
}

#[cfg(feature = "http-credentials")]
pub fn from_instance_metadata() -> Result<Credentials> {
pub fn from_instance_metadata() -> Result<Credentials, CredentialsError> {
#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Response {
Expand All @@ -301,7 +301,7 @@ impl Credentials {
}
Err(_) => {
if !is_ec2() {
bail!("Not an AWS instance")
return Err(CredentialsError::NotEc2);
}

let role = attohttpc::get(
Expand All @@ -327,22 +327,22 @@ impl Credentials {
})
}

pub fn from_profile(section: Option<&str>) -> Result<Credentials> {
let home_dir = dirs::home_dir().ok_or_else(|| anyhow!("Invalid home dir"))?;
pub fn from_profile(section: Option<&str>) -> Result<Credentials, CredentialsError> {
let home_dir = dirs::home_dir().ok_or(CredentialsError::HomeDir)?;
let profile = format!("{}/.aws/credentials", home_dir.display());
let conf = Ini::load_from_file(&profile)?;
let section = section.unwrap_or("default");
let data = conf
.section(Some(section))
.ok_or_else(|| anyhow!("Config missing"))?;
.ok_or(CredentialsError::ConfigNotFound)?;
let access_key = data
.get("aws_access_key_id")
.map(|s| s.to_string())
.ok_or_else(|| anyhow!("Missing aws_access_key_id section"))?;
.ok_or(CredentialsError::ConfigMissingAccessKeyId)?;
let secret_key = data
.get("aws_secret_access_key")
.map(|s| s.to_string())
.ok_or_else(|| anyhow!("Missing aws_secret_access_key section"))?;
.ok_or(CredentialsError::ConfigMissingSecretKey)?;
let credentials = Credentials {
access_key: Some(access_key),
secret_key: Some(secret_key),
Expand All @@ -353,15 +353,11 @@ impl Credentials {
}
}

fn from_env_with_default(var: Option<&str>, default: &str) -> Result<String> {
fn from_env_with_default(var: Option<&str>, default: &str) -> Result<String, CredentialsError> {
let val = var.unwrap_or(default);
env::var(val).or_else(|_e| env::var(val)).map_err(|_| {
anyhow!(
"Neither {:?}, nor {} does not exist in the environment",
var,
default
)
})
env::var(val)
.or_else(|_e| env::var(val))
.map_err(|_| CredentialsError::MissingEnvVar(val.to_string(), default.to_string()))
}

fn is_ec2() -> bool {
Expand Down
30 changes: 30 additions & 0 deletions aws-creds/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum CredentialsError {
#[error("Not an AWS instance")]
NotEc2,
#[error("Config not found")]
ConfigNotFound,
#[error("Missing aws_access_key_id section in config")]
ConfigMissingAccessKeyId,
#[error("Missing aws_access_key_id section in config")]
ConfigMissingSecretKey,
#[error("Neither {0}, nor {1} exists in the environment")]
MissingEnvVar(String, String),
#[cfg(feature = "http-credentials")]
#[error("attohttpc: {0}")]
Atto(#[from] attohttpc::Error),
#[error("ini: {0}")]
Ini(#[from] ini::Error),
#[error("serde_xml: {0}")]
SerdeXml(#[from] serde_xml_rs::Error),
#[error("url parse: {0}")]
UrlParse(#[from] url::ParseError),
#[error("io: {0}")]
Io(#[from] std::io::Error),
#[error("env var: {0}")]
Env(#[from] std::env::VarError),
#[error("Invalid home dir")]
HomeDir,
}
1 change: 1 addition & 0 deletions aws-creds/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ extern crate serde_derive;

mod credentials;
pub use credentials::*;
pub mod error;
4 changes: 2 additions & 2 deletions aws-region/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aws-region"
version = "0.23.5"
version = "0.24.1"
authors = ["Drazen Urch"]
description = "Tiny Rust library for working with Amazon AWS regions, supports `s3` crate"
repository = "https://github.com/durch/rust-s3"
Expand All @@ -15,4 +15,4 @@ name = "awsregion"
path = "src/lib.rs"

[dependencies]
anyhow = "1.0"
thiserror = "1"
4 changes: 4 additions & 0 deletions aws-region/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum RegionError {}
1 change: 1 addition & 0 deletions aws-region/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

mod region;
pub use region::*;
pub mod error;
6 changes: 2 additions & 4 deletions aws-region/src/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
use std::fmt;
use std::str::{self, FromStr};

use anyhow::Result;

/// AWS S3 [region identifier](https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region),
/// passing in custom values is also possible, in that case it is up to you to pass a valid endpoint,
/// otherwise boom will happen :)
Expand Down Expand Up @@ -135,9 +133,9 @@ impl fmt::Display for Region {
}

impl FromStr for Region {
type Err = anyhow::Error;
type Err = std::str::Utf8Error;

fn from_str(s: &str) -> Result<Self> {
fn from_str(s: &str) -> Result<Self, Self::Err> {
use self::Region::*;
match s {
"us-east-1" => Ok(UsEast1),
Expand Down
24 changes: 14 additions & 10 deletions s3/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rust-s3"
version = "0.31.0" # Not published
version = "0.31.0"
authors = ["Drazen Urch"]
description = "Rust library for working with Amazon S3 and compatible object storage APIs"
repository = "https://github.com/durch/rust-s3"
Expand All @@ -21,16 +21,18 @@ path = "src/lib.rs"
[dependencies]
async-std = { version = "1", optional = true }
async-trait = "0.1"
attohttpc = { version = "0.18", optional = true, default-features = false }
aws-creds = { version = "0.28", default-features = false }
aws-region = "0.23"
attohttpc = { version = "0.19", optional = true, default-features = false }
aws-creds = { version = "0.29", default-features = false }
# aws-creds = { path = "../aws-creds", default-features = false }
aws-region = "0.24"
# aws-region = {path = "../aws-region"}
base64 = "0.13"
cfg-if = "1"
time = { version = "0.3", features = ["formatting", "macros"] }
futures-io = { version = "0.3", optional = true }
futures-util = { version = "0.3", optional = true, features = ["io"] }
hex = "0.4"
hmac = "0.11"
hmac = "0.12"
http = "0.2"
log = "0.4"
maybe-async = { version = "0.2" }
Expand All @@ -40,13 +42,13 @@ reqwest = { version = "0.11", default-features = false, features = ["json", "str
serde = "1"
serde_derive = "1"
serde-xml-rs = "0.5"
sha2 = "0.9"
anyhow = "1"
sha2 = "0.10"
thiserror = "1"
surf = { version = "2", optional = true, default-features = false, features = ["h1-client-rustls"] }
tokio = { version = "1", features = ["io-util"], optional = true, default-features = false }
tokio-stream = { version = "0.1", optional = true }
url = "2"
minidom = { version = "0.13", optional = true }
minidom = { version = "0.14", optional = true }

block_on_proc = { version = "0.2", optional = true }

Expand All @@ -67,6 +69,8 @@ tags = ["minidom"]
[dev-dependencies]
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros", "fs"] }
async-std = { version = "1", features = ["attributes"] }
uuid = { version = "0.8", features = ["v4"] }
uuid = { version = "1", features = ["v4"] }
env_logger = "0.9"
aws-creds = { version = "0.28", features = ["http-credentials"] }
aws-creds = { version = "0.29", default-features = false }
# aws-creds = { path = "../aws-creds", features = ["http-credentials"] }
anyhow = "1"
2 changes: 1 addition & 1 deletion s3/bin/simple_crud.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub fn main() -> Result<(), S3Error> {
// Put a "test_file" with the contents of MESSAGE at the root of the
// bucket.
let (_, code) = bucket.put_object_blocking("test_file", MESSAGE.as_bytes())?;
// println!("{}", bucket.presign_get("test_file", 604801)?);
// println!("{}", bucket.presign_get("test_file", 604801, None)?);
assert_eq!(200, code);

// Get the "test_file" contents and make sure that the returned message
Expand Down
19 changes: 8 additions & 11 deletions s3/src/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ use attohttpc::header::HeaderName;

use super::bucket::Bucket;
use super::command::Command;
use crate::error::S3Error;
use time::OffsetDateTime;

use crate::command::HttpMethod;
use crate::request_trait::Request;
use anyhow::anyhow;
use anyhow::Result;
// static CLIENT: Lazy<Client> = Lazy::new(|| {
// if cfg!(feature = "no-verify-ssl") {
// Client::builder()
Expand Down Expand Up @@ -54,7 +53,7 @@ impl<'a> Request for AttoRequest<'a> {
self.path.to_string()
}

fn response(&self) -> Result<Self::Response> {
fn response(&self) -> Result<Self::Response, S3Error> {
// Build headers
let headers = match self.headers() {
Ok(headers) => headers,
Expand Down Expand Up @@ -82,17 +81,15 @@ impl<'a> Request for AttoRequest<'a> {
let response = request.bytes(&self.request_body()).send()?;

if cfg!(feature = "fail-on-err") && !response.status().is_success() {
return Err(anyhow!(
"Request failed with code {}\n{}",
response.status().as_u16(),
response.text()?
));
let status = response.status().as_u16();
let text = response.text()?;
return Err(S3Error::Http(status, text));
}

Ok(response)
}

fn response_data(&self, etag: bool) -> Result<(Vec<u8>, u16)> {
fn response_data(&self, etag: bool) -> Result<(Vec<u8>, u16), S3Error> {
let response = self.response()?;
let status_code = response.status().as_u16();
let headers = response.headers().clone();
Expand All @@ -108,7 +105,7 @@ impl<'a> Request for AttoRequest<'a> {
Ok((body_vec, status_code))
}

fn response_data_to_writer<T: Write>(&self, writer: &mut T) -> Result<u16> {
fn response_data_to_writer<T: Write>(&self, writer: &mut T) -> Result<u16, S3Error> {
let response = self.response()?;

let status_code = response.status();
Expand All @@ -119,7 +116,7 @@ impl<'a> Request for AttoRequest<'a> {
Ok(status_code.as_u16())
}

fn response_header(&self) -> Result<(Self::HeaderMap, u16)> {
fn response_header(&self) -> Result<(Self::HeaderMap, u16), S3Error> {
let response = self.response()?;
let status_code = response.status().as_u16();
let headers = response.headers().clone();
Expand Down
Loading