Skip to content

Commit 9e2977b

Browse files
committed
Fixinator Client Version 6.0.0
* Add support for running Fixinator Enterprise directly inside commandbox (requires enterprise version 6.0.0+). * Reporting enhancements. * Command argument validation. * Autocomplete goals on tab
1 parent d06ee7c commit 9e2977b

File tree

5 files changed

+292
-40
lines changed

5 files changed

+292
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Default: `false` - Prints out a list of scanners supported by the server in the
6464

6565
Default: `false` - When `true` scans only files changed in the HEAD git commit, this is useful in CI to scan only the files changed in a specific commit.
6666

67-
### gitWorkingCopy
67+
### gitChanged
6868

6969
Default: `false` - When `true` scans only the files changed in the working copy (compared to the HEAD git commit). This is useful to scan only the files you have modified since your last git commit.
7070

box.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"name":"fixinator",
3-
"version":"5.0.1",
3+
"version":"6.0.0",
44
"author":"Foundeo Inc.",
5-
"location":"foundeo/fixinator#v5.0.1",
5+
"location":"foundeo/fixinator#v6.0.0",
66
"homepage":"https://fixinator.app/",
77
"documentation":"https://github.com/foundeo/fixinator/wiki",
88
"repository":{

commands/fixinator.cfc

Lines changed: 123 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,29 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
1515
property name="shell" inject="shell";
1616

1717

18+
//used for validation to avoid typos
19+
variables.supportedArgs = ["path",
20+
"resultFile",
21+
"resultFormat",
22+
"verbose",
23+
"listBy",
24+
"severity",
25+
"confidence",
26+
"ignoreScanners",
27+
"autofix",
28+
"failOnIssues",
29+
"debug",
30+
"listScanners",
31+
"ignorePaths",
32+
"ignoreExtensions",
33+
"gitLastCommit",
34+
"gitChanged",
35+
"engines",
36+
"includeScanners",
37+
"configFile",
38+
"goals"
39+
];
40+
1841
/**
1942
* @path.hint A file or directory to scan
2043
* @resultFile.hint A file path to write the results to - see resultFormat
@@ -26,24 +49,25 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
2649
* @severity.optionsUDF severityComplete
2750
* @confidence.hint The minimum confidence level none, low, medium or high
2851
* @confidence.optionsUDF confidenceComplete
29-
* @ignoreScanners.hint A comma seperated list of scanner ids to ignore
52+
* @ignoreScanners.hint A comma separated list of scanner ids to ignore
3053
* @autofix.hint Use either off, prompt or automatic
3154
* @failOnIssues.hint Determines if an exit code is set to 1 when issues are found.
3255
* @debug.hint Enable debug mode
3356
* @listScanners.hint List the types of scanners that are enabled, enabled automatically when verbose=true
3457
* @ignorePaths.hint A globber paths pattern to exclude
3558
* @ignoreExtensions.hint A list of extensions to exclude
3659
* @gitLastCommit.hint Scan only files changed in the last git commit
37-
* @gitWorkingCopy.hint Scan only files changed since the last commit in the working copy
60+
* @gitChanged.hint Scan only files changed since the last commit in the working copy
3861
* @engines.hint A list of engines your code runs on, eg: lucee@5,adobe@2023 default any
39-
* @includeScanners.hint A comma seperated list of scanner ids to scan, all others ignored
62+
* @includeScanners.hint A comma separated list of scanner ids to scan, all others ignored
4063
* @configFile.hint A path to a .fixinator.json file to use
4164
* @goals.hint A list of goals for scanning [compatibility,security], default: security
65+
* @goals.optionsUDF goalsComplete
4266
**/
4367
function run(
4468
string path=".",
4569
string resultFile,
46-
string resultFormat="json",
70+
string resultFormat="",
4771
boolean verbose=true,
4872
string listBy="type",
4973
string severity="default",
@@ -68,10 +92,12 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
6892
var config = {};
6993
var toFix = [];
7094
var paths = [];
95+
var isEnterprise = false;
96+
var arg = "";
7197
if (arguments.verbose) {
7298
//arguments.listScanners = true;
7399

74-
print.greenLine("fixinator v#fixinatorClient.getClientVersion()# built by Foundeo Inc.").line();
100+
print.greenLine("fixinator client v#fixinatorClient.getClientVersion()# built by Foundeo Inc.").line();
75101
print.grayLine(" ___ _ ");
76102
print.grayLine(" / __) | | ");
77103
print.grayLine(" _| |__ ___ _ _ ____ __| |_____ ___ ");
@@ -82,23 +108,47 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
82108
print.line();
83109
}
84110

111+
try {
112+
var enterpriseInstance = new fixinatorapi.app.models.fixinator();
113+
if (arguments.verbose) {
114+
print.grayLine("Fixinator Enterprise v#enterpriseInstance.getVersion()# Detected");
115+
}
116+
fixinatorClient.setFixinatorEnterpriseInstance(enterpriseInstance);
117+
if (fixinatorClient.getMaxPayloadSize() == (1024*640)) {
118+
//increase default for enterprise version to 2mb, can be overridden in settings
119+
fixinatorClient.setMaxPayloadSize(2*1024*1024);
120+
}
121+
isEnterprise = true;
122+
} catch(any entErr) {
123+
//not using enterprise version
124+
}
85125

126+
//validate arguments
127+
for (arg in arguments) {
128+
if (!arrayFindNoCase(variables.supportedArgs, arg)) {
129+
print.boldRedLine("Invalid argument: #reReplace(arg, '[^a-zA-Z0-9]', '', 'ALL')# passed to fixinator.");
130+
print.redLine("Type help fixinator to see the supported arguments.");
131+
setExitCode(1);
132+
return;
133+
}
134+
}
86135

87136
if (configService.getSetting("modules.fixinator.api_key", "UNDEFINED") != "UNDEFINED") {
88137
fixinatorClient.setAPIKey(configService.getSetting("modules.fixinator.api_key", "UNDEFINED"));
89138
}
90139

91-
if (fixinatorClient.getAPIKey() == "UNDEFINED") {
140+
if (!fixinatorClient.hasFixinatorEnterpriseInstance() && fixinatorClient.getAPIKey() == "UNDEFINED") {
92141
print.boldOrangeLine("Missing Fixinator API Key");
93142
print.orangeLine(" Set via commandbox: config set modules.fixinator.api_key=YOUR_API_KEY");
94143
print.orangeLine(" Or set an environment variable FIXINATOR_API_KEY=YOUR_API_KEY");
95144
print.line();
96-
print.line("For details please visit: https://fixinator.app/");
145+
print.line("An API Key is required, unless you are using the Enterprise Version of Fixinator.");
146+
print.line(" For details please visit: https://fixinator.app/");
97147
print.line();
98148
if (isRunningInCI()) {
99149
//in CI we don't want to prompt
100-
print.line("Detected CI Envrionment. Please add the FIXINATOR_API_KEY as a secure environment variable to your CI platform.");
101-
150+
print.line("Detected CI Environment. Please add the FIXINATOR_API_KEY as a secure environment variable to your CI platform.");
151+
102152
if (isTravisCI()) {
103153
print.line("Documentation: https://github.com/foundeo/fixinator/wiki/Running-Fixinator-on-Travis-CI");
104154
}
@@ -119,17 +169,27 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
119169
print.line("Documentation: https://github.com/foundeo/fixinator/wiki/Running-Fixinator-on-Jenkins");
120170
}
121171

172+
print.line();
173+
print.line("Running the Enterprise Version of Fixinator?");
174+
printEnterpriseInstallInstructions();
122175

123176
setExitCode(1);
124177
return;
125-
} else {
178+
}
179+
126180

127-
}
128181
print.line();
129182
print.line("To request a free trial api key, please go here: https://fixinator.app/try/");
130183
local.answer = ask(message="Would you like to open https://fixinator.app/try/ in your browser now? [y/n]: ");
131184
if (left(local.answer, 1) == "y") {
132185
command("browse").params(URI="https://fixinator.app/try/").run();
186+
} else {
187+
print.line();
188+
local.answer = ask(message="Do you have a Fixinator Enterprise Version License? [y/n]: ");
189+
if (left(local.answer, 1) == "y") {
190+
print.line("You do not need an API key to run the Fixinator Enterprise Version Locally.");
191+
printEnterpriseInstallInstructions();
192+
}
133193
}
134194
print.line();
135195
print.line("Exiting Fixinator, please try again once you have an api key");
@@ -141,7 +201,7 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
141201
fixinatorClient.setAPIURL(configService.getSetting("modules.fixinator.api_url", "UNDEFINED"));
142202
}
143203

144-
if (fixinatorClient.isCloudAPIURL() && configService.getSetting("modules.fixinator.accept_policy", "UNDEFINED") == "UNDEFINED") {
204+
if (!fixinatorClient.hasFixinatorEnterpriseInstance() && fixinatorClient.isCloudAPIURL() && configService.getSetting("modules.fixinator.accept_policy", "UNDEFINED") == "UNDEFINED") {
145205
print.line();
146206
print.line("Fixinator will send source code to: " & fixinatorClient.getAPIURL());
147207
print.line("for scanning. The code is kept in RAM during scanning and is not persisted.");
@@ -164,6 +224,22 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
164224

165225
}
166226

227+
if (!fixinatorClient.hasFixinatorEnterpriseInstance() && fixinatorClient.isCloudAPIURL() && left(fixinatorClient.getAPIKey(), 1) != "f") {
228+
var maskedKey = left(fixinatorClient.getAPIKey(), 4);
229+
if (len(fixinatorClient.getAPIKey()) > 4) {
230+
maskedKey &= repeatString("*", len(fixinatorClient.getAPIKey())-4);
231+
}
232+
if (fixinatorClient.getAPIKey() == "UNDEFINED") {
233+
maskedKey = "UNDEFINED";
234+
}
235+
print.line();
236+
print.line("Invalid License Key(#maskedKey#) for API Server: " & fixinatorClient.getAPIURL());
237+
print.line("Running the Enterprise Version?");
238+
printEnterpriseInstallInstructions();
239+
setExitCode(1);
240+
return;
241+
}
242+
167243

168244

169245
if (configService.getSetting("modules.fixinator.max_payload_size", "UNDEFINED") != "UNDEFINED") {
@@ -182,7 +258,7 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
182258
fixinatorClient.setMaxConcurrency(configService.getSetting("modules.fixinator.max_concurrency", "8"));
183259
}
184260

185-
if (arguments.verbose) {
261+
if (arguments.verbose && !fixinatorClient.hasFixinatorEnterpriseInstance()) {
186262
print.greenLine("Fixinator API Server: #fixinatorClient.getAPIURL()#");
187263
}
188264

@@ -438,6 +514,17 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
438514

439515
if (len(arguments.resultFile)) {
440516
local.resultIndex = 0;
517+
//default resultFormat to the file extension if supported
518+
if (len(arguments.resultFormat) == 0) {
519+
if (listFindNoCase("pdf,html,csv,json", listLast(arguments.resultFile, "."))) {
520+
arguments.resultFormat = lcase(listLast(arguments.resultFile, "."));
521+
} else {
522+
//defaults to json
523+
arguments.resultFormat = "json";
524+
}
525+
}
526+
local.results["fixinatorArguments"] = duplicate(arguments);
527+
local.results["fixinatorArguments"]["pwd"] = shell.pwd();
441528
//allow a list of formats and file paths
442529
for (local.rFormat in listToArray(arguments.resultFormat)) {
443530
local.resultIndex++;
@@ -449,8 +536,16 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
449536

450537

451538
if (arrayLen(local.results.results) == 0 && arrayLen(local.results.warnings) == 0) {
452-
print.line().boldGreenLine("0 Issues Found");
539+
print.line().boldGreenLine("0 Issues Found");
453540
if (arguments.verbose) {
541+
print.line();
542+
print.greenLine(" //");
543+
print.greenLine(" //");
544+
print.greenLine(" //");
545+
print.greenLine(" \\ //");
546+
print.greenLine(" \\//");
547+
548+
print.line();
454549
if (local.results.config.minSeverity != "low" || local.results.config.minConfidence != "low") {
455550
print.line().line("Tip: For additional results try decreasing the severity or confidence level to medium or low");
456551
print.line("For example: box fixinator confidence=low path=/some/file.cfm");
@@ -717,6 +812,20 @@ component extends="commandbox.system.BaseCommand" excludeFromHelp=false {
717812
return [ 'low', 'medium', 'high', 'warn' ];
718813
}
719814

815+
function goalsComplete() {
816+
return [ 'security', 'compatibility', 'security,compatibility' ];
817+
}
818+
819+
private function printEnterpriseInstallInstructions() {
820+
print.boldLine("Perform one of these steps to setup the enterprise version:");
821+
print.line(" * Install the fixinator enterprise command (version 6 and up): ");
822+
print.line(" box install c:\temp\fixinator-enterprise-x.y.z.zip")
823+
print.line(" * Or if running your own Fixinator server set the FIXINATOR_API_URL environment variable or run:");
824+
print.line(" box config set modules.fixinator.api_url=http://127.0.0.1:48443/scan/");
825+
print.line();
826+
print.line("See instructions.txt located in your fixinator-enterprise.zip file for details.");
827+
print.line("The zip file can be downloaded from your customer account on foundeo.com");
828+
}
720829

721830
private boolean function isRunningInCI() {
722831
var env = server.system.environment;

models/fixinator/FixinatorClient.cfc

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
component singleton="true" {
1+
component {
22

33
variables.system = createObject("java", "java.lang.System");
44
variables.maxPayloadSize = 1 * 640 * 1024;//half mb+128b
@@ -233,10 +233,26 @@ component singleton="true" {
233233
variables.maxPayloadSize = arguments.size;
234234
}
235235

236+
public function getMaxPayloadSize() {
237+
return variables.maxPayloadSize;
238+
}
239+
236240
public function setMaxPayloadFileCount(numeric count) {
237241
variables.maxPayloadFileCount = arguments.count;
238242
}
239243

244+
public function setFixinatorEnterpriseInstance(any instance) {
245+
variables.fixinatorEnterpriseInstance = arguments.instance;
246+
}
247+
248+
public function getFixinatorEnterpriseInstance() {
249+
return variables.fixinatorEnterpriseInstance;
250+
}
251+
252+
public function hasFixinatorEnterpriseInstance() {
253+
return variables.keyExists("fixinatorEnterpriseInstance");
254+
}
255+
240256
private function processBatch(element, index) {
241257

242258
if (element.batchType == "progressBar") {
@@ -405,6 +421,12 @@ component singleton="true" {
405421

406422
public function sendPayload(payload, isRetry=0) {
407423
var httpResult = "";
424+
425+
//if enterprise version locally installed, use that
426+
if (hasFixinatorEnterpriseInstance()) {
427+
return sendPayloadEnterprise(payload=arguments.payload);
428+
}
429+
408430
local.payloadID = left(createUUID(),12);
409431
if (isDebugModeEnabled()) {
410432

@@ -414,6 +436,7 @@ component singleton="true" {
414436
debugger("Sending Payload #local.payloadID# to #getAPIURL()# of #arrayLen(arguments.payload.files)# files. isRetry:#arguments.isRetry#");
415437
debugger("Payload Paths #local.payloadID#: #serializeJSON(local.payloadPaths)#");
416438
}
439+
417440
local.tick = getTickCount();
418441
cfhttp(url=getAPIURL(), method="POST", result="httpResult", timeout=getAPITimeout()) {
419442
cfhttpparam(type="header", name="Content-Type", value="application/json");
@@ -519,6 +542,19 @@ component singleton="true" {
519542
return deserializeJSON(httpResult.fileContent);
520543
}
521544

545+
public function sendPayloadEnterprise(payload) {
546+
if (isDebugModeEnabled()) {
547+
local.payloadID = left(createUUID(),12);
548+
local.payloadPaths = arrayMap(arguments.payload.files, function(item) {
549+
return item.path;
550+
});
551+
debugger("Sending Payload #local.payloadID# of #arrayLen(arguments.payload.files)# files to Fixinator Enterprise.");
552+
debugger("Payload Paths #local.payloadID#: #serializeJSON(local.payloadPaths)#");
553+
}
554+
var fixinatorEnterprise = getFixinatorEnterpriseInstance();
555+
return fixinatorEnterprise.scan(payload);
556+
}
557+
522558
public function getAPIKey() {
523559
if (structKeyExistS(variables, "fixinatorAPIKey")) {
524560
return variables.fixinatorAPIKey;

0 commit comments

Comments
 (0)