@soos-io/soos-sbom 0.1.0-pre.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -8
- package/bin/index.js +109 -121
- package/bin/utils/constants.d.ts +3 -3
- package/bin/utils/constants.js +3 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
|
-
# soos-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
# [SOOS SBOM](https://soos.io/products/sbom-manager)
|
|
2
|
+
|
|
3
|
+
SOOS is an independent software security company, located in Winooski, VT USA, building security software for your team. [SOOS, Software security, simplified](https://soos.io).
|
|
4
|
+
|
|
5
|
+
Use SOOS to scan your software for [vulnerabilities](https://app.soos.io/research/vulnerabilities) and [open source license](https://app.soos.io/research/licenses) issues with [SOOS Core SCA](https://soos.io/sca-product). [Generate SBOMs](https://kb.soos.io/help/generating-a-software-bill-of-materials-sbom). Govern your open source dependencies. Run the [SOOS DAST vulnerability scanner](https://soos.io/dast-product) against your web apps or APIs.
|
|
6
|
+
|
|
7
|
+
[Demo SOOS](https://app.soos.io/demo) or [Register for a Free Trial](https://app.soos.io/register).
|
|
8
|
+
|
|
9
|
+
If you maintain an Open Source project, sign up for the Free as in Beer [SOOS Community Edition](https://soos.io/products/community-edition).
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
run `npm i -g @soos-io/soos-sbom@latest`
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
Run `soos-sbom` from any terminal and add the parameters you want.
|
|
19
|
+
|
|
20
|
+
## Parameters
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
| Argument | Default | Description |
|
|
24
|
+
| ----------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
25
|
+
| `--apiKey` | `getEnvVariable(CONSTANTS.SOOS.API_KEY_ENV_VAR)` | SOOS API Key - get yours from [SOOS Integration](https://app.soos.io/integrate/sbom). |
|
|
26
|
+
| `--apiURL` | `"https://api.soos.io/api/"` | SOOS API URL - Intended for internal use only, do not modify. |
|
|
27
|
+
| `--appVersion` | N/A | App Version - Intended for internal use only. |
|
|
28
|
+
| `--branchName` | `null` | The name of the branch from the SCM System. |
|
|
29
|
+
| `--branchURI` | `null` | The URI to the branch from the SCM System. |
|
|
30
|
+
| `--buildURI` | `null` | URI to CI build info. |
|
|
31
|
+
| `--buildVersion` | `null` | Version of application build artifacts. |
|
|
32
|
+
| `--clientId` | `getEnvVariable(CONSTANTS.SOOS.CLIENT_ID_ENV_VAR)` | SOOS Client ID - get yours from [SOOS Integration](https://app.soos.io/integrate/sbom). |
|
|
33
|
+
| `--commitHash` | `null` | The commit hash value from the SCM System. |
|
|
34
|
+
| `--integrationName` | N/A | Integration Name - Intended for internal use only. |
|
|
35
|
+
| `--integrationType` | N/A | Integration Type - Intended for internal use only. |
|
|
36
|
+
| `--logLevel` | `LogLevel.INFO` | Minimum level to show logs: PASS, IGNORE, INFO, WARN, or FAIL. |
|
|
37
|
+
| `--operatingEnvironment`| `null` | Set Operating environment for information purposes only. |
|
|
38
|
+
| `--otherOptions` | `null` | Other Options to pass to syft. |
|
|
39
|
+
| `--projectName` | N/A | Project Name - this is what will be displayed in the SOOS app. |
|
|
40
|
+
| `--scriptVersion` | N/A | Script Version - Intended for internal use only. |
|
|
41
|
+
| `--verbose` | `false` | Enable verbose logging. |
|
|
42
|
+
| `sbomPath` | N/A | The SBOM File to scan, it could be the location of the file or the file itself. When location is specified only the first file found will be scanned. |
|
package/bin/index.js
CHANGED
|
@@ -83,11 +83,6 @@ class SOOSSBOMAnalysis {
|
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
});
|
|
86
|
-
parser.add_argument("--onFailure", {
|
|
87
|
-
help: "Action to perform when the scan fails. Options: fail_the_build, continue_on_failure.",
|
|
88
|
-
default: "continue_on_failure",
|
|
89
|
-
required: false,
|
|
90
|
-
});
|
|
91
86
|
parser.add_argument("--operatingEnvironment", {
|
|
92
87
|
help: "Set Operating environment for information purposes only.",
|
|
93
88
|
default: null,
|
|
@@ -118,131 +113,124 @@ class SOOSSBOMAnalysis {
|
|
|
118
113
|
api_client_1.soosLogger.info("Parsing arguments");
|
|
119
114
|
return parser.parse_args();
|
|
120
115
|
}
|
|
121
|
-
runAnalysis() {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
116
|
+
async runAnalysis() {
|
|
117
|
+
let projectHash;
|
|
118
|
+
let branchHash;
|
|
119
|
+
let analysisId;
|
|
120
|
+
const filePath = await this.findSbomFilePath();
|
|
121
|
+
const soosAnalysisApiClient = new SOOSAnalysisApiClient_1.default(this.args.apiKey, this.args.apiURL);
|
|
122
|
+
try {
|
|
123
|
+
api_client_1.soosLogger.info("Starting SOOS SBOM Analysis");
|
|
124
|
+
api_client_1.soosLogger.info(`Creating scan for project '${this.args.projectName}'...`);
|
|
125
|
+
api_client_1.soosLogger.info(`Branch Name: ${this.args.branchName}`);
|
|
126
|
+
const result = await soosAnalysisApiClient.createScan({
|
|
127
|
+
clientId: this.args.clientId,
|
|
128
|
+
projectName: this.args.projectName,
|
|
129
|
+
commitHash: this.args.commitHash,
|
|
130
|
+
branch: this.args.branchName,
|
|
131
|
+
buildVersion: this.args.buildVersion,
|
|
132
|
+
buildUri: this.args.buildUri,
|
|
133
|
+
branchUri: this.args.branchUri,
|
|
134
|
+
integrationType: this.args.integrationType,
|
|
135
|
+
operatingEnvironment: this.args.operatingEnvironment,
|
|
136
|
+
integrationName: this.args.integrationName,
|
|
137
|
+
appVersion: this.args.appVersion,
|
|
138
|
+
scriptVersion: null,
|
|
139
|
+
contributingDeveloperAudit: undefined,
|
|
140
|
+
scanType: api_client_1.ScanType.SBOM,
|
|
141
|
+
toolName: null,
|
|
142
|
+
toolVersion: null,
|
|
143
|
+
});
|
|
144
|
+
projectHash = result.projectHash;
|
|
145
|
+
branchHash = result.branchHash;
|
|
146
|
+
analysisId = result.analysisId;
|
|
147
|
+
api_client_1.soosLogger.info(`Project Hash: ${projectHash}`);
|
|
148
|
+
api_client_1.soosLogger.info(`Branch Hash: ${branchHash}`);
|
|
149
|
+
api_client_1.soosLogger.info(`Scan Id: ${analysisId}`);
|
|
150
|
+
api_client_1.soosLogger.info("Scan created successfully.");
|
|
151
|
+
api_client_1.soosLogger.logLineSeparator();
|
|
152
|
+
api_client_1.soosLogger.info("Uploading SBOM File");
|
|
153
|
+
const formData = await this.getSbomAsFormData(filePath);
|
|
154
|
+
const uploadManifestFilesResponse = await soosAnalysisApiClient.uploadManifestFiles({
|
|
155
|
+
clientId: this.args.clientId,
|
|
156
|
+
projectHash,
|
|
157
|
+
branchHash,
|
|
158
|
+
analysisId,
|
|
159
|
+
manifestFiles: formData,
|
|
160
|
+
});
|
|
161
|
+
api_client_1.soosLogger.info(` SBOM Files: \n`, ` ${uploadManifestFilesResponse.message} \n`, uploadManifestFilesResponse.manifests
|
|
162
|
+
?.map((m) => ` ${m.name}: ${m.statusMessage}`)
|
|
163
|
+
.join("\n"));
|
|
164
|
+
api_client_1.soosLogger.logLineSeparator();
|
|
165
|
+
api_client_1.soosLogger.info("Starting SBOM Analysis scan");
|
|
166
|
+
await soosAnalysisApiClient.startScan({
|
|
167
|
+
clientId: this.args.clientId,
|
|
168
|
+
projectHash,
|
|
169
|
+
analysisId: analysisId,
|
|
170
|
+
});
|
|
171
|
+
api_client_1.soosLogger.info(`Analysis scan started successfully, to see the results visit: ${result.scanUrl}`);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (projectHash && branchHash && analysisId)
|
|
175
|
+
await soosAnalysisApiClient.updateScanStatus({
|
|
162
176
|
clientId: this.args.clientId,
|
|
163
177
|
projectHash,
|
|
164
178
|
branchHash,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
api_client_1.soosLogger.logLineSeparator();
|
|
170
|
-
api_client_1.soosLogger.info("Starting SBOM Analysis scan");
|
|
171
|
-
yield soosAnalysisApiClient.startScan({
|
|
172
|
-
clientId: this.args.clientId,
|
|
173
|
-
projectHash,
|
|
174
|
-
analysisId: analysisId,
|
|
179
|
+
scanType: api_client_1.ScanType.SBOM,
|
|
180
|
+
scanId: analysisId,
|
|
181
|
+
status: api_client_1.ScanStatus.Error,
|
|
182
|
+
message: `Error while performing scan.`,
|
|
175
183
|
});
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (projectHash && branchHash && analysisId)
|
|
180
|
-
yield soosAnalysisApiClient.updateScanStatus({
|
|
181
|
-
clientId: this.args.clientId,
|
|
182
|
-
projectHash,
|
|
183
|
-
branchHash,
|
|
184
|
-
scanType: api_client_1.ScanType.SBOM,
|
|
185
|
-
scanId: analysisId,
|
|
186
|
-
status: api_client_1.ScanStatus.Error,
|
|
187
|
-
message: `Error while performing scan.`,
|
|
188
|
-
});
|
|
189
|
-
api_client_1.soosLogger.error(error);
|
|
190
|
-
(0, process_1.exit)(1);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
184
|
+
api_client_1.soosLogger.error(error);
|
|
185
|
+
(0, process_1.exit)(1);
|
|
186
|
+
}
|
|
193
187
|
}
|
|
194
|
-
getSbomAsFormData(filePath) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
});
|
|
188
|
+
async getSbomAsFormData(filePath) {
|
|
189
|
+
try {
|
|
190
|
+
const fileReadStream = FileSystem.createReadStream(filePath, {
|
|
191
|
+
encoding: api_client_1.SOOS_CONSTANTS.FileUploads.Encoding,
|
|
192
|
+
});
|
|
193
|
+
const formData = new form_data_1.default();
|
|
194
|
+
formData.append("file", fileReadStream);
|
|
195
|
+
return formData;
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
api_client_1.soosLogger.error(`Error on getSbomAsFormData: ${error}`);
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
209
201
|
}
|
|
210
|
-
findSbomFilePath() {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
throw new Error("No SBOM file found in the directory.");
|
|
218
|
-
}
|
|
219
|
-
return Path.join(this.args.sbomPath, sbomFile);
|
|
202
|
+
async findSbomFilePath() {
|
|
203
|
+
const sbomPathStat = await FileSystem.statSync(this.args.sbomPath);
|
|
204
|
+
if (sbomPathStat.isDirectory()) {
|
|
205
|
+
const files = await FileSystem.promises.readdir(this.args.sbomPath);
|
|
206
|
+
const sbomFile = files.find((file) => constants_1.CONSTANTS.SBOM.FILE_REGEX.test(file));
|
|
207
|
+
if (!sbomFile) {
|
|
208
|
+
throw new Error("No SBOM file found in the directory.");
|
|
220
209
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
210
|
+
return Path.join(this.args.sbomPath, sbomFile);
|
|
211
|
+
}
|
|
212
|
+
if (!constants_1.CONSTANTS.SBOM.FILE_REGEX.test(this.args.sbomPath)) {
|
|
213
|
+
throw new Error("The file does not match the required SBOM pattern.");
|
|
214
|
+
}
|
|
215
|
+
return this.args.sbomPath;
|
|
226
216
|
}
|
|
227
|
-
static createAndRun() {
|
|
228
|
-
|
|
229
|
-
|
|
217
|
+
static async createAndRun() {
|
|
218
|
+
api_client_1.soosLogger.info("Starting SOOS SBOM Analysis");
|
|
219
|
+
api_client_1.soosLogger.logLineSeparator();
|
|
220
|
+
try {
|
|
221
|
+
const args = this.parseArgs();
|
|
222
|
+
api_client_1.soosLogger.setMinLogLevel(args.logLevel);
|
|
223
|
+
api_client_1.soosLogger.setVerbose(args.verbose);
|
|
224
|
+
api_client_1.soosLogger.info("Configuration read");
|
|
225
|
+
api_client_1.soosLogger.verboseDebug(JSON.stringify((0, utilities_1.obfuscateProperties)(args, ["apiKey"]), null, 2));
|
|
230
226
|
api_client_1.soosLogger.logLineSeparator();
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const soosSBOMAnalysis = new SOOSSBOMAnalysis(args);
|
|
239
|
-
yield soosSBOMAnalysis.runAnalysis();
|
|
240
|
-
}
|
|
241
|
-
catch (error) {
|
|
242
|
-
api_client_1.soosLogger.error(`Error on createAndRun: ${error}`);
|
|
243
|
-
(0, process_1.exit)(1);
|
|
244
|
-
}
|
|
245
|
-
});
|
|
227
|
+
const soosSBOMAnalysis = new SOOSSBOMAnalysis(args);
|
|
228
|
+
await soosSBOMAnalysis.runAnalysis();
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
api_client_1.soosLogger.error(`Error on createAndRun: ${error}`);
|
|
232
|
+
(0, process_1.exit)(1);
|
|
233
|
+
}
|
|
246
234
|
}
|
|
247
235
|
}
|
|
248
236
|
SOOSSBOMAnalysis.createAndRun();
|
package/bin/utils/constants.d.ts
CHANGED
package/bin/utils/constants.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CONSTANTS = void 0;
|
|
4
4
|
exports.CONSTANTS = {
|
|
5
|
+
SBOM: {
|
|
6
|
+
FILE_REGEX: /\.(cdx|spdx)\.json$/,
|
|
7
|
+
},
|
|
5
8
|
SOOS: {
|
|
6
9
|
API_KEY_ENV_VAR: "SOOS_API_KEY",
|
|
7
10
|
CLIENT_ID_ENV_VAR: "SOOS_CLIENT_ID",
|
|
8
11
|
},
|
|
9
|
-
SBOM: {
|
|
10
|
-
FILE_REGEX: /\.(cdx|spdx)\.json$/,
|
|
11
|
-
},
|
|
12
12
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soos-io/soos-sbom",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "SOOS wrapper script to upload sboms.",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"check": "npm run format && npm run typecheck && npm outdated"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@soos-io/api-client": "0.1.
|
|
19
|
+
"@soos-io/api-client": "0.1.6",
|
|
20
20
|
"argparse": "^2.0.1",
|
|
21
21
|
"axios": "^0.27.2",
|
|
22
22
|
"tslib": "^2.6.2"
|