Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store default account in disk cache #220

Merged
merged 3 commits into from
Jul 4, 2018
Merged

Conversation

eladb
Copy link
Contributor

@eladb eladb commented Jul 2, 2018

Given an access key ID, the account ID is fixed.
This means that we don't need to look up the default
account every time the toolkit is used.

This change will store the mapping between access key
and account ID in ~/.cdk/cache/accounts.json
and will fetch the account ID from there if it exists.

Fixes #228

Given an access key ID, the account ID is fixed.
This means that we don't need to look up the default
account every time the toolkit is used.

This change will store the mapping between access key
and account ID in `~/.cdk/cache/accounts.json`
and will fetch the account ID from there if it exists.
@eladb eladb requested review from rix0rrr and RomainMuller July 2, 2018 14:04
* @param filePath Path to the cache file
*/
constructor(filePath?: string) {
this.cacheFile = filePath || path.join(os.homedir(), '.cdk/cache/accounts.json');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to use path.join, you should do it all the way...

path.join(os.homedir(), '.cdk', 'cache', 'accounts.json');

Otherwise it's a ridiculous way to write:

`${os.homedir()}/.cdk/cache/accounts.json`

}

/** Get the account ID from an access key or undefined if not in cache */
public async get(accessKeyId: string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is ridiculously loosely typed (for loadMap returns any). I would add an explicit typing in there, that this returns string | undefined. I guess otherwise you could make loadMap return { [accessKeyId: string]: string | undefined } to the same effect.

@@ -1,8 +1,9 @@
import { Environment} from '@aws-cdk/cx-api';
import { CloudFormation, config, CredentialProviderChain , EC2, S3, SSM, STS } from 'aws-sdk';
import { CloudFormation, config, CredentialProviderChain, EC2, S3, SSM, STS } from 'aws-sdk';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

const creds = await chain.resolvePromise();
const accessKeyId = creds.accessKeyId;
if (!accessKeyId) {
throw new Error('Unable to resolve AWS credentials');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configure with "aws configure"?

} catch (e) {
debug('Unable to retrieve default account from STS:', e);
debug('Unable to determine the default AWS account (use "aws configure" to set up):', e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bunch of ways here that you could have configured it w/ aws configure and you get there... You'll then be giving the user a pretty direct "steps to fix" that they've already followed, and they'll probably end up looking something like:

FUUUUUUUUU

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to

Unable to determine the default AWS account (did you configure "aws configure"?)

Not much better, but it's now it's less directive and more of a hint.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely prefer that.

debug('STS didn\'t return an account ID');
return undefined;
}
await this.accountCache.put(accessKeyId, accountId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this can be easy to forget, and then the cache would become useless...

Would be nice if the cache class instead had a:

export class AccountCache {
  // ...

  /**
   * @param loader an object to be used for resolving the account ID if it is not already in the cache.
   */
  public fetch(key: string, loader: IAccountIdResolver, reload: boolean = false) {
    if (!reload) {
      const cached = this.get(key);
      if (cached) { return cached; }
    }
    const loaded = loader.load();
    this.put(key, loaded);
    return loaded;
  }
}

public async put(accessKeyId: string, accountId: string) {
const map = await this.loadMap();
map[accessKeyId] = accountId;
await this.saveMap(map);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we going to take any precautions to prevent this map from growing without bounds? Session credentials will have a new access key every time, and this file may become unwieldy after a while.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rix0rrr are you okay with me punting this for later or you feel it's important to take care of it now? (I am on the fence)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't like kicking work down the road in this way, I'd prefer finishing the feature so we don't have to come back to it.

If we do 'wipe on # of entries limit' (let's say 100) then it should be 5 mins to implement, no?

@eladb eladb merged commit cfee46e into master Jul 4, 2018
@eladb eladb deleted the benisrae/account-disk-cache branch July 4, 2018 09:34
@NGL321 NGL321 added the contribution/core This is a PR that came from AWS. label Sep 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Toolkit: protect account disk cache from growing out of bounds
4 participants