Skip to content

Commit b4a6c1d

Browse files
committed
CET-19215 add secret scanning
1 parent 3041720 commit b4a6c1d

13 files changed

+621
-102
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>org.kohsuke</groupId>
44
<artifactId>cortexapps-github-api</artifactId>
5-
<version>1.326</version>
5+
<version>1.327</version>
66
<name>GitHub API for Java</name>
77
<url>https://github-api.kohsuke.org/</url>
88
<description>GitHub API for Java</description>

src/main/java/org/kohsuke/github/GHSecretScanningAlert.java

Lines changed: 74 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
import java.io.IOException;
77
import java.net.URL;
8+
import java.util.Arrays;
89
import java.util.Date;
10+
import java.util.List;
911

1012
/**
1113
* Secret scanning alert for a repository
@@ -18,16 +20,23 @@ public class GHSecretScanningAlert extends GHObject {
1820
private GHRepository owner;
1921
private long number;
2022
private String html_url;
23+
private String locations_url;
2124
private GHSecretScanningAlertState state;
2225
private String resolution;
2326
private String resolved_at;
2427
private GHUser resolved_by;
28+
private String secret_name;
2529
private String secret_type;
26-
private Secret secret;
27-
private String push_protection_bypassed;
30+
private String secret_type_display_name;
31+
private String secret;
32+
33+
private Boolean push_protection_bypassed;
2834
private GHUser push_protection_bypassed_by;
2935
private String push_protection_bypassed_at;
3036

37+
private String created_at;
38+
private String updated_at;
39+
3140
GHSecretScanningAlert wrap(GHRepository owner) {
3241
this.owner = owner;
3342
return this;
@@ -54,6 +63,11 @@ public long getId() {
5463
return getNumber();
5564
}
5665

66+
@Override
67+
public URL getHtmlUrl() throws IOException {
68+
return GitHubClient.parseURL(html_url);
69+
}
70+
5771
/**
5872
* State of alert
5973
*
@@ -105,11 +119,29 @@ public String getSecretType() {
105119
}
106120

107121
/**
108-
* Secret that was detected
122+
* Display name for tyype of secret that was detected
123+
*
124+
* @return the secret type display name
125+
*/
126+
public String getSecretTypeDisplayName() {
127+
return secret_type_display_name;
128+
}
129+
130+
/**
131+
* Secret name that was detected
109132
*
110-
* @return the secret
133+
* @return the secret name
111134
*/
112-
public Secret getSecret() {
135+
public String getSecretName() {
136+
return secret_name;
137+
}
138+
139+
/**
140+
* Secret value that was detected
141+
*
142+
* @return the secret value
143+
*/
144+
public String getSecret() {
113145
return secret;
114146
}
115147

@@ -118,8 +150,8 @@ public Secret getSecret() {
118150
*
119151
* @return true if push protection was bypassed, false otherwise
120152
*/
121-
public boolean isPushProtectionBypassed() {
122-
return push_protection_bypassed != null && !push_protection_bypassed.isEmpty();
153+
public Boolean isPushProtectionBypassed() {
154+
return push_protection_bypassed;
123155
}
124156

125157
/**
@@ -141,45 +173,43 @@ public Date getPushProtectionBypassedAt() {
141173
return GitHubClient.parseDate(push_protection_bypassed_at);
142174
}
143175

144-
@Override
145-
public URL getHtmlUrl() throws IOException {
146-
return GitHubClient.parseURL(html_url);
176+
/**
177+
* Gets created at.
178+
*
179+
* @return the created at
180+
*/
181+
public Date getCreatedAt() {
182+
return GitHubClient.parseDate(created_at);
183+
}
184+
185+
/**
186+
* Gets updated at.
187+
*
188+
* @return the updated at
189+
*/
190+
public Date getUpdatedAt() {
191+
return GitHubClient.parseDate(updated_at);
147192
}
148193

149194
/**
150-
* Secret details
151-
*/
152-
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API")
153-
public static class Secret {
154-
private String name;
155-
private String type;
156-
private String value;
157-
158-
/**
159-
* Name of the secret
160-
*
161-
* @return the name
162-
*/
163-
public String getName() {
164-
return name;
165-
}
166-
167-
/**
168-
* Type of the secret
169-
*
170-
* @return the type
171-
*/
172-
public String getType() {
173-
return type;
174-
}
175-
176-
/**
177-
* Value of the secret
178-
*
179-
* @return the value
180-
*/
181-
public String getValue() {
182-
return value;
183-
}
195+
* Gets locations url.
196+
*
197+
* @return the locations url
198+
*/
199+
public String getLocationsUrl() {
200+
return locations_url;
184201
}
202+
203+
/**
204+
* Gets locations.
205+
*
206+
* @return the locations array
207+
* @throws IOException
208+
* the io exception
209+
*/
210+
public List<GHSecretScanningAlertLocation> getLocations() throws IOException {
211+
return Arrays.asList(
212+
root().createRequest().withUrlPath(getLocationsUrl()).fetch(GHSecretScanningAlertLocation[].class));
213+
}
214+
185215
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.kohsuke.github;
2+
3+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4+
5+
/**
6+
* Code scanning alert for a repository
7+
*
8+
* <a href="https://docs.github.com/en/rest/reference/code-scanning"></a>
9+
*/
10+
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API")
11+
public class GHSecretScanningAlertLocation {
12+
private String type;
13+
private GHSecretScanningAlertLocationDetails details;
14+
15+
/**
16+
* Instantiates a new GH secret scanning alert location.
17+
*/
18+
public GHSecretScanningAlertLocation() {
19+
}
20+
21+
/**
22+
* The type of location.
23+
*
24+
* @return the type
25+
*/
26+
public String getType() {
27+
return type;
28+
}
29+
30+
/**
31+
* The details of the location.
32+
*
33+
* @return the details
34+
*/
35+
public GHSecretScanningAlertLocationDetails getDetails() {
36+
return details;
37+
}
38+
39+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.kohsuke.github;
2+
3+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4+
5+
/**
6+
* Code sc for a repository
7+
*
8+
* <a href="https://docs.github.com/en/rest/reference/code-scanning"></a>
9+
*/
10+
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API")
11+
public class GHSecretScanningAlertLocationDetails {
12+
private String path;
13+
14+
/**
15+
* Instantiates a new GH secret scanning alert location details.
16+
*/
17+
public GHSecretScanningAlertLocationDetails() {
18+
}
19+
20+
/**
21+
* The path to the file containing the secret.
22+
*
23+
* @return the path
24+
*/
25+
public String getPath() {
26+
return path;
27+
}
28+
}
Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package org.kohsuke.github;
22

3-
import org.junit.Assume;
43
import org.junit.Before;
54
import org.junit.Test;
65

7-
import java.io.IOException;
86
import java.util.List;
97

108
import static org.hamcrest.Matchers.*;
@@ -28,76 +26,54 @@ public class GHSecretScanningAlertTest extends AbstractGitHubWireMockTest {
2826
*/
2927
@Before
3028
public void setUp() throws Exception {
31-
repo = gitHub.getRepository("cortextests" + "/" + "test-code-scanning");
29+
repo = gitHub.getRepository("cortextests" + "/" + "secret-scanning");
3230
}
3331

3432
/**
35-
* Test list code scanning alert payload
33+
* Test list secret scanning alert payload
34+
*
35+
* @throws Exception
36+
* the exception
3637
*/
3738
@Test
38-
public void testListSecretScanningAlerts() {
39+
public void testListSecretScanningAlerts() throws Exception {
3940
// Arrange
4041

4142
// Act
4243
List<GHSecretScanningAlert> alerts = repo.listSecretScanningAlerts()._iterator(2).nextPage();
4344

4445
// Assert
45-
assertThat(alerts.size(), equalTo(2)); // This assertion is based on manual setup done on repo to
46-
// guarantee there are atleast 2 issues
46+
assertThat(alerts.size(), equalTo(2));
4747

48-
// GHCodeScanningAlert alert = codeQlAlerts.get(0);
49-
//
50-
// // Verify the code scanning tool details
51-
// assertThat(alert.getTool(), not((Object) null));
52-
// GHCodeScanningAlert.Tool tool = alert.getTool();
53-
// assertThat(tool.getName(), is("CodeQL"));
54-
// assertThat(tool.getVersion(), not((Object) null));
55-
//
56-
// // Verify that fields of the code scanning rule are non-null
57-
// assertThat(alert.getRule(), not((Object) null));
58-
// GHCodeScanningAlert.Rule rule = alert.getRule();
59-
// assertThat(rule.getId(), not((Object) null));
60-
// assertThat(rule.getName(), not((Object) null));
61-
// assertThat(rule.getSeverity(), not((Object) null));
62-
// assertThat(rule.getSecuritySeverityLevel(), not((Object) null));
63-
//
64-
// // Act - Search by filtering on alert status
65-
// List<GHCodeScanningAlert> openAlerts = repo.listCodeScanningAlerts(GHCodeScanningAlertState.OPEN)
66-
// ._iterator(2)
67-
// .nextPage(); // This assertion is based on manual setup done on repo to
68-
// // guarantee there are atleast 2 issues
69-
//
70-
// // Assert
71-
// assertThat(openAlerts.size(), equalTo(2));
72-
// GHCodeScanningAlert openAlert = openAlerts.get(0);
73-
// assertThat(openAlert.getState(), is(GHCodeScanningAlertState.OPEN));
74-
}
48+
GHSecretScanningAlert alert1 = alerts.get(0);
49+
assertThat(alert1.getNumber(), equalTo(2L));
50+
assertThat(alert1.getState(), equalTo(GHSecretScanningAlertState.OPEN));
51+
assertThat(alert1.getSecretType(), equalTo("npm_access_token"));
52+
assertThat(alert1.getSecret(), equalTo("secret1"));
53+
assertThat(alert1.isPushProtectionBypassed(), equalTo(false));
54+
assertThat(alert1.getResolvedBy(), nullValue());
55+
assertThat(alert1.getResolvedAt(), nullValue());
7556

76-
/**
77-
* Test get code scanning alert payload
78-
*
79-
* @throws IOException
80-
* Signals that an I/O exception has occurred.
81-
*/
82-
@Test
83-
public void testGetCodeScanningAlert() throws IOException {
84-
// Arrange
85-
List<GHCodeScanningAlert> dismissedAlerts = repo.listCodeScanningAlerts(GHCodeScanningAlertState.DISMISSED)
86-
._iterator(1)
87-
.nextPage();
88-
Assume.assumeThat(dismissedAlerts.size(), greaterThanOrEqualTo(1));
89-
GHCodeScanningAlert dismissedAlert = dismissedAlerts.get(0);
90-
long idOfDismissed = dismissedAlert.getId();
57+
List<GHSecretScanningAlertLocation> locations = alert1.getLocations();
58+
assertThat(locations.size(), equalTo(1));
59+
assertThat(locations.get(0).getType(), equalTo("commit"));
60+
assertThat(locations.get(0).getDetails().getPath(), equalTo("secrets/secrets1.env"));
9161

92-
// Act
93-
GHCodeScanningAlert result = repo.getCodeScanningAlert(idOfDismissed);
62+
GHSecretScanningAlert alert2 = alerts.get(1);
63+
assertThat(alert2.getNumber(), equalTo(1L));
64+
assertThat(alert2.getState(), equalTo(GHSecretScanningAlertState.OPEN));
65+
assertThat(alert2.getSecretType(), equalTo("stripe_test_secret_key"));
66+
assertThat(alert2.getSecret(), equalTo("secret2"));
67+
assertThat(alert2.isPushProtectionBypassed(), equalTo(true));
68+
assertThat(alert2.getPushProtectionBypassedBy().getLogin(), equalTo("lukbla"));
69+
assertThat(alert2.getPushProtectionBypassedAt(), equalTo(GitHubClient.parseDate("2025-05-05T15:32:05Z")));
70+
assertThat(alert2.getResolvedBy(), nullValue());
71+
assertThat(alert2.getResolvedAt(), nullValue());
9472

95-
// Assert
96-
assertThat(result, not((Object) null));
97-
assertThat(result.getId(), equalTo(idOfDismissed));
98-
assertThat(result.getDismissedReason(), equalTo(dismissedAlert.getDismissedReason()));
99-
assertThat(result.getDismissedAt(), equalTo(dismissedAlert.getDismissedAt()));
100-
assertThat(result.getDismissedBy().login, equalTo(dismissedAlert.getDismissedBy().login));
73+
List<GHSecretScanningAlertLocation> locations2 = alert2.getLocations();
74+
assertThat(locations2.size(), equalTo(1));
75+
assertThat(locations2.get(0).getType(), equalTo("commit"));
76+
assertThat(locations2.get(0).getDetails().getPath(), equalTo("secrets.env"));
10177
}
10278

10379
}

0 commit comments

Comments
 (0)