From 5a7be012de40fb1c109556603a6490d8bed0788d Mon Sep 17 00:00:00 2001 From: Igor Matlin Date: Wed, 25 Sep 2024 23:29:38 -0500 Subject: [PATCH 1/3] Bug fixes and additional diagnostics --- .../ZDevUploadPlugin.java | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java b/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java index 7810951..11990c6 100644 --- a/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java +++ b/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java @@ -23,6 +23,8 @@ import hudson.tasks.Recorder; import hudson.util.FormValidation; import hudson.util.Secret; +import hudson.security.Permission; +import jenkins.model.Jenkins; import jenkins.tasks.SimpleBuildStep; import net.sf.json.JSONObject; import okhttp3.*; @@ -236,6 +238,12 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi // If teamID is empty, find the correct team id by name if(teamId.isEmpty()) { log(console, "Application " + zdevAppId + " does not belong to a team. Assigning it to the " + teamName + " team."); + + // need to wait a bit; otherwise we can get 404 + synchronized(this) { + wait(checkInterval * 1000); + } + // get the list of teams to figure out team id Call teamsCall = service.listTeams(authToken); Response teamList = teamsCall.execute(); @@ -287,7 +295,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi else { log(console, "Unable to assign this app to a team. Please review team name setting and retry."); if(assignResponse.errorBody() != null) { - log(console, "HTTP " + assignResponse.code() + ": " + assignResponse.errorBody()); + log(console, "HTTP " + assignResponse.code() + ": " + assignResponse.errorBody().string()); } } } @@ -295,9 +303,22 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi log(console, "Unable to assign this app to a team. Please review team name setting and retry."); } } + else { + log(console, "Unable to assign this app to a team. Unexpected response from the server."); + if(teamList.body() != null) { + log(console, "HTTP " + teamList.code() + ": " + teamList.body().string()); + } + } + } + else { + log(console, "Unable to assign this app to a team. Please review team name setting and credentials, and retry."); + if(teamList.errorBody() != null) { + log(console, "HTTP " + teamList.code() + ": " + teamList.errorBody().string()); + } } } catch(RuntimeException e) { + log(console, "Unexpected runtime exception: " + e.getLocalizedMessage()); throw e; } catch(Exception e) { @@ -355,6 +376,15 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi break; } } + else if (statusResponse.code() != 404) { + log(console, "Unable to get assessment report. Please check credentials and try again."); + if(statusResponse.errorBody() != null) { + log(console, "HTTP " + statusResponse.code() + ": " + statusResponse.errorBody().string()); + } + run.setResult(Result.UNSTABLE); + // move on to the next one + break; + } wait(checkInterval * 1000); } @@ -419,6 +449,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi } } catch(RuntimeException e) { + log(console, "Unexpected runtime exception: " + e.getLocalizedMessage()); throw e; } catch(Exception e) { @@ -546,7 +577,6 @@ public String getDefaultTeamName() { // Validate credentials by trying to obtain access token // This method can be executed by anyone since the token is not saved or logged anywhere // Only the response code is checked - @SuppressWarnings("lgtm[jenkins/no-permission-check]") @POST public FormValidation doValidateCredentials( @QueryParameter("endpoint") final String endpoint, @@ -555,6 +585,8 @@ public FormValidation doValidateCredentials( @AncestorInPath Job job) { try { + Jenkins.get().checkPermission(hudson.security.Permission.CONFIGURE); + OkHttpClient okHttpClient = new OkHttpClient().newBuilder() .writeTimeout(2, TimeUnit.MINUTES) .readTimeout(60, TimeUnit.SECONDS) @@ -575,11 +607,14 @@ public FormValidation doValidateCredentials( return FormValidation.error("Unable to login with provided Client ID and Client Secret to " + endpoint); } } + catch(hudson.security.AccessDeniedException3 e) { + return FormValidation.error("User not authorized to check credentials."); + } catch(java.net.UnknownHostException e) { return FormValidation.error("Unknown host: " + endpoint); } catch(java.io.IOException e) { - return FormValidation.error("Unable to connect to the provided endpoint: " + endpoint); + return FormValidation.error("Unable to connect to the provided endpoint: " + endpoint + "(" + e.getLocalizedMessage() + ")"); } catch(Exception e) { return FormValidation.error("Error validating credentials: " + e.getLocalizedMessage()); From 8e0d0a1ab9dd05ec050ae8740f07be89b60328db Mon Sep 17 00:00:00 2001 From: Igor Matlin Date: Mon, 30 Sep 2024 14:22:21 -0500 Subject: [PATCH 2/3] Added empty endpoint check --- .../plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java b/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java index 11990c6..a4ce99a 100644 --- a/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java +++ b/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/ZDevUploadPlugin.java @@ -23,7 +23,6 @@ import hudson.tasks.Recorder; import hudson.util.FormValidation; import hudson.util.Secret; -import hudson.security.Permission; import jenkins.model.Jenkins; import jenkins.tasks.SimpleBuildStep; import net.sf.json.JSONObject; @@ -511,8 +510,10 @@ public String getDisplayName() { return "Upload build artifacts to zScan"; } - // TODO: Add server validation logic public FormValidation doCheckEndpoint(@QueryParameter String value) throws IOException, ServletException { + if (value.isBlank()) { + return FormValidation.error("Endpoint cannot be blank."); + } return FormValidation.ok(); } From b3f4e2037d1a8b1339505e0e5b683e2b21105935 Mon Sep 17 00:00:00 2001 From: Igor Matlin Date: Tue, 1 Oct 2024 14:43:43 -0500 Subject: [PATCH 3/3] API URL changes --- .../services/UploadPluginService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/services/UploadPluginService.java b/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/services/UploadPluginService.java index 6965b01..90721b8 100644 --- a/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/services/UploadPluginService.java +++ b/src/main/java/com/zimperium/plugins/zDevJenkinsUploadPlugin/services/UploadPluginService.java @@ -21,7 +21,7 @@ public interface UploadPluginService { @POST("api/auth/v1/api_keys/access") Call refreshAccess(@Body RefreshCredentials body); - @POST("api/zdev-upload/v1/uploads/build") + @POST("api/zdev-upload/public/v1/uploads/build") Call upload(@Header("Authorization") String clientSecret, @Body RequestBody body); @PUT("api/zdev-app/public/v1/apps/{appId}/upload") @@ -30,10 +30,10 @@ public interface UploadPluginService { @GET("api/auth/public/v1/teams") Call listTeams(@Header("Authorization") String clientSecret); - @GET("api/zdev-app/pub/v1/assessments/status") + @GET("api/zdev-app/public/v1/assessments/status") Call checkStatus(@Query("buildId") String buildId, @Header("Authorization") String clientSecret); - @GET("api/zdev-app/pub/v1/assessments/{assessmentId}/{report_format}") + @GET("api/zdev-app/public/v1/assessments/{assessmentId}/{report_format}") @Streaming Call downloadReport(@Path("assessmentId") String assessmentId, @Path("report_format") String reportFormat, @Header("Authorization") String clientSecret); }