Skip to content

Commit

Permalink
feat(plugin): Simplify contract for credential providers (aws#646)
Browse files Browse the repository at this point in the history
Only require credential provider plugins to provide `aws.Credentials`
instances, and not `aws.CredentialProviderChain`. That is a much simpler
contract to fulfill, and it still offers ability to vend self-refreshing
credentials in an efficient manner.
  • Loading branch information
RomainMuller authored Aug 30, 2018
1 parent 54c202a commit 4dae9dc
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 15 deletions.
6 changes: 2 additions & 4 deletions packages/aws-cdk/lib/api/aws-auth/credentials.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { CredentialProviderChain } from 'aws-sdk';

export { CredentialProviderChain };
import aws = require('aws-sdk');

export enum Mode {
ForReading,
Expand All @@ -27,5 +25,5 @@ export interface CredentialProviderSource {
*
* Guaranteed to be called only if canProvideCredentails() returned true at some point.
*/
getProvider(accountId: string, mode: Mode): Promise<CredentialProviderChain>;
getProvider(accountId: string, mode: Mode): Promise<aws.Credentials>;
}
22 changes: 11 additions & 11 deletions packages/aws-cdk/lib/api/util/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { SharedIniFile } from './sdk_ini_file';
export class SDK {
private readonly userAgent: string;
private readonly defaultAwsAccount: DefaultAWSAccount;
private readonly credentialProviderCache: CredentialProviderCache;
private readonly credentialsCache: CredentialsCache;

constructor(private readonly profile: string | undefined) {
// Find the package.json from the main toolkit
Expand All @@ -31,37 +31,37 @@ export class SDK {
const defaultCredentialProvider = makeCLICompatibleCredentialProvider(profile);

this.defaultAwsAccount = new DefaultAWSAccount(defaultCredentialProvider);
this.credentialProviderCache = new CredentialProviderCache(this.defaultAwsAccount, defaultCredentialProvider);
this.credentialsCache = new CredentialsCache(this.defaultAwsAccount, defaultCredentialProvider);
}

public async cloudFormation(environment: Environment, mode: Mode): Promise<AWS.CloudFormation> {
return new AWS.CloudFormation({
region: environment.region,
credentialProvider: await this.credentialProviderCache.get(environment.account, mode),
credentials: await this.credentialsCache.get(environment.account, mode),
customUserAgent: this.userAgent
});
}

public async ec2(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise<AWS.EC2> {
return new AWS.EC2({
region,
credentialProvider: await this.credentialProviderCache.get(awsAccountId, mode),
credentials: await this.credentialsCache.get(awsAccountId, mode),
customUserAgent: this.userAgent
});
}

public async ssm(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise<AWS.SSM> {
return new AWS.SSM({
region,
credentialProvider: await this.credentialProviderCache.get(awsAccountId, mode),
credentials: await this.credentialsCache.get(awsAccountId, mode),
customUserAgent: this.userAgent
});
}

public async s3(environment: Environment, mode: Mode): Promise<AWS.S3> {
return new AWS.S3({
region: environment.region,
credentialProvider: await this.credentialProviderCache.get(environment.account, mode),
credentials: await this.credentialsCache.get(environment.account, mode),
customUserAgent: this.userAgent
});
}
Expand All @@ -87,23 +87,23 @@ export class SDK {
* all loaded credential provider plugins will be tried to obtain credentials
* for the given account.
*/
class CredentialProviderCache {
private readonly cache: {[key: string]: AWS.CredentialProviderChain} = {};
class CredentialsCache {
private readonly cache: {[key: string]: AWS.Credentials} = {};

public constructor(
private readonly defaultAwsAccount: DefaultAWSAccount,
private readonly defaultCredentialProvider: Promise<AWS.CredentialProviderChain>) {
}

public async get(awsAccountId: string | undefined, mode: Mode): Promise<AWS.CredentialProviderChain> {
public async get(awsAccountId: string | undefined, mode: Mode): Promise<AWS.Credentials> {
const key = `${awsAccountId}-${mode}`;
if (!(key in this.cache)) {
this.cache[key] = await this.getCredentialProvider(awsAccountId, mode);
this.cache[key] = await this.getCredentials(awsAccountId, mode);
}
return this.cache[key];
}

private async getCredentialProvider(awsAccountId: string | undefined, mode: Mode): Promise<AWS.CredentialProviderChain> {
private async getCredentials(awsAccountId: string | undefined, mode: Mode): Promise<AWS.Credentials> {
// If requested account is undefined or equal to default account, use default credentials provider.
// (Note that we ignore the mode in this case, if you preloaded credentials they better be correct!)
const defaultAccount = await this.defaultAwsAccount.get();
Expand Down

0 comments on commit 4dae9dc

Please sign in to comment.