aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.61k stars 3.91k forks source link

[cli] Cache mfa credentials #10867

Open johan-lindqvist opened 4 years ago

johan-lindqvist commented 4 years ago

Re-creating this issue since #9855 don't show up in the list of issues after the account that posted it was deleted.


It's great to see that the CDK CLI now supports MFA since #6510 was merged! However, the MFA credentials are not cached, which means that for every deploy/synth/diff it requires you to enter your MFA credentials again.

Use Case

As a user I would like to not have to enter my MFA credentials for every CLI command.

Proposed Solution

Cache the credentials in some way for some amount of time so that users don't have to enter their MFA credentials every time they call a CLI command.

This is a 🚀 Feature Request

johan-lindqvist commented 4 years ago

@shivlaks not sure if this was correct or you'd rather update the reporter on the previous issue #9855

rix0rrr commented 4 years ago

I understand that this is a usability pain point, but the point of a TOTP is really that it can't be cached because it's time-dependent, and its lifetime window is on the order of 30-60 seconds.

What other tools might do is cache the AssumeRole credentials somewhere on your disk. Personally, that's very scary to me and I don't want to be writing a tool that stores user credentials somewhere on disk.

Can't you use a dedicated tool that stores the temporary credentials in your ~/.aws/config or environment instead? Maybe using credential_process ?

johan-lindqvist commented 4 years ago

It used to be that I could use the third-party tool aws-mfa, but since the aws-cdk now supports MFA it stopped working and I'm always prompted to enter my MFA code.

The aws-cli has this caching already, it doesn't prompt you for your MFA code every time, but stores it for something like an hour or so (unsure of the exact duration).

I assumed that since the aws-cli did it, that it would be possible to do in the aws-cdk as well. I'm confused as to the difference between aws-cdk caching it and aws-cli caching it, and why it would be a risk here compared to the aws-cli, could you elaborate on that?

rix0rrr commented 4 years ago

There is a risk because it's a different code base. We might make mistakes; effectively your credentials might get stolen because of us. We're going to need to come up with a design and have that security reviewed. I'm not saying it can't be done, and we'll leave this ticket open as a feature request, but it's not a small change and we're unlikely to do it anytime soon.

Also, deferring to a tool that's explicitly designed to perform this task (for example, one that can store the credentials in your OS' keychain) rather than reimplementing the same features over and over again seems like a better design strategy in general.

s-j-h commented 4 years ago

I think the ask here was to re-use the mechanism already in use by aws-cli, storing tokens in ~/.aws/cli/cache, but from a bit of digging that comes from botocore not aws-cli itself, but the implementation & considerations made when adopting that may be of help? https://github.com/boto/botocore/blob/e216df29b07cb1a04a12dc7ffd68734d9105c0ae/botocore/credentials.py#L809

aripalo commented 3 years ago

I concur with the above, i.e. AWS tools should really have a more unified experience when handling credentials. From Developer Experience point of view, as a developer used to AWS CLI, CDK should behave similarly.

Maybe CDK could even depend on AWS botocore to manage the credential process? It wouldn't be unreasonable to have it as dependency to provide secure, but usable credential process.

The current MFA process is painful, especially when one is trying things out / developing something new and has to deploy often from one's own computer.

Helgeb commented 3 years ago

Just as a reference, here is how a python-script could use the (botocore)-credential-cache the same way the aws cli does:

import boto3
from botocore import credentials
import os
import botocore.session

def get_session(profile, region):
    """Get Boto3 Session using defalt cache (the same as the aws cli)"""
    cli_cache = os.path.join(os.path.expanduser("~"), ".aws/cli/cache")
    # Construct botocore session with cache
    session = botocore.session.Session(profile=profile)
    session.get_component("credential_provider").get_provider(
        "assume-role"
    ).cache = credentials.JSONFileCache(cli_cache)
    return boto3.Session(botocore_session=session, region_name=region)    
zachbtp commented 3 years ago

The current MFA process is painful, especially when one is trying things out / developing something new and has to deploy often from one's own computer.

+1 getting starting with CDK is very difficult when every single cdk command requires a MFA round trip.

I could work around this same issue for the sam tool by vaulting the credential, however this doesn't seem to work for cdk.

lony commented 3 years ago

@rix0rrr if it may help - I tried to describe my problem on Stackoverflow here before finding this issue.

To be honest, I do not get the discussion form above. My assumption so far was, that you just hook up to boto (or something similar) and avoid reimplementing authentication inside the CDK. Why is it necessary to reimplement it and divert? If I can assist, please feel free to ping me as @zachbtp described - a real pain in the ass - but still CDK is an amazing step into the right direction. Thanks for your work!

adamnovak commented 2 years ago

The reason role assumption is reimplemented in the CDK and not just using the botocore implementation is probably that botocore is in Python and the CDK is in Typescript, so the CDK can't call into botocore.

So tapping into the main AWS credential cache isn't as simple as plugging in a JSONFileCache; that class would need to be reimplemented in Typescript and against the AWS Javascript SDK APIs.

It looks like the CDK already has a reimplementation of credential fetching and role assumption logic from the SDK, because the CDK was blocked on some SDK bugs and for some reason didn't just fix them in the SDK. I'm not sure if this machinery is likely to survive on top of SDK 3.0, since that ostensibly has fixed the linked issues that justify the reimplementation. But it does look like the easiest place to add MFA credential caching if it is going to be added to the CDK.

Now, this functionality was already implemented once for the SDK in https://github.com/aws/aws-sdk-js/pull/2270, but the stale bot clock ran out on reviewer @AllanZhengYP and the PR was rejected. In September, @tavisrudd revived that code with https://github.com/unbounce/aws-sdk-js/commit/32191b99dfa10120fa48701593db3315d17e7e45, but doesn't appear to have a PR open at the moment.

The SDK is probably the right place for this feature, but perhaps @rix0rrr, who made PatchedSharedIniFileCredentials, can speak to whether it's feasible to get a feature added to the SDK.

Assuming we can't fix the SDK, the easiest way to implement this feature in the CDK would be to steal the STSCredentialsCache implementation and SharedIniFileCredentials modifications from that old PR, and glue them onto the CDK's PatchedSharedIniFileCredentials.

tavisrudd commented 2 years ago

If you're interested I could rebase the revised PR for review/discussion. I was updating it for the patched version of the aws-sdk we use in https://github.com/unbounce/iidy/.

Kazpers commented 2 years ago

This might be a security problem, but right now the workaround I've seen used multiple places has been making a shared account with no MFA to do CDK stuff - which is far worse security-wise than the risk of caching credentials.

github-actions[bot] commented 2 years ago

This issue has received a significant amount of attention so we are automatically upgrading its priority. A member of the community will see the re-prioritization and provide an update on the issue.