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

feat(aws-cdk): add support for HTTPS_PROXY #666

Merged
merged 4 commits into from
Sep 5, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/src/tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,33 @@ Below are the actions you can take on your CDK app:
If one of cdk.json or ~/.cdk.json exists, options specified there will be used
as defaults. Settings in cdk.json take precedence.

.. _using-a-proxy:

Using a proxy
~~~~~~~~~~~~~

If you use a proxy to connect to the Internet, configure it by setting either the `HTTPS_PROXY` or
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a one line note in “cdk —help” about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose we can make it a real command-line argument as well.

`https_proxy` environment variable.

On Linux and macOS, you set environment variables like this:

.. code-block:: sh

export HTTPS_PROXY=http://10.0.0.10:8080/

Put this line in your ``~/.bashrc`` file or similar to make it persistent.

On Windows, you set an environment variable like this:

.. code-block:: sh

set HTTPS_PROXY=http://10.0.0.10:8080/

To make the setting persistent on Windows, right-click **My Computer** ~> **Properties** > **Advanced System Settings**
> **Environment Variables** > **New**, fill in the name and value in separate fields, click **OK** and restart your
command prompt.


.. _version-reporting:

Version Reporting
Expand Down
55 changes: 44 additions & 11 deletions packages/aws-cdk/lib/api/util/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,50 +19,59 @@ import { SharedIniFile } from './sdk_ini_file';
* to the requested account.
*/
export class SDK {
private readonly userAgent: string;
private readonly defaultAwsAccount: DefaultAWSAccount;
private readonly credentialsCache: CredentialsCache;
private readonly defaultClientArgs: any = {};

constructor(private readonly profile: string | undefined) {
// Find the package.json from the main toolkit
const pkg = (require.main as any).require('../package.json');
this.userAgent = `${pkg.name}/${pkg.version}`;

const defaultCredentialProvider = makeCLICompatibleCredentialProvider(profile);

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

// Find the package.json from the main toolkit
const pkg = (require.main as any).require('../package.json');
this.defaultClientArgs.userAgent = `${pkg.name}/${pkg.version}`;

// https://aws.amazon.com/blogs/developer/using-the-aws-sdk-for-javascript-from-behind-a-proxy/
const proxyAddress = httpsProxyAddress();
if (proxyAddress) {
debug('Using proxy server: %s', proxyAddress);
this.defaultClientArgs.httpOptions = {
agent: require('proxy-agent')(proxyAddress)
};
}
}

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

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

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

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

Expand Down Expand Up @@ -109,7 +118,11 @@ class CredentialsCache {
const defaultAccount = await this.defaultAwsAccount.get();
if (!awsAccountId || awsAccountId === defaultAccount) {
debug(`Using default AWS SDK credentials for account ${awsAccountId}`);
return this.defaultCredentialProvider;

// CredentialProviderChain extends Credentials, but that is a lie.
// https://github.com/aws/aws-sdk-js/issues/2235
// Call resolve() instead.
return (await this.defaultCredentialProvider).resolvePromise();
}

const triedSources: CredentialProviderSource[] = [];
Expand All @@ -122,7 +135,14 @@ class CredentialsCache {
triedSources.push(source);
if (!(await source.canProvideCredentials(awsAccountId))) { continue; }
debug(`Using ${source.name} credentials for account ${awsAccountId}`);
return await source.getProvider(awsAccountId, mode);
const providerOrCreds = await source.getProvider(awsAccountId, mode);

// Backwards compatibility: if the plugin returns a ProviderChain, resolve that chain.
// Otherwise it must have returned credentials.
if ((providerOrCreds as any).resolvePromise) {
return await (providerOrCreds as any).resolvePromise();
}
return providerOrCreds;
}
const sourceNames = ['default credentials'].concat(triedSources.map(s => s.name)).join(', ');
throw new Error(`Need to perform AWS calls for account ${awsAccountId}, but no credentials found. Tried: ${sourceNames}.`);
Expand Down Expand Up @@ -256,3 +276,16 @@ async function getCLICompatibleDefaultRegion(profile: string | undefined): Promi

return region;
}

/**
* Find and return the configured HTTPS proxy address
*/
function httpsProxyAddress(): string | undefined {
if (process.env.http_proxy) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Didn’t know process.env is case insensitive

Copy link
Contributor Author

@rix0rrr rix0rrr Sep 5, 2018

Choose a reason for hiding this comment

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

Oops. Brain fart. I meant to type https_proxy and HTTPS_PROXY but typed something else :/

return process.env.http_proxy;
}
if (process.env.https_proxy) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think https should have precedence

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes no, the http_ one should never have been there.

return process.env.https_proxy;
}
return undefined;
}
1 change: 1 addition & 0 deletions packages/aws-cdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"json-diff": "^0.3.1",
"minimatch": ">=3.0",
"promptly": "^0.2.0",
"proxy-agent": "^3.0.1",
"request": "^2.83.0",
"source-map-support": "^0.5.6",
"yamljs": "^0.2.0",
Expand Down