Repository: rusoto/rusoto (language: rust)

Issue:
0.33 breaks STS with EC2
Consider the following code, which used to work (modulo `new_with` vs `new` and such) in 0.32:
```rust
extern crate rusoto_core;
extern crate rusoto_ec2;
extern crate rusoto_sts;

use rusoto_core::request::HttpClient;
use rusoto_core::Region;
use rusoto_ec2::Ec2Client;
use rusoto_sts::{StsAssumeRoleSessionCredentialsProvider, StsClient};

fn main() {
    let sts = StsClient::new(Region::UsEast1);
    let provider = StsAssumeRoleSessionCredentialsProvider::new(
        sts,
        "arn:aws:sts::1122334455:role/myrole".to_owned(),
        "session-name".to_owned(),
        None,
        None,
        None,
        None,
    );

    Ec2Client::new_with(HttpClient::new().unwrap(), provider, Region::default());
}
```
This no longer compiles since `rusoto_sts::custom::credential::StsSessionCredentialsClient` is neither `Send` nor `Sync`, which `Ec2Client::new_with` now requires.


Discussion / hints:
Oops! That should be a relatively easy fix though.

Would be great to also add at least a doc test for this so that we prevent regress again.
I think this basically breaks all use of STS, so probably something that should be relatively high priority. I'd be happy to give it a shot if you could give some guidance on what would need to be changed.
That‘d be fantastic! I‘ll try to provide some guidance later today.
Okay, so here we go for initial mentoring instructions!

- The relevant source code can be found in [rusoto/services/sts/src/custom/credential.rs](https://github.com/rusoto/rusoto/blob/master/rusoto/services/sts/src/custom/credential.rs)
- This file includes multiple different credential provider implementations (such as `StsAssumeRoleSessionCredentialsProvider`), that all wrap an `StsClient` in the form a boxed trait object (grep for `Box<StsSessionCredentialsClient>`)
- In order to make all these providers `Send + Sync`, we need to change the trait object to also include the `Send` and `Sync` markers, in other words, change the box to be `Box<StsSessionCredentialsClient + Send + Sync>`
- I don't see any direct knock-on effects for this change, but it could be that changing it results in a bunch of cascading type errors that need to be fixed up (likely by adding `Send` and `Sync` bounds as well)
- After this is done, it would be great to ensure that we don't regress, by adding assertions to check that all the credential providers implement `Sync` and `Send`. You can see an example of how this is done here: https://github.com/rusoto/rusoto/blob/master/rusoto/core/src/future.rs#L121

Let me know if this works for you @jonhoo, or whether you need more detail for any of the steps!
@srijs fixed in #1110.

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index 649ce8fe27e..c332e3452aa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ cache:
     - ~/.cargo
 # run builds for all the trains (and more)
 rust:
-  - 1.25.0 # test against minimum Rust version supported
+  - 1.26.1 # test against minimum Rust version supported
   - stable
   - beta
   - nightly
diff --git a/README.md b/README.md
index 8ae7135d60d..270f6d6331a 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ You may be looking for:
 
 ## Requirements
 
-Rust 1.25.0 or later is required.
+Rust 1.26.1 or later is required.
 
 On Linux, OpenSSL is required.
 
diff --git a/rusoto/core/README.md b/rusoto/core/README.md
index e22a50f582c..3e9318c4872 100644
--- a/rusoto/core/README.md
+++ b/rusoto/core/README.md
@@ -31,7 +31,7 @@ You may be looking for:
 
 ## Requirements
 
-Rust 1.25.0 or later is required.
+Rust 1.26.1 or later is required.
 
 On Linux, OpenSSL is required.
 
diff --git a/rusoto/services/sts/src/custom/credential.rs b/rusoto/services/sts/src/custom/credential.rs
index 9576a360a23..2e258ed461f 100644
--- a/rusoto/services/sts/src/custom/credential.rs
+++ b/rusoto/services/sts/src/custom/credential.rs
@@ -91,7 +91,7 @@ impl<T> StsSessionCredentialsClient for T where T: Sts {
 /// You will need to ensure the provider has a valid code each time you
 /// acquire a new STS token.
 pub struct StsSessionCredentialsProvider {
-    sts_client: Box<StsSessionCredentialsClient>,
+    sts_client: Box<StsSessionCredentialsClient + Send + Sync>,
     session_duration: Duration,
     mfa_serial: Option<String>,
     mfa_code: Option<String>,
@@ -179,7 +179,7 @@ impl ProvideAwsCredentials for StsSessionCredentialsProvider {
 /// You will need to ensure the provider has a valid code each time you
 /// acquire a new STS token.
 pub struct StsAssumeRoleSessionCredentialsProvider {
-    sts_client: Box<StsSessionCredentialsClient>,
+    sts_client: Box<StsSessionCredentialsClient + Send + Sync>,
     role_arn: String,
     session_name: String,
     external_id: Option<String>,
@@ -285,7 +285,7 @@ impl ProvideAwsCredentials for StsAssumeRoleSessionCredentialsProvider {
 /// [AwsCredentials](../rusoto_credential/struct.AwsCredentials.html) provider that calls
 /// `AssumeRoleWithWebIdentity` using the provided [StsClient](struct.StsClient.html).
 pub struct StsWebIdentityFederationSessionCredentialsProvider {
-    sts_client: Box<StsSessionCredentialsClient>,
+    sts_client: Box<StsSessionCredentialsClient + Send + Sync>,
     wif_token: String,
     wif_provider: Option<String>,
     role_arn: String,
@@ -386,3 +386,12 @@ impl ProvideAwsCredentials for StsWebIdentityFederationSessionCredentialsProvide
         self.assume_role_with_web_identity()
     }
 }
+
+#[test]
+fn sts_futures_are_send() {
+    fn is_send<T: Send>() {}
+
+    is_send::<StsSessionCredentialsProvider>();
+    is_send::<StsAssumeRoleSessionCredentialsProvider>();
+    is_send::<StsWebIdentityFederationSessionCredentialsProvider>();
+}


Test patch:
diff --git a/integration_tests/tests/sts.rs b/integration_tests/tests/sts.rs
index d3136cb795c..f6ee245186b 100644
--- a/integration_tests/tests/sts.rs
+++ b/integration_tests/tests/sts.rs
@@ -3,14 +3,17 @@
 extern crate futures;
 extern crate rusoto_core;
 extern crate rusoto_sts;
+extern crate rusoto_ec2;
 
 use futures::Future;
 
 use rusoto_sts::{Sts, StsClient};
 use rusoto_sts::{AssumeRoleRequest, AssumeRoleError};
 use rusoto_sts::{GetSessionTokenRequest, GetSessionTokenError};
-use rusoto_sts::StsSessionCredentialsProvider;
+use rusoto_sts::{StsSessionCredentialsProvider, StsAssumeRoleSessionCredentialsProvider};
 use rusoto_core::{ProvideAwsCredentials, Region};
+use rusoto_core::request::HttpClient;
+use rusoto_ec2::Ec2Client;
 
 #[test]
 fn main() {
@@ -46,4 +49,16 @@ fn main() {
         Err(e) => panic!("sts credentials provider error: {:?}", e),
         Ok(r) => println!("sts credentials provider result: {:?}", r)
     }
+
+    // check that it's possible to create a new ec2 client with sts
+    let provider = StsAssumeRoleSessionCredentialsProvider::new(
+        StsClient::new(Region::UsEast1),
+        "arn:aws:sts::1122334455:role/myrole".to_owned(),
+        "session-name".to_owned(),
+        None,
+        None,
+        None,
+        None,
+    );
+    Ec2Client::new_with(HttpClient::new().unwrap(), provider, Region::default());
 }