Skip to content

Commit f88b7cf

Browse files
authored
Bucket path style (#99)
* Remove path-style feature, add a bucket flag * Add configuration methods, closes #96 * Add BTC and ETH addresses * Allow specifying credentials env vars * Run simple_crud with tests * Add secrets to actions
1 parent 5457ea7 commit f88b7cf

File tree

8 files changed

+229
-86
lines changed

8 files changed

+229
-86
lines changed

.github/workflows/rust.yml

+12-8
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@ name: build
22

33
on:
44
push:
5-
branches: [ master ]
5+
branches: [master]
66
pull_request:
7-
branches: [ master ]
7+
branches: [master]
88

99
jobs:
1010
build:
11-
1211
runs-on: ubuntu-latest
1312

1413
steps:
15-
- uses: actions/checkout@v2
16-
- name: Build
17-
run: cargo build --verbose
18-
- name: Run tests
19-
run: cargo test --verbose
14+
- uses: actions/checkout@v2
15+
- name: Build
16+
run: cargo build --verbose
17+
- name: Run tests
18+
run: cargo test --verbose
19+
- name: Run simple_crud
20+
env:
21+
EU_AWS_ACCESS_KEY_ID: ${{ secrets.EU_AWS_ACCESS_KEY_ID }}
22+
EU_AWS_SECRET_ACCESS_KEY: ${{ secrets.EU_AWS_SECRET_ACCESS_KEY }}
23+
run: cargo run --bin simple_crud

README.md

+20-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
Rust library for working with Amazon S3 or arbitrary S3 compatible APIs, fully compatible with **async/await** and `futures ^0.3`
1010

11+
### Support further development
12+
13+
+ BTC - `3QQdtQGSMStTWEBhe65hPiAWJekXH8n26o`
14+
+ ETH - `0x369Fd06ACc25CCfE0A28BE40018cF3aC38AcdcB6`
15+
1116
### Intro
1217

1318
Modest interface towards Amazon S3, as well as S3 compatible object storage APIs such as Wasabi, Yandex or Minio.
@@ -18,6 +23,10 @@ a `PUT` presigned URL, meaning they can upload to a specific key in S3 for the d
1823

1924
**[AWS, Yandex and Custom (Minio) Example](https://github.com/durch/rust-s3/blob/master/s3/bin/simple_crud.rs)**
2025

26+
#### Path or subdomain style URLs and headers
27+
28+
`Bucket` struct provides constructors for `path-style` paths, `subdomain` style is the default. `Bucket` exposes methods for configuring and accessing `path-style` configuration.
29+
2130
#### Presign
2231

2332
| | |
@@ -85,26 +94,30 @@ while `tokio` methods are generic over `tokio::io::AsyncReadExt`.
8594

8695
```toml
8796
[dependencies]
88-
rust-s3 = "0.22.8"
97+
rust-s3 = "0.22.11"
8998
```
9099

91-
#### Disable SSL verification for endpoints, useful for custom regions
100+
#### Features
101+
102+
##### Disable SSL verification for endpoints, useful for custom regions
92103

93104
```toml
94105
[dependencies]
95-
rust-s3 = {version = "0.22.8", features = ["no-verify-ssl"]}
106+
rust-s3 = {version = "0.22.11", features = ["no-verify-ssl"]}
96107
```
97108

98-
#### Fail on HTTP error responses
109+
##### Fail on HTTP error responses
99110

100111
```toml
101112
[dependencies]
102-
rust-s3 = {version = "0.22.8", features = ["fail-on-err"]}
113+
rust-s3 = {version = "0.22.11", features = ["fail-on-err"]}
103114
```
104115

105-
#### Use path style addressing, needed for Minio compatibility
116+
##### Different SSL backends
117+
118+
Default is `reqwest/native-tls`, it is possible to switch to `reqwest/rustls-tls` which is more portable
106119

107120
```toml
108121
[dependencies]
109-
rust-s3 = {version = "0.22.8", features = ["path-style"]}
122+
rust-s3 = {version = "0.22.11", features = ["rustls-tls"]}
110123
```

aws-creds/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aws-creds"
3-
version = "0.22.1"
3+
version = "0.22.2"
44
authors = ["Drazen Urch"]
55
description = "Tiny Rust library for working with Amazon IAM credential,s, supports `s3` crate"
66
repository = "https://github.com/durch/rust-s3"
@@ -15,7 +15,7 @@ name = "awscreds"
1515
path = "src/lib.rs"
1616

1717
[dependencies]
18-
simpl = "0.1.0-alpha"
18+
simpl = "0.1.0"
1919
dirs = "2.0.2"
2020
rust-ini = "0.15.2"
2121
tokio = "0.2.20"

aws-creds/src/credentials.rs

+46-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::{AwsCredsError, Result};
22
use ini::Ini;
33
use std::collections::HashMap;
44
use std::env;
5+
use std::str::FromStr;
56

67
/// AWS access credentials: access key, secret key, and optional token.
78
///
@@ -95,7 +96,7 @@ impl Credentials {
9596
secret_key: None,
9697
security_token: None,
9798
session_token: None,
98-
_private: ()
99+
_private: (),
99100
})
100101
}
101102

@@ -108,8 +109,7 @@ impl Credentials {
108109
session_token: Option<&str>,
109110
profile: Option<&str>,
110111
) -> Result<Credentials> {
111-
112-
let security_token = if let Some(security_token) = security_token{
112+
let security_token = if let Some(security_token) = security_token {
113113
Some(security_token.to_string())
114114
} else {
115115
None
@@ -152,14 +152,20 @@ impl Credentials {
152152
}
153153
}
154154

155-
pub fn from_env() -> Result<Credentials> {
156-
let access_key = env::var("AWS_ACCESS_KEY_ID")?;
157-
let secret_key = env::var("AWS_SECRET_ACCESS_KEY")?;
158-
let security_token = match env::var("AWS_SECURITY_TOKEN") {
155+
pub fn from_env_specific(
156+
access_key_var: Option<&str>,
157+
secret_key_var: Option<&str>,
158+
security_token_var: Option<&str>,
159+
session_token_var: Option<&str>,
160+
) -> Result<Credentials> {
161+
let access_key = from_env_with_default(access_key_var, "AWS_ACCESS_KEY_ID")?;
162+
let secret_key = from_env_with_default(secret_key_var, "AWS_SECRET_ACCESS_KEY")?;
163+
164+
let security_token = match from_env_with_default(security_token_var, "AWS_SECURITY_TOKEN") {
159165
Ok(x) => Some(x),
160166
Err(_) => None,
161167
};
162-
let session_token = match env::var("AWS_SESSION_TOKEN") {
168+
let session_token = match from_env_with_default(session_token_var, "AWS_SESSION_TOKEN") {
163169
Ok(x) => Some(x),
164170
Err(_) => None,
165171
};
@@ -172,6 +178,10 @@ impl Credentials {
172178
})
173179
}
174180

181+
pub fn from_env() -> Result<Credentials> {
182+
Credentials::from_env_specific(None, None, None, None)
183+
}
184+
175185
async fn from_instance_metadata() -> Result<Credentials> {
176186
if !Credentials::is_ec2() {
177187
return Err(AwsCredsError::from("Not an EC2 instance"));
@@ -280,3 +290,31 @@ impl Credentials {
280290
})
281291
}
282292
}
293+
294+
fn from_env_with_default(var: Option<&str>, default: &str) -> Result<String> {
295+
if let Some(var) = var {
296+
if let Ok(value) = env::var(var) {
297+
Ok(value)
298+
} else {
299+
match env::var(default) {
300+
Ok(value) => Ok(value),
301+
Err(_) => Err(format!(
302+
"Neither {:?}, nor {} does not exist in the environment",
303+
var, default
304+
)
305+
.as_str()
306+
.into()),
307+
}
308+
}
309+
} else {
310+
match env::var(default) {
311+
Ok(value) => Ok(value),
312+
Err(_) => Err(format!(
313+
"Neither {:?}, nor {} does not exist in the environment",
314+
var, default
315+
)
316+
.as_str()
317+
.into()),
318+
}
319+
}
320+
}

s3/Cargo.toml

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rust-s3"
3-
version = "0.22.10"
3+
version = "0.22.11"
44
authors = ["Drazen Urch", "Nick Stevens"]
55
description = "Tiny Rust library for working with Amazon S3 and compatible object storage APIs"
66
repository = "https://github.com/durch/rust-s3"
@@ -35,7 +35,7 @@ tokio = {version="0.2.13", features=["macros", "io-util", "stream"]}
3535
rand = "0.7.3"
3636
simpl = "0.1.0"
3737
aws-region = "0.21.0"
38-
aws-creds = "0.22.1"
38+
aws-creds = "0.22.2"
3939
log = "0.4.8"
4040
once_cell = "1.3.1"
4141
percent-encoding = "2.1.0"
@@ -44,7 +44,6 @@ percent-encoding = "2.1.0"
4444
default = ["native-tls"]
4545
no-verify-ssl = []
4646
fail-on-err = []
47-
path-style = []
4847
native-tls = ["reqwest/native-tls"]
4948
rustls-tls = ["reqwest/rustls-tls"]
5049

s3/bin/simple_crud.rs

+38-31
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::str;
55

66
use s3::bucket::Bucket;
77
use s3::creds::Credentials;
8-
use s3::S3Error;
98
use s3::region::Region;
9+
use s3::S3Error;
1010

1111
struct Storage {
1212
name: String,
@@ -22,39 +22,45 @@ pub fn main() -> Result<(), S3Error> {
2222
let aws = Storage {
2323
name: "aws".into(),
2424
region: "eu-central-1".parse()?,
25-
credentials: Credentials::from_profile(Some("rust-s3"))?,
25+
// credentials: Credentials::from_profile(Some("rust-s3"))?,
26+
credentials: Credentials::from_env_specific(
27+
Some("EU_AWS_ACCESS_KEY_ID"),
28+
Some("EU_AWS_SECRET_ACCESS_KEY"),
29+
None,
30+
None,
31+
)?,
2632
bucket: "rust-s3-test".to_string(),
2733
location_supported: true,
2834
};
2935

30-
let aws_public = Storage {
31-
name: "aws-public".into(),
32-
region: "eu-central-1".parse()?,
33-
credentials: Credentials::anonymous()?,
34-
bucket: "rust-s3-public".to_string(),
35-
location_supported: true,
36-
};
37-
38-
let minio = Storage {
39-
name: "minio".into(),
40-
region: Region::Custom {
41-
region: "us-east-1".into(),
42-
endpoint: "https://minio.adder.black".into(),
43-
},
44-
credentials: Credentials::from_profile(Some("minio"))?,
45-
bucket: "rust-s3".to_string(),
46-
location_supported: false,
47-
};
48-
49-
let yandex = Storage {
50-
name: "yandex".into(),
51-
region: "ru-central1".parse()?,
52-
credentials: Credentials::from_profile(Some("yandex"))?,
53-
bucket: "soundcloud".to_string(),
54-
location_supported: false,
55-
};
56-
57-
for backend in vec![aws, yandex] {
36+
// let aws_public = Storage {
37+
// name: "aws-public".into(),
38+
// region: "eu-central-1".parse()?,
39+
// credentials: Credentials::anonymous()?,
40+
// bucket: "rust-s3-public".to_string(),
41+
// location_supported: true,
42+
// };
43+
44+
// let minio = Storage {
45+
// name: "minio".into(),
46+
// region: Region::Custom {
47+
// region: "us-east-1".into(),
48+
// endpoint: "https://minio.adder.black".into(),
49+
// },
50+
// credentials: Credentials::from_profile(Some("minio"))?,
51+
// bucket: "rust-s3".to_string(),
52+
// location_supported: false,
53+
// };
54+
55+
// let yandex = Storage {
56+
// name: "yandex".into(),
57+
// region: "ru-central1".parse()?,
58+
// credentials: Credentials::from_profile(Some("yandex"))?,
59+
// bucket: "soundcloud".to_string(),
60+
// location_supported: false,
61+
// };
62+
63+
for backend in vec![aws] {
5864
println!("Running {}", backend.name);
5965
// Create Bucket in REGION for BUCKET
6066
let bucket = Bucket::new(&backend.bucket, backend.region, backend.credentials)?;
@@ -75,7 +81,8 @@ pub fn main() -> Result<(), S3Error> {
7581

7682
// Put a "test_file" with the contents of MESSAGE at the root of the
7783
// bucket.
78-
let (_, code) = bucket.put_object_blocking("test_file", MESSAGE.as_bytes(), "text/plain")?;
84+
let (_, code) =
85+
bucket.put_object_blocking("test_file", MESSAGE.as_bytes(), "text/plain")?;
7986
// println!("{}", bucket.presign_get("test_file", 604801)?);
8087
assert_eq!(200, code);
8188

0 commit comments

Comments
 (0)