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

assume role chain parse tree (#632)



* assume role chain parse tree

This commit builds the parsing half of our AssumeRoleProvider implementation. Our implementation decouples
the (fairly complex) task of actually turning a profile file into a series of providers from the (fairly simple)
task if iterating through credential providers and executing them.

The descriptive test cases from the spec have been ported to JSON and some new ones have been added and they cover our implementation fairly exhaustively.

Future commits will implement a named-provider factory, wire up the STS client and actually turn this into a credentials provider.

* assume role chain parse tree

This commit builds the parsing half of our AssumeRoleProvider implementation. Our implementation decouples
the (fairly complex) task of actually turning a profile file into a series of providers from the (fairly simple)
task if iterating through credential providers and executing them.

The descriptive test cases from the spec have been ported to JSON and some new ones have been added and they cover our implementation fairly exhaustively.

Future commits will implement a named-provider factory, wire up the STS client and actually turn this into a credentials provider.

* Update aws/rust-runtime/aws-auth-providers/src/profile/repr.rs

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

* Deal with the aws-auth-providers package being special

* add copyright header

* update changelog

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>
parent 68984dc4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ vNext (Month Day Year)

**New This Week**
- (When complete) Add profile file provider for region (#594, #xyz)
- Add AssumeRoleProvider parser implementation. (#632)

v0.19 (August 3rd, 2021)
------------------------
+2 −0
Original line number Diff line number Diff line
@@ -11,3 +11,5 @@ members = [
    "aws-sig-auth",
    "aws-types"
]

exclude = ["aws-auth-providers"]
+16 −0
Original line number Diff line number Diff line
[package]
name = "aws-auth-providers"
version = "0.1.0"
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>", "Russell Cohen <rcoh@amazon.com>"]
edition = "2018"

[dependencies]
aws-auth = { path = "../../sdk/build/aws-sdk/aws-auth" }
aws-types = { path = "../../sdk/build/aws-sdk/aws-types" }
aws-sdk-sts = { path = "../../sdk/build/aws-sdk/sts"}
aws-hyper = { path = "../../sdk/build/aws-sdk/aws-hyper"}
tracing = "0.1"

[dev-dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
+6 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

pub mod profile;
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

//! Profile File Based Providers
//!
//! Profile file based providers combine two pieces:
//!
//! 1. Parsing and resolution of the assume role chain
//! 2. A user-modifiable hashmap of provider name to provider.
//!
//! Profile file based providers first determine the chain of providers that will be used to load
//! credentials. After determining and validating this chain, a `Vec` of providers will be created.
//!
//! Each subsequent provider will provide boostrap providers to the next provider in order to load
//! the final credentials.
//!
//! This module contains two sub modules:
//! - `repr` which contains an abstract representation of a provider chain and the logic to
//! build it from `~/.aws/credentials` and `~/.aws/config`.
//! - `exec` which contains a chain representation of providers to implement passing bootstrapped credentials
//! through a series of providers.
use std::borrow::Cow;
use std::error::Error;
use std::fmt::{Display, Formatter};

use aws_types::os_shim_internal::{Env, Fs};
use aws_types::profile::ProfileParseError;

mod exec;
mod repr;

#[doc(hidden)]
pub fn load_profile() -> Result<(), Box<dyn Error>> {
    // remove the non-usage warnings until we're actually using this module
    let _ = repr::resolve_chain(&aws_types::profile::load(&Fs::real(), &Env::real())?)?;
    Ok(())
}

#[derive(Debug)]
#[non_exhaustive]
pub enum ProfileFileError {
    CouldNotParseProfile(ProfileParseError),
    CredentialLoop {
        profiles: Vec<String>,
        next: String,
    },
    MissingCredentialSource {
        profile: String,
        message: Cow<'static, str>,
    },
    InvalidCredentialSource {
        profile: String,
        message: Cow<'static, str>,
    },
    MissingProfile {
        profile: String,
        message: Cow<'static, str>,
    },
}

impl Display for ProfileFileError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ProfileFileError::CouldNotParseProfile(err) => {
                write!(f, "could not parse profile file: {}", err)
            }
            ProfileFileError::CredentialLoop { profiles, next } => write!(
                f,
                "profile formed an infinite loop. first we loaded {:?}, \
            then attempted to reload {}",
                profiles, next
            ),
            ProfileFileError::MissingCredentialSource { profile, message } => {
                write!(f, "missing credential source in `{}`: {}", profile, message)
            }
            ProfileFileError::InvalidCredentialSource { profile, message } => {
                write!(f, "invalid credential source in `{}`: {}", profile, message)
            }
            ProfileFileError::MissingProfile { profile, message } => {
                write!(f, "profile `{}` was not defined: {}", profile, message)
            }
        }
    }
}

impl Error for ProfileFileError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            ProfileFileError::CouldNotParseProfile(err) => Some(err),
            _ => None,
        }
    }
}
Loading