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(cli): support custom CA certificate bundles #5295

Merged
merged 3 commits into from
Dec 20, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions packages/aws-cdk/bin/cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ async function parseCommandLineArguments() {
.option('verbose', { type: 'boolean', alias: 'v', desc: 'Show debug logs', default: false })
.option('profile', { type: 'string', desc: 'Use the indicated AWS profile as the default environment', requiresArg: true })
.option('proxy', { type: 'string', desc: 'Use the indicated proxy. Will read from HTTPS_PROXY environment variable if not specified.', requiresArg: true })
.option('ca-bundle-path', { type: 'string', desc: 'Path to CA certificate to use when validating HTTPS requests. Will read from AWS_CA_BUNDLE environment variable if not specified.', requiresArg: true })
.option('ec2creds', { type: 'boolean', alias: 'i', default: undefined, desc: 'Force trying to fetch EC2 instance credentials. Default: guess EC2 instance status.' })
.option('version-reporting', { type: 'boolean', desc: 'Include the "AWS::CDK::Metadata" resource in synthesized templates (enabled by default)', default: undefined })
.option('path-metadata', { type: 'boolean', desc: 'Include "aws:cdk:path" CloudFormation metadata for each resource (enabled by default)', default: true })
Expand Down Expand Up @@ -107,6 +108,7 @@ async function initCommandLine() {
const aws = new SDK({
profile: argv.profile,
proxyAddress: argv.proxy,
caBundlePath: argv['ca-bundle-path'],
ec2creds: argv.ec2creds,
});

Expand Down
62 changes: 45 additions & 17 deletions packages/aws-cdk/lib/api/util/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as cxapi from '@aws-cdk/cx-api';
import * as AWS from 'aws-sdk';
import * as child_process from 'child_process';
import * as fs from 'fs-extra';
import * as https from 'https';
import * as os from 'os';
import * as path from 'path';
import * as util from 'util';
Expand Down Expand Up @@ -53,6 +54,13 @@ export interface SDKOptions {
* @default Automatically determine.
*/
ec2creds?: boolean;

/**
* A path to a certificate bundle that contains a cert to be trusted.
*
* @default No certificate bundle
*/
caBundlePath?: string;
}

/**
Expand Down Expand Up @@ -88,23 +96,7 @@ export class SDK implements ISDK {

const defaultCredentialProvider = makeCLICompatibleCredentialProvider(options.profile, options.ec2creds);

// Find the package.json from the main toolkit
const pkg = (require.main as any).require('../package.json');
AWS.config.update({
customUserAgent: `${pkg.name}/${pkg.version}`
});

// https://aws.amazon.com/blogs/developer/using-the-aws-sdk-for-javascript-from-behind-a-proxy/
if (options.proxyAddress === undefined) {
options.proxyAddress = httpsProxyFromEnvironment();
}
if (options.proxyAddress) { // Ignore empty string on purpose
debug('Using proxy server: %s', options.proxyAddress);
AWS.config.update({
// eslint-disable-next-line @typescript-eslint/no-require-imports
httpOptions: { agent: require('proxy-agent')(options.proxyAddress) }
});
}
this.configureSDKHttpOptions(options);

this.defaultAwsAccount = new DefaultAWSAccount(defaultCredentialProvider, getCLICompatibleDefaultRegionGetter(this.profile));
this.credentialsCache = new CredentialsCache(this.defaultAwsAccount, defaultCredentialProvider);
Expand Down Expand Up @@ -196,6 +188,29 @@ export class SDK implements ISDK {
return environment;
}

private async configureSDKHttpOptions(options: SDKOptions) {
const config: {[k: string]: any} = {};
const httpOptions: {[k: string]: any} = {};
// Find the package.json from the main toolkit
const pkg = (require.main as any).require('../package.json');
config.customUserAgent = `${pkg.name}/${pkg.version}`;

// https://aws.amazon.com/blogs/developer/using-the-aws-sdk-for-javascript-from-behind-a-proxy/
options.proxyAddress = options.proxyAddress || httpsProxyFromEnvironment();
options.caBundlePath = options.caBundlePath || caBundlePathFromEnvironment();

if (options.proxyAddress) { // Ignore empty string on purpose
debug('Using proxy server: %s', options.proxyAddress);
httpOptions.proxy = options.proxyAddress;
}
if (options.caBundlePath) {
debug('Using ca bundle path: %s', options.caBundlePath);
httpOptions.agent = new https.Agent({ca: await readIfPossible(options.caBundlePath)});
}
config.httpOptions = httpOptions;

AWS.config.update(config);
}
}

/**
Expand Down Expand Up @@ -438,6 +453,19 @@ function httpsProxyFromEnvironment(): string | undefined {
return undefined;
}

/**
* Find and return a CA certificate bundle path to be passed into the SDK.
*/
function caBundlePathFromEnvironment(): string | undefined {
if (process.env.aws_ca_bundle) {
return process.env.aws_ca_bundle;
}
if (process.env.AWS_CA_BUNDLE) {
return process.env.AWS_CA_BUNDLE;
}
return undefined;
}

/**
* Return whether it looks like we'll have ECS credentials available
*/
Expand Down
1 change: 0 additions & 1 deletion packages/aws-cdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
"json-diff": "^0.5.4",
"minimatch": ">=3.0",
"promptly": "^3.0.3",
"proxy-agent": "^3.1.1",
"request": "^2.88.0",
"semver": "^7.1.1",
"source-map-support": "^0.5.16",
Expand Down