Unverified Commit 6e3ebaaa authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Implement the "source" side of profile parsing (#594)



* Introduce environment abstraction

* Update region provider to use ProcessEnvironment

* Update credentials provider to use env var abstraction

* implement the "source" side of profile parsing

This commit adds support for the "source" side of profile file parsing:
Given a filesystem/environment, what files should we actually be reading?

* run runtime tests on windows

* Update changelog

* Update ci.yaml

don't run rustfmt on windows

* Apply suggestions from code review

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>

* cr feedback / refactorings to profile source loading

* refactor runtime test job

* Add missing workspace cargo.toml

* Fix working directory issue

* fix windows test for new API

* special case test for windows behavior

* Always compile the tests but conditionally ignore

* Apply suggestions from code review

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>
parent 6342fdc6
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -108,7 +108,11 @@ jobs:
          codegen-test/build/smithyprojections/codegen-test/Cargo.toml
  runtime-tests:
    name: Rust runtime tests
    runs-on: ubuntu-latest
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        runtime: [., ./aws]
    runs-on: ${{ matrix.os }}
    steps:
    - uses: actions/checkout@v2
    - uses: actions/cache@v2
@@ -125,8 +129,21 @@ jobs:
        default: true
    - name: Format Check
      run: rustfmt --check --edition 2018 $(find -name '*.rs' -print)
    - name: execute runtime tests
      run: ./rust-runtime/test.sh
      # windows doesn't support using --check like this
      if: ${{ matrix.os == 'ubuntu-latest' }}
    - name: clippy check
      run: cargo clippy -- -D warnings
      working-directory: ${{ matrix.runtime }}/rust-runtime/
      # don't bother running Clippy twice, it will have the same results on Windows
      if: ${{ matrix.os == 'ubuntu-latest' }}
    - name: run tests
      run: cargo test --all-features
      working-directory: ${{ matrix.runtime }}/rust-runtime/
    - name: generate docs
      run: cargo doc --no-deps --document-private-items
      working-directory: ${{ matrix.runtime }}/rust-runtime/
      env:
        RUSTDOCFLAGS: -D warnings

  generate-sdk:
    name: Generate an AWS SDK
+3 −0
Original line number Diff line number Diff line
@@ -2,6 +2,9 @@

**New This Week**
- :bug: Bugfix: Fix parsing bug where whitespace was stripped when parsing XML (#590)
- Establish common abstraction for environment variables (#594)
- Add windows to the test matrix (#594)
- (When complete) Add profile file provider for region (#594, #xyz)
- :bug: Bugfix: Constrain RFC-3339 timestamp formatting to microsecond precision (#596)

## v0.15 (June 29th 2021)
+13 −0
Original line number Diff line number Diff line
# Note: this workspace exists solely for the convenience of running tests. These packages will all eventually
# end up in the final SDK workspace.
[workspace]

members = [
    "aws-auth",
    "aws-endpoint",
    "aws-http",
    "aws-hyper",
    "aws-inlineable",
    "aws-sig-auth",
    "aws-types"
]
+2 −1
Original line number Diff line number Diff line
@@ -8,8 +8,9 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
smithy-http = { path = "../../../rust-runtime/smithy-http" }
aws-types = { path = "../aws-types" }
tokio = { version = "1", features = ["sync"] }
tracing = "0.1.25"
tracing = "0.1"
zeroize = "1.2.0"

[dev-dependencies]
+31 −40
Original line number Diff line number Diff line
@@ -5,28 +5,17 @@

use crate::provider::{CredentialsError, ProvideCredentials};
use crate::Credentials;
use std::collections::HashMap;
use aws_types::os_shim_internal::Env;
use std::env::VarError;

/// Load Credentials from Environment Variables
pub struct EnvironmentVariableCredentialsProvider {
    env: Box<dyn Fn(&str) -> Result<String, VarError> + Send + Sync>,
    env: Env,
}

impl EnvironmentVariableCredentialsProvider {
    pub fn new() -> Self {
        EnvironmentVariableCredentialsProvider { env: Box::new(var) }
    }

    /// Create a EnvironmentVariable provider from a HashMap for testing
    pub fn for_map(env: HashMap<String, String>) -> Self {
        EnvironmentVariableCredentialsProvider {
            env: Box::new(move |key: &str| {
                env.get(key)
                    .ok_or(VarError::NotPresent)
                    .map(|k| k.to_string())
            }),
        }
        EnvironmentVariableCredentialsProvider { env: Env::real() }
    }
}

@@ -36,19 +25,17 @@ impl Default for EnvironmentVariableCredentialsProvider {
    }
}

fn var(key: &str) -> Result<String, VarError> {
    std::env::var(key)
}

const ENV_PROVIDER: &str = "EnvironmentVariable";

impl ProvideCredentials for EnvironmentVariableCredentialsProvider {
    fn provide_credentials(&self) -> Result<Credentials, CredentialsError> {
        let access_key = (self.env)("AWS_ACCESS_KEY_ID").map_err(to_cred_error)?;
        let secret_key = (self.env)("AWS_SECRET_ACCESS_KEY")
            .or_else(|_| (self.env)("SECRET_ACCESS_KEY"))
        let access_key = self.env.get("AWS_ACCESS_KEY_ID").map_err(to_cred_error)?;
        let secret_key = self
            .env
            .get("AWS_SECRET_ACCESS_KEY")
            .or_else(|_| self.env.get("SECRET_ACCESS_KEY"))
            .map_err(to_cred_error)?;
        let session_token = (self.env)("AWS_SESSION_TOKEN").ok();
        let session_token = self.env.get("AWS_SESSION_TOKEN").ok();
        Ok(Credentials::new(
            access_key,
            secret_key,
@@ -70,15 +57,20 @@ fn to_cred_error(err: VarError) -> CredentialsError {
mod test {
    use super::EnvironmentVariableCredentialsProvider;
    use crate::provider::{CredentialsError, ProvideCredentials};
    use std::collections::HashMap;
    use aws_types::os_shim_internal::Env;

    fn make_provider(vars: &[(&str, &str)]) -> EnvironmentVariableCredentialsProvider {
        EnvironmentVariableCredentialsProvider {
            env: Env::from_slice(vars),
        }
    }

    #[test]
    fn valid_no_token() {
        let mut env = HashMap::new();
        env.insert("AWS_ACCESS_KEY_ID".to_owned(), "access".to_owned());
        env.insert("AWS_SECRET_ACCESS_KEY".to_owned(), "secret".to_owned());

        let provider = EnvironmentVariableCredentialsProvider::for_map(env);
        let provider = make_provider(&[
            ("AWS_ACCESS_KEY_ID", "access"),
            ("AWS_SECRET_ACCESS_KEY", "secret"),
        ]);
        let creds = provider.provide_credentials().expect("valid credentials");
        assert_eq!(creds.session_token(), None);
        assert_eq!(creds.access_key_id(), "access");
@@ -87,12 +79,12 @@ mod test {

    #[test]
    fn valid_with_token() {
        let mut env = HashMap::new();
        env.insert("AWS_ACCESS_KEY_ID".to_owned(), "access".to_owned());
        env.insert("AWS_SECRET_ACCESS_KEY".to_owned(), "secret".to_owned());
        env.insert("AWS_SESSION_TOKEN".to_owned(), "token".to_owned());
        let provider = make_provider(&[
            ("AWS_ACCESS_KEY_ID", "access"),
            ("AWS_SECRET_ACCESS_KEY", "secret"),
            ("AWS_SESSION_TOKEN", "token"),
        ]);

        let provider = EnvironmentVariableCredentialsProvider::for_map(env);
        let creds = provider.provide_credentials().expect("valid credentials");
        assert_eq!(creds.session_token().unwrap(), "token");
        assert_eq!(creds.access_key_id(), "access");
@@ -101,12 +93,12 @@ mod test {

    #[test]
    fn secret_key_fallback() {
        let mut env = HashMap::new();
        env.insert("AWS_ACCESS_KEY_ID".to_owned(), "access".to_owned());
        env.insert("SECRET_ACCESS_KEY".to_owned(), "secret".to_owned());
        env.insert("AWS_SESSION_TOKEN".to_owned(), "token".to_owned());
        let provider = make_provider(&[
            ("AWS_ACCESS_KEY_ID", "access"),
            ("SECRET_ACCESS_KEY", "secret"),
            ("AWS_SESSION_TOKEN", "token"),
        ]);

        let provider = EnvironmentVariableCredentialsProvider::for_map(env);
        let creds = provider.provide_credentials().expect("valid credentials");
        assert_eq!(creds.session_token().unwrap(), "token");
        assert_eq!(creds.access_key_id(), "access");
@@ -115,8 +107,7 @@ mod test {

    #[test]
    fn missing() {
        let env = HashMap::new();
        let provider = EnvironmentVariableCredentialsProvider::for_map(env);
        let provider = make_provider(&[]);
        let err = provider
            .provide_credentials()
            .expect_err("no credentials defined");
Loading