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: initial snyk-fix package setup & loadPlugin functionality #1659

Merged
merged 1 commit into from
Mar 4, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ src/lib/errors/invalid-iac-file.ts @snyk/cloudconfig
src/lib/errors/unsupported-options-iac-error.ts @snyk/cloudconfig
help/commands-docs/iac-examples.md @snyk/cloudconfig
help/commands-docs/iac.md @snyk/cloudconfig
packages/snyk-fix/ @snyk/tech-services
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ test/**/.gradle
.iac-data
.dccache
!test/smoke/.iac-data
# Jest
coverage
3 changes: 3 additions & 0 deletions packages/snyk-fix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @snyk/snyk-fix

Experimental package for future use of Snyk fix functionality (next generation `snyk wizard`).
21 changes: 21 additions & 0 deletions packages/snyk-fix/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Reporting Security Issues

We at Snyk value the security community and believe that responsible disclosure of security vulnerabilities in open source packages helps us ensure the security and privacy of the users.

If you believe you have found a security vulnerability on Snyk, we encourage you to let us know right away. We will investigate all legitimate reports and do our best to quickly fix the problem. Before reporting though, please review our responsible disclosure policy, and those things that should not be reported.

Submit your report to security@snyk.io (one issue per report) and respond to the report with any updates. Please do not contact employees directly or through other channels about a report.

Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through our [Snyk Vulnerability Disclosure](https://docs.google.com/a/snyk.io/forms/d/e/1FAIpQLSemwgWZ0JgK1ZULKhy9DZCQ5KulbLEldvmokAuRtt-_nrqNlA/viewform) program.

### Responsible Disclosure Policy

We ask that:

- You give us reasonable time to investigate and mitigate an issue you report before making public any information about the report or sharing such information with others.
- You do not interact with an individual account (which includes modifying or accessing data from the account) if the account owner has not consented to such actions.
- You make a good faith effort to avoid privacy violations and disruptions to others, including (but not limited to) destruction of data and interruption or degradation of our services.
- You do not exploit a security issue you discover for any reason. (This includes demonstrating additional risk, such as attempted compromise of sensitive company data or probing for additional issues).
- You do not violate any other applicable laws or regulations.

Find out more about our [security policy](https://snyk.io/docs/security) and [Bug Bounty program](https://snyk.io/docs/security#snyk-s-vulnerability-disclosure-program)
10 changes: 10 additions & 0 deletions packages/snyk-fix/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const sharedConfig = require('../../jest.config.js');

module.exports = {
...sharedConfig,
'rootDir': './',
collectCoverage: true, // not collecting coverage for now
collectCoverageFrom: ['src/**/*.spec.ts'],
coverageReporters: ['text-summary', 'html'],
testMatch: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"]
};
60 changes: 60 additions & 0 deletions packages/snyk-fix/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "@snyk/fix",
"version": "1.0.0-monorepo",
"description": "Snyk fix library and utility",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"help",
"dist",
"SECURITY.md",
"LICENSE",
"README.md"
],
"directories": {
"lib": "src",
"test": "test"
},
"bin": {
"snyk-fix": "dist/index.js"
},
"engines": {
"node": ">=8"
},
"scripts": {
"build": "tsc",
"test": "jest"
},
"keywords": [
"security",
"vulnerabilities",
"advisories",
"audit",
"snyk",
"scan",
"docker",
"container",
"scanning"
],
"author": "snyk.io",
"license": "Apache-2.0",
"dependencies": {
"@snyk/dep-graph": "^1.21.0",
"debug": "^4.3.1"
},
"devDependencies": {
"@types/jest": "26.0.20",
"@types/node": "14.14.25",
"jest": "26.6.3",
"ts-jest": "26.5.0",
"typescript": "4.1.3"
},
"repository": {
"type": "git",
"url": "https://github.com/snyk/snyk.git"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
}
}
42 changes: 42 additions & 0 deletions packages/snyk-fix/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as debugLib from 'debug';
import { loadPlugin } from './plugins/load-plugin';
import { FixHandlerResult } from './plugins/types';

import { EntityToFix } from './types';

const debug = debugLib('snyk-fix:main');

export async function fix(
entities: EntityToFix[],
): Promise<FixHandlerResult[]> {
debug(`Requested to fix ${entities.length} projects.`);
const entitiesPerType = groupEntitiesPerType(entities);
const allResults: FixHandlerResult[] = [];
// TODO: pMap this?
for (const type of Object.keys(entitiesPerType)) {
const handler = loadPlugin(type);
const results = await handler(entitiesPerType[type]);
allResults.push(results);
}

return allResults;
}

function groupEntitiesPerType(
entities: EntityToFix[],
): {
[type: string]: EntityToFix[];
} {
const entitiesPerType: {
[type: string]: EntityToFix[];
} = {};
for (const entity of entities) {
const type = entity.scanResult.identity.type;
if (entitiesPerType[type]) {
entitiesPerType[type].push(entity);
continue;
}
entitiesPerType[type] = [entity];
}
return entitiesPerType;
}
15 changes: 15 additions & 0 deletions packages/snyk-fix/src/lib/errors/custom-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export class CustomError extends Error {
public innerError?: Error;
public errorCode: string;

public constructor(message: string, errorCode: ERROR_CODES) {
super(message);
this.name = this.constructor.name;
this.innerError = undefined;
this.errorCode = errorCode;
}
}

export enum ERROR_CODES {
UnsupportedTypeError = 'G1',
}
9 changes: 9 additions & 0 deletions packages/snyk-fix/src/lib/errors/error-to-user-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { UnsupportedTypeError } from "./unsupported-type-error";

export function convertErrorToUserMessage(error) {
const errorMessagePrefix = `Error ${error.code} (${error.name})`;
if (error instanceof UnsupportedTypeError) {
return `${errorMessagePrefix} ${error.scanType} is not supported.`;
}

}
13 changes: 13 additions & 0 deletions packages/snyk-fix/src/lib/errors/unsupported-type-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { CustomError, ERROR_CODES } from './custom-error';

export class UnsupportedTypeError extends CustomError {
public scanType: string;

public constructor(scanType: string) {
super(
'Provided scan type is not supported',
ERROR_CODES.UnsupportedTypeError,
);
this.scanType = scanType;
}
}
13 changes: 13 additions & 0 deletions packages/snyk-fix/src/plugins/load-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { UnsupportedTypeError } from '../lib/errors/unsupported-type-error';
import { pythonFix } from './python';

export function loadPlugin(type: string) {
switch (type) {
case 'pip': {
return pythonFix;
}
default: {
throw new UnsupportedTypeError(type);
}
}
}
15 changes: 15 additions & 0 deletions packages/snyk-fix/src/plugins/python/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as debugLib from 'debug';

import { EntityToFix } from '../../types';
import { FixHandlerResult } from '../types';

const debug = debugLib('snyk-fix:python');

export async function pythonFix(
entities: EntityToFix[],
): Promise<FixHandlerResult> {
debug(`Preparing to fix ${entities.length} Python projects`);
const succeeded: EntityToFix[] = entities;
const failed: EntityToFix[] = [];
return { succeeded, failed };
}
8 changes: 8 additions & 0 deletions packages/snyk-fix/src/plugins/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { EntityToFix } from '../types';

export type FixHandler = (entities: EntityToFix[]) => Promise<FixHandlerResult[]>;

export interface FixHandlerResult {
succeeded: EntityToFix[];
failed: EntityToFix[];
}