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

Change iac gen-driftignore to iac update-exclude-policy #3046

Merged
merged 1 commit into from
Mar 29, 2022
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: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ src/cli/commands/test/iac-output.ts @snyk/group-infrastructure-as-code
src/cli/commands/test/iac-test-shim.ts @snyk/group-infrastructure-as-code
src/cli/commands/describe.ts @snyk/group-infrastructure-as-code
src/cli/commands/report/ @snyk/group-infrastructure-as-code
src/cli/commands/gen-driftignore.ts @snyk/group-infrastructure-as-code
src/cli/commands/update-exclude-policy.ts @snyk/group-infrastructure-as-code
src/cli/commands/apps @snyk/moose
src/lib/apps @snyk/moose
src/lib/cloud-config-projects.ts @snyk/group-infrastructure-as-code
Expand Down
66 changes: 0 additions & 66 deletions help/cli-commands/iac-gen-driftignore.md

This file was deleted.

46 changes: 46 additions & 0 deletions help/cli-commands/iac-update-exclude-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# snyk iac update-exclude-policy -- generate ignore rules based on scan result

## Usage

`snyk iac update-exclude-policy [<OPTIONS>]`

## Description

The `snyk iac update-exclude-policy` can generate exclude policy rules to be used by `snyk iac scan`.

## Exit codes

Possible exit codes and their meaning:

**0**: success, exclude rules generated successfully
**1**: error, something wrong happened during exclude rules generation

## Configure the Snyk CLI

You can use environment variables to configure the Snyk CLI and also set variables to configure the Snyk CLI to connect with the Snyk API.
See [Configure the Snyk CLI](https://docs.snyk.io/features/snyk-cli/configure-the-snyk-cli).

## Debug

Use the `-d` option to output the debug logs.

## Options

### `--exclude-changed`

Exclude resources that changed on cloud provider

### `--exclude-missing`

Exclude missing resources

### `--exclude-unmanaged`

Exclude resources not managed by IaC

## Usage

```
$ snyk iac scan --output=json://output.json
$ snyk iac describe --json --all | snyk iac update-exclude-policy
eliecharra marked this conversation as resolved.
Show resolved Hide resolved
```
36 changes: 0 additions & 36 deletions src/cli/commands/gen-driftignore.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/cli/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ async function callModule(mod, args) {
const commands = {
auth: async (...args) => callModule(import('./auth'), args),
config: async (...args) => callModule(import('./config'), args),
'gen-driftignore': async (...args) =>
callModule(import('./gen-driftignore'), args),
'update-exclude-policy': async (...args) =>
callModule(import('./update-exclude-policy'), args),
describe: async (...args) => callModule(import('./describe'), args),
help: async (...args) => callModule(import('./help'), args),
ignore: async (...args) => callModule(import('./ignore'), args),
Expand Down
57 changes: 57 additions & 0 deletions src/cli/commands/update-exclude-policy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { MethodArgs } from '../args';
import { processCommandArgs } from './process-command-args';
import * as legacyError from '../../lib/errors/legacy-errors';
import * as fs from 'fs';
import * as snykPolicyLib from 'snyk-policy';
import { getIacOrgSettings } from './test/iac-local-execution/org-settings/get-iac-org-settings';
import { UnsupportedEntitlementCommandError } from './test/iac-local-execution/assert-iac-options-flag';
import config from '../../lib/config';
import {
parseDriftAnalysisResults,
updateExcludeInPolicy,
} from '../../lib/iac/drift';
import { Policy } from '../../lib/policy/find-and-load-policy';

export default async (...args: MethodArgs): Promise<any> => {
const { options } = processCommandArgs(...args);

// Ensure that this update-exclude-policy command can only be runned when using `snyk iac update-exclude-policy`
// Avoid `snyk update-exclude-policy` direct usage
if (options.iac != true) {
return legacyError('update-exclude-policy');
}

// Ensure that we are allowed to run that command
// by checking the entitlement
const orgPublicId = options.org ?? config.org;
const iacOrgSettings = await getIacOrgSettings(orgPublicId);
if (!iacOrgSettings.entitlements?.iacDrift) {
throw new UnsupportedEntitlementCommandError(
'update-exclude-policy',
'iacDrift',
);
}

try {
// There's an open bug for this in Windows in the current version of node when called with no stdinput.
// See https://github.com/nodejs/node/issues/19831
// The actual error handling behavior is enough for now but may be improved if needed
const analysis = parseDriftAnalysisResults(fs.readFileSync(0).toString());
eliecharra marked this conversation as resolved.
Show resolved Hide resolved
let policy: Policy;
try {
policy = await snykPolicyLib.load();
} catch (error) {
if (error.code === 'ENOENT') {
// policy file does not exist - create it
policy = await snykPolicyLib.create();
} else {
throw error;
}
}
await updateExcludeInPolicy(policy, analysis, options);
await snykPolicyLib.save(policy);
eliecharra marked this conversation as resolved.
Show resolved Hide resolved
} catch (e) {
const err = new Error('Error running `iac update-exclude-policy` ' + e);
return Promise.reject(err);
}
};
2 changes: 1 addition & 1 deletion src/cli/modes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const modes: Record<string, ModeData> = {
},
},
iac: {
allowedCommands: ['test', 'gen-driftignore', 'describe', 'report'],
allowedCommands: ['test', 'update-exclude-policy', 'describe', 'report'],
config: (args): [] => {
args['iac'] = true;

Expand Down
61 changes: 27 additions & 34 deletions src/lib/iac/drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,47 +120,13 @@ export const generateArgs = (
return generateScanFlags(options as DescribeOptions, driftIgnore);
}

if (options.kind === 'gen-driftignore') {
return generateGenDriftIgnoreFlags(options as GenDriftIgnoreOptions);
}

if (options.kind === 'fmt') {
return generateFmtFlags(options as FmtOptions);
}

throw 'Unsupported command';
};

export const generateGenDriftIgnoreFlags = (
options: GenDriftIgnoreOptions,
): string[] => {
const args: string[] = ['gen-driftignore', ...driftctlDefaultOptions];

if (options.input) {
args.push('--input');
args.push(options.input);
}

if (options.output) {
args.push('--output');
args.push(options.output);
}

if (options['exclude-changed']) {
args.push('--exclude-changed');
}

if (options['exclude-missing']) {
args.push('--exclude-missing');
}

if (options['exclude-unmanaged']) {
args.push('--exclude-unmanaged');
}

return args;
};

const generateFmtFlags = (options: FmtOptions): string[] => {
const args: string[] = ['fmt', ...driftctlDefaultOptions];

Expand Down Expand Up @@ -535,6 +501,33 @@ export function driftignoreFromPolicy(policy: Policy | undefined): string[] {
return policy.exclude[excludeSection];
}

export const updateExcludeInPolicy = (
policy: Policy,
analysis: DriftAnalysis,
options: GenDriftIgnoreOptions,
): void => {
const excludedResources = driftignoreFromPolicy(policy);
const addResource = (res) => excludedResources.push(`${res.type}.${res.id}`);

if (!options['exclude-changed'] && analysis.summary.total_changed > 0) {
analysis.differences?.forEach((change) => addResource(change.res));
}

if (!options['exclude-missing'] && analysis.summary.total_missing > 0) {
analysis.missing?.forEach((res) => addResource(res));
}

if (!options['exclude-unmanaged'] && analysis.summary.total_unmanaged > 0) {
analysis.unmanaged?.forEach((res) => addResource(res));
}

if (!policy.exclude) {
policy.exclude = {};
}

policy.exclude['iac-drift'] = excludedResources;
};

export function processDriftctlOutput(
options: DescribeOptions,
stdout: string,
Expand Down
4 changes: 1 addition & 3 deletions src/lib/iac/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ export interface FmtOptions extends DriftCTLOptions {
'html-file-output': string;
}

export interface GenDriftIgnoreOptions extends DriftCTLOptions {
input?: string;
output?: string;
export interface GenDriftIgnoreOptions {
'exclude-changed'?: boolean;
'exclude-missing'?: boolean;
'exclude-unmanaged'?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export enum SupportedCliCommands {
apps = 'apps',
drift = 'drift',
describe = 'describe',
'gen-driftignore' = 'gen-driftignore',
'update-exclude-policy' = 'update-exclude-policy',
report = 'report',
}

Expand Down
Loading