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 for notices #18936

Merged
merged 26 commits into from Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
120 changes: 108 additions & 12 deletions packages/aws-cdk/README.md
Expand Up @@ -11,18 +11,20 @@

The AWS CDK Toolkit provides the `cdk` command-line interface that can be used to work with AWS CDK applications.

Command | Description
----------------------------------|-------------------------------------------------------------------------------------
[`cdk docs`](#cdk-docs) | Access the online documentation
[`cdk init`](#cdk-init) | Start a new CDK project (app or library)
[`cdk list`](#cdk-list) | List stacks in an application
[`cdk synth`](#cdk-synthesize) | Synthesize a CDK app to CloudFormation template(s)
[`cdk diff`](#cdk-diff) | Diff stacks against current state
[`cdk deploy`](#cdk-deploy) | Deploy a stack into an AWS account
[`cdk watch`](#cdk-watch) | Watches a CDK app for deployable and hotswappable changes
[`cdk destroy`](#cdk-destroy) | Deletes a stack from an AWS account
[`cdk bootstrap`](#cdk-bootstrap) | Deploy a toolkit stack to support deploying large stacks & artifacts
[`cdk doctor`](#cdk-doctor) | Inspect the environment and produce information useful for troubleshooting
Command | Description
--------------------------------------|---------------------------------------------------------------------------------
[`cdk docs`](#cdk-docs) | Access the online documentation
[`cdk init`](#cdk-init) | Start a new CDK project (app or library)
[`cdk list`](#cdk-list) | List stacks in an application
[`cdk synth`](#cdk-synthesize) | Synthesize a CDK app to CloudFormation template(s)
[`cdk diff`](#cdk-diff) | Diff stacks against current state
[`cdk deploy`](#cdk-deploy) | Deploy a stack into an AWS account
[`cdk watch`](#cdk-watch) | Watches a CDK app for deployable and hotswappable changes
[`cdk destroy`](#cdk-destroy) | Deletes a stack from an AWS account
[`cdk bootstrap`](#cdk-bootstrap) | Deploy a toolkit stack to support deploying large stacks & artifacts
[`cdk doctor`](#cdk-doctor) | Inspect the environment and produce information useful for troubleshooting
[`cdk acknowledge`](#cdk-acknowledge) | Acknowledge (and hide) a notice by issue number
[`cdk notices`](#cdk-notices) | List all relevant notices for the application

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.

Expand Down Expand Up @@ -503,6 +505,100 @@ $ cdk doctor
- AWS_SDK_LOAD_CONFIG = 1
```

## Notices

> This feature exists on CDK CLI version 2.14.0 and up.

CDK Notices are important messages regarding security vulnerabilities, regressions, and usage of unsupported
versions. Relevant notices appear on every command by default. For example,

```console
$ cdk deploy

... # Normal output of the command

NOTICES

16603 Toggling off auto_delete_objects for Bucket empties the bucket

Overview: If a stack is deployed with an S3 bucket with
auto_delete_objects=True, and then re-deployed with
auto_delete_objects=False, all the objects in the bucket
will be deleted.

Affected versions: <1.126.0.

More information at: https://github.com/aws/aws-cdk/issues/16603

17061 Error when building EKS cluster with monocdk import

Overview: When using monocdk/aws-eks to build a stack containing
an EKS cluster, error is thrown about missing
lambda-layer-node-proxy-agent/layer/package.json.

Affected versions: >=1.126.0 <=1.130.0.

More information at: https://github.com/aws/aws-cdk/issues/17061

If you don’t want to see an notice anymore, use "cdk acknowledge ID". For example, "cdk acknowledge 16603".
```

You can suppress warnings in a variety of ways:

- per individual execution:

`cdk deploy --no-notices`

- disable all notices indefinitely through context in `cdk.json`:

```json
{
"context": {
"notices": false
}
}
```

- acknowleding individual notices via `cdk acknowledge` (see below).

### `cdk acknowledge`

To hide a particular notice that has been addressed or does not apply, call `cdk acknowledge` with the ID of
the notice:

```console
$cdk acknowledge 16603
```

> Please note that the acknowledgements are made project by project. If you acknowledge an notice in one CDK
> project, it will still appear on other projects when you run any CDK commands, unless you have suppressed
> or disabled notices.


### `cdk notices`

List the notices that are relevant to the current CDK repository, regardless of context flags or notices that
have been acknowledged:

```console
$ cdk notices

NOTICES

16603 Toggling off auto_delete_objects for Bucket empties the bucket

Overview: if a stack is deployed with an S3 bucket with auto_delete_objects=True, and then re-deployed with auto_delete_objects=False, all the objects in the bucket will be deleted.

Affected versions: framework: <=2.15.0 >=2.10.0

More information at: https://github.com/aws/aws-cdk/issues/16603

If you don’t want to see a notice anymore, use "cdk acknowledge <id>". For example, "cdk acknowledge 16603".
```

This command returns zero if there is no notice and non-zero otherwise. Users can then plug this into a
otaviomacedo marked this conversation as resolved.
Show resolved Hide resolved
pipeline approval workflow and expect manual review if there are any notices.

### Bundling

By default asset bundling is skipped for `cdk list` and `cdk destroy`. For `cdk deploy`, `cdk diff`
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk/lib/cdk-toolkit.ts
Expand Up @@ -79,6 +79,13 @@ export class CdkToolkit {
return stacks.firstStack.manifest.metadata ?? {};
}

public async acknowledge(noticeId: string) {
otaviomacedo marked this conversation as resolved.
Show resolved Hide resolved
const acks = this.props.configuration.context.get('acknowledged-issue-numbers') ?? [];
acks.push(Number(noticeId));
this.props.configuration.context.set('acknowledged-issue-numbers', acks);
await this.props.configuration.saveContext();
}

public async diff(options: DiffOptions): Promise<number> {
const stacks = await this.selectStacksForDiff(options.stackNames, options.exclusively);

Expand Down
39 changes: 32 additions & 7 deletions packages/aws-cdk/lib/cli.ts
Expand Up @@ -19,6 +19,7 @@ import { realHandler as doctor } from '../lib/commands/doctor';
import { RequireApproval } from '../lib/diff';
import { availableInitLanguages, cliInit, printAvailableTemplates } from '../lib/init';
import { data, debug, error, print, setLogLevel } from '../lib/logging';
import { displayNotices } from '../lib/notices';
import { PluginHost } from '../lib/plugin';
import { serializeStructure } from '../lib/serialize';
import { Command, Configuration, Settings } from '../lib/settings';
Expand Down Expand Up @@ -71,6 +72,7 @@ async function parseCommandLineArguments() {
.option('role-arn', { type: 'string', alias: 'r', desc: 'ARN of Role to use when invoking CloudFormation', default: undefined, requiresArg: true })
.option('staging', { type: 'boolean', desc: 'Copy assets to the output directory (use --no-staging to disable, needed for local debugging the source files with SAM CLI)', default: true })
.option('output', { type: 'string', alias: 'o', desc: 'Emits the synthesized cloud assembly into a directory (default: cdk.out)', requiresArg: true })
.option('notices', { type: 'boolean', desc: 'Show relevant notices', default: true })
.option('no-color', { type: 'boolean', desc: 'Removes colors and other style from console output', default: false })
.command(['list [STACKS..]', 'ls [STACKS..]'], 'Lists all stacks in the app', yargs => yargs
.option('long', { type: 'boolean', default: false, alias: 'l', desc: 'Display environment information for each stack' }),
Expand Down Expand Up @@ -193,6 +195,8 @@ async function parseCommandLineArguments() {
.option('security-only', { type: 'boolean', desc: 'Only diff for broadened security changes', default: false })
.option('fail', { type: 'boolean', desc: 'Fail with exit code 1 in case of diff', default: false }))
.command('metadata [STACK]', 'Returns all metadata associated with this stack')
.command('acknowledge [ID]', 'Acknowledge a notice so that it does not show up anymore')
otaviomacedo marked this conversation as resolved.
Show resolved Hide resolved
.command('notices', 'Returns a list of relevant notices')
.command('init [TEMPLATE]', 'Create a new, empty CDK project from a template.', yargs => yargs
.option('language', { type: 'string', alias: 'l', desc: 'The language to be used for the new project (default can be configured in ~/.cdk.json)', choices: initTemplateLanguages })
.option('list', { type: 'boolean', desc: 'List the available templates' })
Expand Down Expand Up @@ -226,7 +230,7 @@ if (!process.stdout.isTTY) {
process.env.FORCE_COLOR = '0';
}

async function initCommandLine() {
async function initCommandLine(): Promise<{ configuration: Configuration, value: any }> {
const argv = await parseCommandLineArguments();
if (argv.verbose) {
setLogLevel(argv.verbose);
Expand Down Expand Up @@ -315,11 +319,20 @@ async function initCommandLine() {
}

if (typeof returnValue === 'object') {
return toJsonOrYaml(returnValue);
return {
value: toJsonOrYaml(returnValue),
configuration,
};
} else if (typeof returnValue === 'string') {
return returnValue;
return {
value: returnValue,
configuration,
};
} else {
return returnValue;
return {
value: returnValue,
configuration,
};
}
} finally {
await version.displayVersionMessage();
Expand Down Expand Up @@ -463,10 +476,16 @@ async function initCommandLine() {
return cli.synth(args.STACKS, true, args.quiet, args.validation);
}


case 'metadata':
return cli.metadata(args.STACK);

case 'acknowledge':
return cli.acknowledge(args.ID);

case 'notices':
SHOW_ALL_NOTICES = true;
otaviomacedo marked this conversation as resolved.
Show resolved Hide resolved
return;

case 'init':
const language = configuration.settings.get(['language']);
if (args.list) {
Expand Down Expand Up @@ -556,15 +575,21 @@ function yargsNegativeAlias<T extends { [x in S | L ]: boolean | undefined }, S
};
}

let SHOW_ALL_NOTICES = false;
export function cli() {
initCommandLine()
.then(value => {
if (value == null) { return; }
.then(async ({ value, configuration }) => {
if (typeof value === 'string') {
data(value);
} else if (typeof value === 'number') {
process.exitCode = value;
}
await displayNotices({
otaviomacedo marked this conversation as resolved.
Show resolved Hide resolved
outdir: configuration.settings.get(['output']) ?? 'cdk.out',
acknowledgedIssueNumbers: SHOW_ALL_NOTICES ? [] : configuration.context.get('acknowledged-issue-numbers') ?? [],
permanentlySuppressed: SHOW_ALL_NOTICES ? false : !(configuration.context.get('notices') ?? true),
temporarilySuppressed: !configuration.settings.get(['notices']),
});
})
.catch(err => {
error(err.message);
Expand Down