diff --git a/Jenkinsfile b/Jenkinsfile index 48bf230..4ac4572 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1 +1,6 @@ -buildPlugin() \ No newline at end of file +buildPlugin( + configurations: [ + [platform: 'linux', jdk: 21], // Update to the desired JDK version + [platform: 'windows', jdk: 21] // Update to the desired JDK version + ] +) \ No newline at end of file diff --git a/README.md b/README.md index 3d8842b..7be506b 100644 --- a/README.md +++ b/README.md @@ -79,12 +79,12 @@ stages { steps { script { // Perform Appknox scan using AppknoxScanner - step([ - $class: 'AppknoxScanner', + appKnoxScanner( credentialsId: 'your-appknox-access-token-ID', //Specify the Appknox Access Token ID. Ensure the ID matches with the ID given while configuring Appknox Access Token in the credentials. filePath: FILE_PATH, - riskThreshold: params.RISK_THRESHOLD.toUpperCase() - ]) + riskThreshold: params.RISK_THRESHOLD.toUpperCase(), + region: params.Region // Pass the region parameter as expected + ) } } @@ -95,11 +95,12 @@ stages { ## Inputs -| Key | Value | -|-------------------------|------------------------------| -| `credentialsId` | Personal appknox access token ID | -| `file_path` | Specify the build file name or path for the mobile application binary to upload, E.g. app-debug.apk, app/build/apk/app-debug.apk | -| `risk_threshold` | Risk threshold value for which the CI should fail.

Accepted values: `CRITICAL, HIGH, MEDIUM & LOW`

Default: `LOW` | +| Key | Value | +|-------------------|------------------------------| +| `credentialsId` | Personal appknox access token ID | +| `file_path` | Specify the build file name or path for the mobile application binary to upload, E.g. app-debug.apk, app/build/apk/app-debug.apk | +| `risk_threshold` | Risk threshold value for which the CI should fail.

Accepted values: `CRITICAL, HIGH, MEDIUM & LOW`

Default: `LOW` | +| `region` | Specify the Appknox region.

Accepted values: 'Global, Saudi'

Default: 'Global' | --- @@ -109,6 +110,7 @@ pipeline { agent any parameters { choice(name: 'RISK_THRESHOLD', choices: ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'], description: 'Risk Threshold') + choice(name: 'Region', choices: ['global', 'saudi'], description: 'Appknox Regions') } stages { stage('Checkout') { @@ -129,12 +131,12 @@ pipeline { steps { script { // Perform Appknox scan using AppknoxScanner - step([ - $class: 'AppknoxScanner', - credentialsId: 'your-appknox-access-token-id', //Specify the Appknox Access Token ID. Ensure the ID matches with the ID given while configuring Appknox Access Token in the credentials. + appKnoxScanner( + credentialsId: 'your-appknox-access-token-ID', //Specify the Appknox Access Token ID. Ensure the ID matches with the ID given while configuring Appknox Access Token in the credentials. filePath: FILE_PATH, - riskThreshold: params.RISK_THRESHOLD.toUpperCase() - ]) + riskThreshold: params.RISK_THRESHOLD.toUpperCase(), + region: params.Region // Pass the region parameter as expected + ) } } @@ -142,4 +144,4 @@ pipeline { } } -``` +``` \ No newline at end of file diff --git a/src/main/java/io/jenkins/plugins/AppknoxScanner.java b/src/main/java/io/jenkins/plugins/scanner/AppknoxScanner.java similarity index 95% rename from src/main/java/io/jenkins/plugins/AppknoxScanner.java rename to src/main/java/io/jenkins/plugins/scanner/AppknoxScanner.java index 93120bb..58019e6 100644 --- a/src/main/java/io/jenkins/plugins/AppknoxScanner.java +++ b/src/main/java/io/jenkins/plugins/scanner/AppknoxScanner.java @@ -1,4 +1,4 @@ -package io.jenkins.plugins; +package io.jenkins.plugins.scanner; import hudson.Extension; import hudson.FilePath; @@ -57,20 +57,23 @@ import org.apache.commons.io.FileUtils; +@Symbol("appKnoxScanner") public class AppknoxScanner extends Builder implements SimpleBuildStep { private final String credentialsId; private final String filePath; private final String riskThreshold; + private final String apiHost; - private static final String binaryVersion = "1.3.1"; + private static final String binaryVersion = "1.6.0"; private static final String osName = System.getProperty("os.name").toLowerCase(); private static final String CLI_DOWNLOAD_PATH = System.getProperty("user.home") + File.separator + "appknox"; @DataBoundConstructor - public AppknoxScanner(String credentialsId, String filePath, String riskThreshold) { + public AppknoxScanner(String credentialsId, String filePath, String riskThreshold, String apiHost) { this.credentialsId = credentialsId; this.filePath = filePath; this.riskThreshold = riskThreshold; + this.apiHost = apiHost; } public String getCredentialsId() { @@ -85,6 +88,10 @@ public String getRiskThreshold() { return riskThreshold; } + public String getApiHost() { + return apiHost; + } + @Override public void perform(Run run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { @@ -111,6 +118,8 @@ private boolean executeAppknoxCommands(Run run, FilePath workspace, String env.put("APPKNOX_ACCESS_TOKEN", accessToken); String appknoxPath = downloadAndInstallAppknox(osName, listener); + listener.getLogger().println("Selected Region: " + apiHost); + // Determine if the file is an APK or IPA based on extension String appFilePath = findAppFilePath(workspace.getRemote(), filePath, listener); @@ -214,6 +223,7 @@ private String findAppFilePathRecursive(File dir, String fileName, TaskListener return null; } + private String extractFileID(String uploadOutput, TaskListener listener) { String[] lines = uploadOutput.split("\n"); if (lines.length > 0) { @@ -259,7 +269,7 @@ private String downloadAndInstallAppknox(String os, TaskListener listener) listener.getLogger().println("Appknox CLI already exists at: " + CLI_DOWNLOAD_PATH); } - addPathToEnvironment(CLI_DOWNLOAD_PATH, listener); + listener.getLogger().println("Appknox CLI located at: " + CLI_DOWNLOAD_PATH); return CLI_DOWNLOAD_PATH; } @@ -293,12 +303,6 @@ private void downloadFile(String url, String destinationPath, TaskListener liste } } - private void addPathToEnvironment(String path, TaskListener listener) { - String existingPath = System.getenv("PATH"); - String newPath = path + File.pathSeparator + existingPath; - System.setProperty("PATH", newPath); - } - private String uploadFile(String appknoxPath, TaskListener listener, Map env, String appFilePath) throws IOException, InterruptedException { String accessToken = getAccessToken(listener); @@ -309,6 +313,8 @@ private String uploadFile(String appknoxPath, TaskListener listener, Map run, String fileID, Tas command.add(fileID); command.add("--risk-threshold"); command.add(riskThreshold); + command.add("--region"); + command.add(apiHost); ProcessBuilder pb = new ProcessBuilder(command); pb.environment().putAll(env); @@ -398,6 +406,8 @@ private String createReport(String appknoxPath, String fileID, TaskListener list command.add("reports"); command.add("create"); command.add(fileID); + command.add("--region"); + command.add(apiHost); ProcessBuilder pb = new ProcessBuilder(command); pb.environment().putAll(env); @@ -439,6 +449,8 @@ private void downloadReportSummaryCSV(String appknoxPath, String reportName, Str command.add(reportID); command.add("--output"); command.add(workspace.child(reportName).getRemote()); + command.add("--region"); + command.add(apiHost); ProcessBuilder pb = new ProcessBuilder(command); pb.environment().putAll(env); @@ -508,6 +520,14 @@ public String getDisplayName() { return "Appknox Security Scanner"; } + @POST + public ListBoxModel doFillApiHostItems() { + return new ListBoxModel( + new ListBoxModel.Option("Global", "global"), + new ListBoxModel.Option("Saudi", "saudi") + ); + } + @SuppressWarnings("deprecation") @POST public ListBoxModel doFillCredentialsIdItems(@AncestorInPath ItemGroup context) { diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly index 00ef09e..65aa504 100644 --- a/src/main/resources/index.jelly +++ b/src/main/resources/index.jelly @@ -1,4 +1,4 @@
- The Appknox Security Scan Plugin allows you to perform Appknox security scan on your mobile application binary. + This plugin allows you to perform Appknox security scan on your mobile application binary.
\ No newline at end of file diff --git a/src/main/resources/io/jenkins/plugins/AppknoxScanner/config.jelly b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/config.jelly similarity index 73% rename from src/main/resources/io/jenkins/plugins/AppknoxScanner/config.jelly rename to src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/config.jelly index 99bc3e4..ed3331d 100644 --- a/src/main/resources/io/jenkins/plugins/AppknoxScanner/config.jelly +++ b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/config.jelly @@ -16,8 +16,14 @@ + + + Global + Saudi + + -

${%requiredFields}

-
+

${%requiredFields}

+ diff --git a/src/main/resources/io/jenkins/plugins/AppknoxScanner/config.properties b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/config.properties similarity index 53% rename from src/main/resources/io/jenkins/plugins/AppknoxScanner/config.properties rename to src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/config.properties index 636e5e2..a36aa8f 100644 --- a/src/main/resources/io/jenkins/plugins/AppknoxScanner/config.properties +++ b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/config.properties @@ -1,5 +1,6 @@ filePath = File Path * -note: Note +note = Note riskThreshold = Risk Threshold * credentialsId = Appknox Access Token * -requiredFields=* indicates required fields \ No newline at end of file +requiredFields = * indicates required fields +region = Appknox Regions * diff --git a/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-apiHost.html b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-apiHost.html new file mode 100644 index 0000000..7cf0c42 --- /dev/null +++ b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-apiHost.html @@ -0,0 +1,3 @@ +
+ Select a region if you're using a different cloud instance of Appknox than the default global region. +
diff --git a/src/main/resources/io/jenkins/plugins/AppknoxScanner/help-credentialsId.html b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-credentialsId.html similarity index 100% rename from src/main/resources/io/jenkins/plugins/AppknoxScanner/help-credentialsId.html rename to src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-credentialsId.html diff --git a/src/main/resources/io/jenkins/plugins/AppknoxScanner/help-filePath.html b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-filePath.html similarity index 100% rename from src/main/resources/io/jenkins/plugins/AppknoxScanner/help-filePath.html rename to src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-filePath.html diff --git a/src/main/resources/io/jenkins/plugins/AppknoxScanner/help-riskThreshold.html b/src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-riskThreshold.html similarity index 100% rename from src/main/resources/io/jenkins/plugins/AppknoxScanner/help-riskThreshold.html rename to src/main/resources/io/jenkins/plugins/scanner/AppknoxScanner/help-riskThreshold.html