awslabs / aws-sdk-rust

AWS SDK for the Rust Programming Language
https://awslabs.github.io/aws-sdk-rust/
Apache License 2.0
3.04k stars 247 forks source link

example on how to use IAM Auth tokens for RDS access #792

Open c-p-i-o opened 1 year ago

c-p-i-o commented 1 year ago

Describe the issue

This is a request for adding an example on how to correctly use generate-db-auth-token in Rust for DB operations. I followed the conversation as listed here and am able to generate IAM tokens. However, under the covers I'm using sqlx to make connections to a DB. Access works correctly when I use password, however I'm currently unable to get it to work when I use the IAM token. I suspect I probably need to follow what was done in golang?

Links

I looked at the following locations for a working example: https://github.com/awslabs/aws-sdk-rust/tree/main/examples/sts/src/bin and https://docs.aws.amazon.com/sdk-for-rust/latest/dg/rust_sts_code_examples.html but could not find anything.

Velfi commented 1 year ago

@c-p-i-o We don't have a crate for this and we don't plan on releasing something soon. Your idea to follow what the golang SDK does is a good one. I'm guessing that this is just a matter of formatting a string correctly.

@DavidSouther Perhaps this use-case is worthy of an example?

rcoh commented 1 year ago

I agree an end-to-end worked example would be good—in the meantime, this should get you most of the way there: https://docs.rs/aws-sig-auth/0.55.1/aws_sig_auth/#generate-rds-iam-token

lcmgh commented 1 year ago

Stumbled over this issue as https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.html was not helpful for Rust.

lcmgh commented 1 year ago

https://docs.rs/aws-sig-auth/0.55.1/aws_sig_auth/#generate-rds-iam-token

@rcoh Do you know how to go from a AssumeRoleProvider to &Credentials (fn generate_rds_iam_token parameter) ?

fn assume_role_provider(
    proxy: Option<ProxyConnector<HttpConnector>>,
    p: &AwsProfile,
    region: &Region,
    source_profile: &str,
) -> AssumeRoleProvider {
    let inner_provider = aws_config::profile::ProfileFileCredentialsProvider::builder()
        .profile_name(p.source_profile.clone())
        .build();

    match proxy {
        Some(proxy) => {
            let provider_config = ProviderConfig::default().with_tcp_connector(proxy.clone());
            let http_connector = aws_smithy_client::hyper_ext::Adapter::builder().build(proxy);
            AssumeRoleProvider::builder(p.role_arn.clone())
                .region(region.clone())
                .session_name("abc")
                .configure(&provider_config)
                .connection(http_connector)
                .build(inner_provider)
        }
        None => AssumeRoleProvider::builder(p.role_arn.clone())
            .region(region.clone())
            .session_name("abc")
            .build(inner_provider),
    }
}

Edit: Solution: https://github.com/awslabs/aws-sdk-rust/discussions/814#discussioncomment-6013367

sammoh94 commented 1 year ago

Has anyone used aws_sig_auth to connect to an AWS RDS instance when using Diesel? I am trying to use the signed URL that is generated as a replacement for the password-based DB URL and getting errors connecting. My understanding is that since it's a signed URL, I should be able to plug it into the connecting code and it should allow me to connect to the DB

lcmgh commented 1 year ago

@sammoh94 Don't you have to use the IAM role name as username and the generated token as password?

sammoh94 commented 1 year ago

@lcmgh Would you mind posting what you passed in to assume_role_provider for the proxy argument? Thanks!

lcmgh commented 1 year ago

@lcmgh Would you mind posting what you passed in to assume_role_provider for the proxy argument? Thanks!

/// Returns `ProxyConnector<HttpConnector>` if env. variable 'https_proxy' is set
pub fn determine_proxy() -> Option<ProxyConnector<HttpConnector>> {
    let proxy_url: Url = env::var("https_proxy").ok()?.parse().ok()?;
    let proxy_uri: Uri = env::var("https_proxy").ok()?.parse().ok()?;
    let mut proxy = Proxy::new(Intercept::All, proxy_uri);

    if let Some(password) = proxy_url.password() {
        proxy.set_authorization(Authorization::basic(proxy_url.username(), password));
    }

    let connector = HttpConnector::new();
    Some(ProxyConnector::from_proxy(connector, proxy).unwrap())
}