Skip to content

Commit

Permalink
fix: Update endpoint based on the code review comments
Browse files Browse the repository at this point in the history
Signed-off-by: Oleg Kopysov <o.kopysov@samsung.com>
  • Loading branch information
o-kopysov committed Jan 3, 2024
1 parent 6109148 commit 1d469cc
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 19 deletions.
9 changes: 1 addition & 8 deletions doc/lpvs-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,13 @@ paths:
schema:
$ref: '#/components/schemas/WebhookResponseForbidden'

/scan/{gitHubDomain}/{gitHubOrg}/{gitHubRepo}/{prNumber}:
/scan/{gitHubOrg}/{gitHubRepo}/{prNumber}:
post:
tags:
- GitHub Pull Request Single Scan API
summary: GitHub Pull Request Single Scan
description: Endpoint for performing a single scan operation based on GitHub organization, repository, and pull request number.
parameters:
- in: path
name: gitHubDomain
required: true
schema:
type: string
description: GitHub domain name
example: 'github.com'
- in: path
name: gitHubOrg
required: true
Expand Down
40 changes: 34 additions & 6 deletions src/main/java/com/lpvs/controller/GitHubController.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import javax.crypto.spec.SecretKeySpec;

/**
* Controller class for handling GitHub webhook events.
* Controller class for handling GitHub webhook events and single scan requests.
* This class is responsible for processing GitHub webhook payloads and triggering relevant actions.
*/
@RestController
Expand All @@ -48,12 +48,18 @@ public class GitHubController {
*/
private String GITHUB_SECRET;

/**
* Name of the GitHub API URL.
* It is set from the LPVS_GITHUB_API_URL environment variable or the application property.
*/
private String GITHUB_API_URL;

/**
* Initializes the GitHub secret from the LPVS_GITHUB_SECRET environment variable or the application property.
* Exits the application if the secret is not set.
*/
@PostConstruct
public void initializeGitHubSecret() {
public void initializeGitHubController() {
this.GITHUB_SECRET =
Optional.ofNullable(this.GITHUB_SECRET)
.filter(s -> !s.isEmpty())
Expand All @@ -64,6 +70,17 @@ public void initializeGitHubSecret() {
log.error("LPVS_GITHUB_SECRET (github.secret) is not set.");
exitHandler.exit(-1);
}

this.GITHUB_API_URL =
Optional.ofNullable(this.GITHUB_API_URL)
.filter(s -> !s.isEmpty())
.orElse(
Optional.ofNullable(System.getenv("LPVS_GITHUB_API_URL"))
.orElse(""));
if (this.GITHUB_API_URL.isEmpty()) {
log.info(
"LPVS_GITHUB_API_URL (github.api.url) is not set. Default domain \"github.com\" will be used.");
}
}

/**
Expand Down Expand Up @@ -175,7 +192,6 @@ public ResponseEntity<LPVSResponseWrapper> gitHubWebhooks(
* and pull request number provided in the path variables. The method validates
* the input parameters and performs necessary security checks.
*
* @param gitHubDomain The GitHub domain name.
* @param gitHubOrg The GitHub organization name. Must not be empty and should be a valid string.
* @param gitHubRepo The GitHub repository name. Must not be empty and should be a valid string.
* @param prNumber The pull request number. Must be a positive integer greater than or equal to 1.
Expand All @@ -184,10 +200,9 @@ public ResponseEntity<LPVSResponseWrapper> gitHubWebhooks(
* If there are validation errors or security issues, returns HTTP 403 FORBIDDEN.
*/
@RequestMapping(
value = "/scan/{gitHubDomain}/{gitHubOrg}/{gitHubRepo}/{prNumber}",
value = "/scan/{gitHubOrg}/{gitHubRepo}/{prNumber}",
method = RequestMethod.POST)
public ResponseEntity<LPVSResponseWrapper> gitHubSingleScan(
@PathVariable("gitHubDomain") @NotEmpty @Valid String gitHubDomain,
@PathVariable("gitHubOrg") @NotEmpty @Valid String gitHubOrg,
@PathVariable("gitHubRepo") @NotEmpty @Valid String gitHubRepo,
@PathVariable("prNumber") @Min(1) @Valid Integer prNumber)
Expand All @@ -202,10 +217,23 @@ public ResponseEntity<LPVSResponseWrapper> gitHubSingleScan(
}

// Validate and sanitize user inputs to prevent XSS attacks
gitHubDomain = HtmlUtils.htmlEscape(gitHubDomain);
gitHubOrg = HtmlUtils.htmlEscape(gitHubOrg);
gitHubRepo = HtmlUtils.htmlEscape(gitHubRepo);

String gitHubDomain;
if (!GITHUB_API_URL.isEmpty()) {
gitHubDomain =
GITHUB_API_URL
.trim()
.substring(
GITHUB_API_URL.indexOf("https://api.")
+ "https://api.".length())
.replaceAll("/", "");
} else {
gitHubDomain = "github.com";
}
log.debug("GitHub domain name is \"" + GITHUB_API_URL + "\"");

String prUrl =
"https://"
+ gitHubDomain
Expand Down
28 changes: 23 additions & 5 deletions src/test/java/com/lpvs/controller/GitHubControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public void wrongSecretTest() {
+ "}"
+ "}";
try {
gitHubController.initializeGitHubSecret();
gitHubController.initializeGitHubController();
boolean secret = gitHubController.wrongSecret(signature, json_to_test);
assertEquals(secret, false);
secret = gitHubController.wrongSecret(signature + " ", json_to_test);
Expand All @@ -164,7 +164,7 @@ public void wrongSecretTest() {
@Test
@SetEnvironmentVariable(key = "LPVS_GITHUB_SECRET", value = "LPVS")
public void testGitHubSingleScan_Success() throws Exception {
Method method = gitHubController.getClass().getDeclaredMethod("initializeGitHubSecret");
Method method = gitHubController.getClass().getDeclaredMethod("initializeGitHubController");
method.setAccessible(true);
method.invoke(gitHubController);
LPVSQueue mockScanConfig = new LPVSQueue();
Expand All @@ -173,7 +173,25 @@ public void testGitHubSingleScan_Success() throws Exception {
when(mocked_queueRepo.save(any())).thenReturn(mockScanConfig);
doNothing().when(mocked_instance_queueServ).addFirst(any());
ResponseEntity<LPVSResponseWrapper> responseEntity =
gitHubController.gitHubSingleScan("github.com", "org", "repo", 1);
gitHubController.gitHubSingleScan("org", "repo", 1);

assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
}

@Test
@SetEnvironmentVariable(key = "LPVS_GITHUB_SECRET", value = "LPVS")
@SetEnvironmentVariable(key = "LPVS_GITHUB_API_URL", value = "https://api.github.com")
public void testGitHubSingleScan_SuccessSetEnvironment() throws Exception {
Method method = gitHubController.getClass().getDeclaredMethod("initializeGitHubController");
method.setAccessible(true);
method.invoke(gitHubController);
LPVSQueue mockScanConfig = new LPVSQueue();
when(mocked_instance_ghServ.getInternalQueueByPullRequest(anyString()))
.thenReturn(mockScanConfig);
when(mocked_queueRepo.save(any())).thenReturn(mockScanConfig);
doNothing().when(mocked_instance_queueServ).addFirst(any());
ResponseEntity<LPVSResponseWrapper> responseEntity =
gitHubController.gitHubSingleScan("org", "repo", 1);

assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
}
Expand All @@ -183,7 +201,7 @@ public void testGitHubSingleScan_Success() throws Exception {
public void testGitHubSingleScan_InvalidSecret() throws Exception {
when(mocked_instance_ghServ.getInternalQueueByPullRequest(anyString())).thenReturn(null);
ResponseEntity<LPVSResponseWrapper> responseEntity =
gitHubController.gitHubSingleScan("", "org", "repo", 1);
gitHubController.gitHubSingleScan("org", "repo", 1);

assertEquals(HttpStatus.FORBIDDEN, responseEntity.getStatusCode());
}
Expand All @@ -194,7 +212,7 @@ public void testGitHubSingleScan_ConnectionError() throws Exception {
when(mocked_instance_ghServ.getInternalQueueByPullRequest(anyString()))
.thenThrow(new RuntimeException("Connection error"));
ResponseEntity<LPVSResponseWrapper> responseEntity =
gitHubController.gitHubSingleScan("github.com", "org", "repo", 1);
gitHubController.gitHubSingleScan("org", "repo", 1);

assertEquals(HttpStatus.FORBIDDEN, responseEntity.getStatusCode());
}
Expand Down

0 comments on commit 1d469cc

Please sign in to comment.